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 what source files will be affected by a particular compile definition. When compile definitions change, CMake assumes that all sources should be rebuilt.
A better approach is to use a configured header file, so when the 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 the resulted file's timestamp if its content wouldn't be changed. So, if you re-run cmake
without git commit
, nothing will be recompiled on the next build. Only re-running cmake
after git commit
will force the main.cpp
file (and only it) to be recompiled on the next build.
Another way is to use COMPILE_DEFINITIONS property on specific source files instead of a target-wide one (which is affected by the add_definition()
call):
set_property(SOURCE main.cpp APPEND
PROPERTY COMPILE_DEFINITIONS "-DCODE_VERSION=${GIT_CODE_VERSION}")
Changing this property via a cmake
call will be detected by the build system, so the next build will recompile main.cpp
and only it.
Unfortunately, this approach doesn't work as expected for Makefile generators: even if compile definitions are changed for a specific source, all sources (for the same target) will be rebuilt. This is a known limitation.