[ad_1]
I am migrating a large legacy codebase from autotools to CMake, and we have some behaviour that we’d like to preserve. However, my naive initial reimplementation of the build system in CMake has resulted in the entire project being rebuilt every time cmake is invoked. I believe this is happening because of the way that include_directories
is being used, along with a lack of cache variables, but I’d like to double-check here if a better solution exists than the one I’m thinking of.
The original reimplementation was done in CMake 2.8 (corporate slowness, hooray), but I’ve managed to get hold of 3.14, so I’ve tried to tidy it up a little. I’d like to use some more modern features if possible.
Legacy Autotools setup
conf.sh
:
#!/bin/sh
DIR_=`dirname $0`
${DIR_}/configure \
--some-flag=yes \
--some-other-flag=ok \
--some-dependency=/home/deps/dependencyOne \
--some-other-dependency=/home/deps/dependencyTwo \
"$@"
exit %?
configure.in contains the decoding logic to set these dependencies up:
AC_ARG_ENABLE(some-dependency),
[
if test "x$some_dependency" != "xno" ; then
if test -d "${enableval}"; then
DEPONE_DIR=$enableval
else
AC_MSG_ERROR("Must specify dependencyOne directory!")
fi
DEPONE_INCLUDES="-I$DEPONE_DIR/include"
DEPONE_LDFLAGS="-L$DEPONE_DIR/lib -ldepone"
#etcetera
fi
]
Running ./conf.sh
from the desired build
directory generates the Makefiles and such. After this, we run make
. If we change a source file, it only rebuilds that source and its dependees (dependors? Is there a word for this). If we change a Makefile.am, again, it’s smart enough to not rebuild everything.
Current CMakeLists.txt setup:
We want to be able to switch dependencies on and off in the build, and the way we do this is through this configure script. I originally recreated the existing setup closely in CMake as shown below:
Config script:
#!/bin/bash
libs=(
-Dsome-dependency=/home/deps/dependencyOne
-Dsome-other-dependency=/home/deps/dependencyTwo
)
args=(
${libs[@]}
-Dsome-flag=yes
-Dsome-other-flag=ok
)
cmake "${args[@]}"
Root CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
PROJECT(myProject)
#some language-specific setup (standard etc)
if(some-dependency)
link_directories(${some-dependency}/lib)
include_directories(${some-dependency}/include)
endif()
if(some-other-dependency)
link_directories(${some-other-dependency}/lib)
include_directories(${some-other-dependency}/include)
endif()
I noticed that if I switch off a line in the config script, running cmake will have cached the value and still act as if it was enabled, which I don’t want. So I committed this cardinal sin:
End of root CMakeLists.txt:
unset(some-dependency CACHE)
unset(some-other-dependency CACHE)
Now, every time I run the configure script (and by extension cmake
), it rebuilds everything when I run make
. My guess is that this happens because of include_directories
being reset every time, resulting in everything being marked as dirty.
My supposed solution to this is twofold:
- Use
target_include_directories
- Check if the value supplied from the config script via -D matches an existing CACHE entry, and if so, do nothing. I don’t think this will work, given -D sets a variable in cache.
Is there a better way of getting this done? I get the impression that my attempt at it is fairly naive and simplistic, and if a better solution exists, I’d really love to know about it.
[ad_2]