在编译 CMake 创建的 Makefile 时,我无法使用 -D 或 add_definitions() 显示传递给 CMake 的任何内容。
(使用简单示例进行总结)。
在顶层,我有一个 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 的文档时,我看到:
Adds definitions to the compiler command line for sources in the current directory and below.
这是我问题的根源吗?即:仅为我运行 CMake 的目录添加定义,或者是否为 ../../src(及以下)中的所有内容添加定义,而问题出在其他地方?如果是这种情况,是否有办法手动指定这些定义应适用于 ../../src 及以下?
最佳答案
正如@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
调用之前。如果“One”使用 add_definitions
设置任何 PP 定义,它们将不会传播回顶层或“Two”。
但是,由于 add_subdirectory(Two)
在 add_definitions
调用之后,所有在其中定义的目标(及其任何子目录)< em>将将 TOPPINGS
作为 PP 定义。
最后,目标 MyTestExe
也将具有 TOPPINGS
作为 PP 定义,无论 add_executable
调用与 add_definitions
调用。
使用 target_compile_definitions
可能会避免一些混淆。而不是 add_definitions
。这为 PP 定义提供了更细粒度的控制;我们不想羊哈希漏得到处都是!
假设我们从 CMakeLists.txt 中删除 add_definitions(-DTOPPINGS=Haggis)
行。现在在子目录“Two”的 CMakeLists.txt 中,我们可以:
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)
这会导致 PP 定义 TOPPINGS
和 SIDE
应用于单个目标库 Two
,无论我们可以在同一个 CMakeList.txt 中定义多少个其他目标。
由于 TOPPINGS
被声明为 PUBLIC
,它导致 CMake 将其应用于链接 Two
的任何其他目标。当我们调用 target_link_libraries(MyTestExe One Two)
时,我们在顶级 CMakeLists.txt 中执行此操作,因此 MyTestExe
也将具有 TOPPINGS
作为 PP 定义,但它不会有 SIDE
,因为它是 PRIVATE
到 Two
。
关于c++ - 预处理器定义不会从 CMake 传播到 Unix Makefile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27812662/