假设我在linux上使用cmake 2.8编译代码。
我更改了一个文件" my_changed_file",运行cmake,只构建了这个文件。到目前为止一切都很好。
现在我要承诺:
git add my_changed_file
git commit
如果我再次运行cmake,我预计什么都不会发生。但我的所有文件都被重新编译,尽管我没有触及任何东西!当我执行ls -l时,时间戳似乎不受影响。
我确实有以下几行:
execute_process(
COMMAND git describe --abbrev=8 --dirty --always --tags
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_CODE_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions("-DCODE_VERSION=${GIT_CODE_VERSION}")
但它只影响文件main.cpp
发生了什么事?
感谢
答案 0 :(得分:4)
CMake不跟踪,哪个源文件可能受特定编译定义的影响。当编译定义更改时,CMake假定应重建所有来源。
更好的方法是使用配置的头文件。因此,当更改此文件的内容时,将仅重新编译包含此文件(直接或间接)的那些源:
<强> version.h.in 强>:
#define CODE_VERSION @GIT_CODE_VERSION@
<强>的main.cpp 强>:
#include "version.h"
...
<强>的CMakeLists.txt 强>:
# Calculate value of variable GIT_CODE_VERSION
...
configure_file("version.h.in" "version.h")
configure_file
的好处是它不会更新结果文件的时间戳,如果它的内容不会被更改。因此,如果您在没有cmake
的情况下重新运行git commit
,则下次构建时不会重新编译任何内容。只有在cmake
之后重新运行git commit
才会强制main.cpp
文件(并且只有它)在下一次构建时重新编译。
另一种方法是在特定源文件上使用COMPILE_DEFINITIONS属性而不是目标范围的文件(受add_definition()
调用影响):
set_property(SOURCE main.cpp APPEND
PROPERTY COMPILE_DEFINITIONS "-DCODE_VERSION=${GIT_CODE_VERSION}")
构建系统将检测到通过cmake
调用更改此属性,因此下一个构建将重新编译main.cpp
并且仅重新编译它。
不幸的是,在makefile生成器的情况下,这种方法不能正常工作:即使针对特定源更改了编译定义,也将重建所有源(针对相同目标)。这是known limitation。