为什么cmake在git commit之后编译所有内容

时间:2015-11-30 13:23:00

标签: git compilation cmake

假设我在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

发生了什么事?

感谢

1 个答案:

答案 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