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

Nap*_*eis 3 git compilation cmake

假设我有时在 Linux 上使用 cmake 2.8 编译一段代码。

我更改了一个文件“my_changed_file”,运行 cmake,并且只构建了这个文件。到目前为止,一切都很好。

现在我想提交这个:

git add my_changed_file
git commit
Run Code Online (Sandbox Code Playgroud)

如果我再次运行 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}")
Run Code Online (Sandbox Code Playgroud)

但它只影响文件main.cpp

怎么了 ?

谢谢

Tsy*_*rev 5

CMake 不跟踪哪个源文件可能受到特定编译定义的影响。当编译定义更改时,CMake 假定所有源都应重新构建

更好的方法是使用配置的头文件。因此,当此文件的内容更改时,只有包含此文件的源才会被重新编译(直接或间接):

版本.h.in

#define CODE_VERSION @GIT_CODE_VERSION@
Run Code Online (Sandbox Code Playgroud)

主要.cpp

#include "version.h"
...
Run Code Online (Sandbox Code Playgroud)

CMakeLists.txt

# Calculate value of variable GIT_CODE_VERSION
...
configure_file("version.h.in" "version.h")
Run Code Online (Sandbox Code Playgroud)

好处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}")
Run Code Online (Sandbox Code Playgroud)

通过调用更改此属性cmake将被构建系统检测到,因此下一个构建将main.cpp仅重新编译它。

不幸的是,这种方法在 makefile 生成器的情况下不能按预期工作:即使更改特定源的编译定义,所有源(针对同一目标)都将被重建。这是已知的限制