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.