Reputation: 7015
I'm having trouble getting anything I pass to CMake using -D or add_definitions() to show up when compiling the Makefiles that CMake creates.
(Summarized using a trivial example).
At the top level, I have a build.sh script, that starts with:
cmake \
-G "Unix Makefiles" \
-DPIZZA=1 \
-DCMAKE_VERBOSE_MAKEFILE=1 \
$TOPPINGS \
../../src
$TOPPINGS is declared as -DTOPPINGS=ALL previously. I've verified it's correctly getting passed to the above. Based on the value of TOPPINGS, my CmakeLists.txt adds some more preprocessor definitions using add_definitions(). For the sake of discussion we'll say it does:
add_definitions( -DCHEESE=Mozz )
add_definitions( -DMEAT=Meat )
This generates without a problem. In the CMakeCache.txt they appear:
//No help, variable specified on the command line.
CHEESE:UNINITIALIZED=Mozz
And I've verified my logic using message() in CMakeLists.txt.
But when we build using generated Makefiles, these are not defined. Neither the ones specified on the invocation to Cmake nor those added through add_definitions.
In looking at the documentation for add_definitions I see:
Adds definitions to the compiler command line for sources in the current directory and below.
Is this the source of my problem? I.e.: The definitions are only being added for the directory I'm running CMake from, or is it being added for everything in ../../src (and below) and the problem is elsewhere? If this is the case, is there a way to manually specify these definitions should apply to ../../src and below?
Upvotes: 3
Views: 5300
Reputation: 78458
As @steveire mentioned, an SSCCE would be helpful. Nonetheless, there's a good chance that the problem is related to the order/location of your add_subdirectory
calls in relation to the add_definitions
calls.
First, just to be clear, variables set by CMake don't have any bearing on preprocessor definitions unless you explicitly tie them together. What I mean is that if you call
cmake -DTOPPINGS=Haggis .
or have set(TOPPINGS Haggis)
in your CMakeLists.txt, the preprocessor won't see any Haggis
unless you also have something like
add_definitions(-DTOPPINGS=${TOPPINGS})
OK, so for an example, consider the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.1)
project(MyTest)
add_executable(MyTestExe main.cpp)
add_subdirectory(One)
add_definitions(-DTOPPINGS=Haggis)
add_subdirectory(Two)
target_link_libraries(MyTestExe One Two)
In this case, targets defined in the CMakeLists.txt of subdir "One" won't have TOPPINGS
as a PP definition since add_subdirectory(One)
comes before the add_definitions
call. If "One" sets any PP definitions using add_definitions
, they won't propagate back up to the top-level or to "Two".
However, since add_subdirectory(Two)
comes after the add_definitions
call, all targets defined in there (and any of its subdirs) will have TOPPINGS
as a PP definition.
Finally, the target MyTestExe
will also have TOPPINGS
as a PP definition, regardless of where the add_executable
call comes in relation to the add_definitions
call.
Some of this confusion can possibly be avoided by using target_compile_definitions
instead of add_definitions
. This gives much more fine-grained control of PP definitions; we don't want haggis leaking everywhere!
Say we remove the line add_definitions(-DTOPPINGS=Haggis)
from the CMakeLists.txt. Now in the CMakeLists.txt of subdir "Two", we can do:
add_library(Two two.hpp two.cpp)
# Note, we don't need to use -D here, but it doesn't matter if you do
target_compile_definitions(Two PUBLIC TOPPINGS=Haggis PRIVATE SIDE=Whisky)
This causes the PP definitions TOPPINGS
and SIDE
to be applied to the single target library Two
, regardless of how many other targets we may define in the same CMakeList.txt.
Since TOPPINGS
is declared as PUBLIC
, it causes CMake to apply it to any other target which links Two
. We're doing that in the top-level CMakeLists.txt when we call target_link_libraries(MyTestExe One Two)
, so MyTestExe
will also have TOPPINGS
as a PP definition, but it won't have SIDE
since that's PRIVATE
to Two
.
Upvotes: 12