预处理器定义不从CMake传播到Unix Makefile

时间:2015-01-07 04:58:43

标签: c++ makefile cmake c-preprocessor

我在使用-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及以下?

2 个答案:

答案 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}因为那是TOPPINGSSIDE

答案 1 :(得分:-2)

Is this the source of my problem?

你没有提供sscce,所以我们真的不知道。

http://sscce.org/