我在使用-D或add_definitions()传递给CMake时遇到任何问题,以便在编译CMake创建的Makefile时显示。
(使用一个简单的例子总结)。
在顶层,我有一个build.sh脚本,它以:
开头cmake \
-G "Unix Makefiles" \
-DPIZZA=1 \
-DCMAKE_VERBOSE_MAKEFILE=1 \
$TOPPINGS \
../../src
$ TOPPINGS之前被声明为-DTOPPINGS = ALL。我已经验证它已正确传递给上述内容。基于TOPPINGS的值,我的CmakeLists.txt使用add_definitions()添加了一些预处理器定义。为了便于讨论,我们会说:
add_definitions( -DCHEESE=Mozz )
add_definitions( -DMEAT=Meat )
这没有问题。在CMakeCache.txt中,它们出现:
//No help, variable specified on the command line.
CHEESE:UNINITIALIZED=Mozz
我在CMakeLists.txt中使用message()验证了我的逻辑。
但是当我们使用生成的Makefile构建时,这些都没有定义。既不是在调用Cmake时指定的那些,也不是通过add_definitions添加的那些。
在查看add_definitions的文档时,我看到:
为编译器命令行添加定义 当前目录及以下。
这是我的问题的根源吗?即:仅为我正在运行CMake的目录添加定义,或者是为../../src(及以下)中的所有内容添加定义,问题出在其他地方?如果是这种情况,有没有办法手动指定这些定义应该适用于../../src及以下?
答案 0 :(得分:9)
正如@steveire所说,SSCCE会有所帮助。尽管如此,此问题很可能与您add_subdirectory
来电add_definitions
来电的订单/位置有关。
首先,为了清楚起见,CMake设置的变量与预处理器定义没有任何关系,除非您明确地将它们绑定在一起。我的意思是,如果你打电话
cmake -DTOPPINGS=Haggis .
或在您的CMakeLists.txt中有set(TOPPINGS Haggis)
,预处理器将看不到任何Haggis
,除非您还有类似
add_definitions(-DTOPPINGS=${TOPPINGS})
好的,举个例子,请考虑以下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)
在这种情况下,子目录“One”的CMakeLists.txt中定义的目标不会将TOPPINGS
作为PP定义,因为add_subdirectory(One)
位于add_definitions
之前1}}打电话。如果“一个”使用add_definitions
设置任何PP定义,它们将不会传播回顶级或“两个”。
但是,由于add_subdirectory(Two)
在<{em> add_definitions
调用之后来了,因此在其中定义的所有目标(及其任何子目录)将具有{ {1}}作为PP定义。
最后,目标TOPPINGS
也会MyTestExe
作为PP定义,无论TOPPINGS
来电与add_executable
来电有何关联。
使用target_compile_definitions
代替add_definitions
可以避免一些混淆。这样可以更精细地控制PP定义;我们不希望哈吉斯到处泄漏!
假设我们从CMakeLists.txt中删除了行add_definitions
。现在在子目录“Two”的CMakeLists.txt中,我们可以这样做:
add_definitions(-DTOPPINGS=Haggis)
这会导致PP定义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)
和 TOPPINGS
应用于单个目标库SIDE
,无论我们在其中定义了多少其他目标相同的CMakeList.txt。
由于Two
被声明为TOPPINGS
,因此会导致CMake将其应用于链接PUBLIC
的任何其他目标。我们在调用Two
时在顶级CMakeLists.txt中执行此操作,因此target_link_libraries(MyTestExe One Two)
也将MyTestExe
作为PP定义,但它不会{{1}因为那是TOPPINGS
到SIDE
。
答案 1 :(得分:-2)