为什么cmake编译git commit后的一切 [英] why does cmake compiles everything after git commit

查看:1303
本文介绍了为什么cmake编译git commit后的一切的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个代码编译在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



发生了什么?



感谢

解决方案

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



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



version.h.in

  #define CODE_VERSION @ GIT_CODE_VERSION @ 

main.cpp

  #include version.h
...

CMakeLists.txt

 #计算变量GIT_CODE_VERSION的值
...
configure_file(version.h。 inversion.h)

configure_file 是它不会更新结果文件的时间戳,如果其内容不会更改。所以,如果你重新运行 cmake 没有 git commit ,没有什么将重新编译下次构建。只有在之后重新运行 cmake 才会强制 main.cpp






另一种方法是使用 COMPILE_DEFINITIONS 属性在特定源文件上,而不是目标范围(这受到 add_definition() call):

  set_property(SOURCE main.cpp APPEND 
PROPERTY COMPILE_DEFINITIONS-DCODE_VERSION = $ {GIT_CODE_VERSION})

通过 cmake 调用将被构建系统检测到,所以下一个build将重新编译 main.cpp ,只有它。

$ b不幸的是,这种方法不能像makefile生成器那样正常工作:即使针对特定源更改了编译定义,所有源(对于同一目标)也将被重建。这是已知限制


Lets say I have a code compiling at some time with cmake 2.8 on linux.

I change a file "my_changed_file", run cmake, and only this one file is built. So far so good.

Now i want to commit this:

git add my_changed_file
git commit

If I run cmake again, i'd expect nothing happens. But all my files are recompiled, despite I didn't touched anything! The timestamp appears to be untouched when I do ls -l.

I do have these lines:

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}")

But it only affect the file main.cpp

What is happening ?

thanks

解决方案

CMake doesn't track, which source file can be affected by particular compile definition. When compile definitions changes, CMake assumes that all sources should be rebuilt.

Better approach is to use configured header file. So, when content of this file is changed, only those sources will be recompiled which includes this file(directly or indirectly):

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")

Nice thing with configure_file is that it doesn't update resulted file's timestamp if its content wouldn't be changed. So, if you rerun cmake without git commit, nothing will be recompiled on next build. Only rerunning cmake after git commit will force main.cpp file(and only it) to be recompiled on next build.


Another way is to use COMPILE_DEFINITIONS property on specific source files instead of target-wide one (which is affected by add_definition() call):

set_property(SOURCE main.cpp APPEND
    PROPERTY COMPILE_DEFINITIONS "-DCODE_VERSION=${GIT_CODE_VERSION}")

Changing this property via cmake call will be detected by build system, so next build will recompile main.cpp and only it.

Unfortunately, this approach doesn't work as expected in case of makefile generators: even if compile definitions are changed for specific source, all sources (for same target) will be rebuilt. This is known limitation.

这篇关于为什么cmake编译git commit后的一切的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆