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:
main.cpp:
CMakeLists.txt:
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 reruncmake
withoutgit commit
, nothing will be recompiled on next build. Only rerunningcmake
aftergit commit
will forcemain.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):Changing this property via
cmake
call will be detected by build system, so next build will recompilemain.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.