CMake条件预处理器定义代码

我正在将一个makefile项目迁移到CMake。 第一次编写makefile的人已经完成了一个用于在include文件中写入某些值的模块。

有一个主config.h文件,其中包含config_in.h。 config.h文件包含以下内容:

#ifndef USE_FEATURE_A #define USE_FEATURE_A 0 #endif #ifndef USE_FEATURE_B #define USE_FEATURE_B 0 #endif 

在makefile中有一个假目标,如with_feature_a ,它在config_in.h中写入

 #define USE_FEATURE_A 1 

通过这种方式,有人可以打字

 make with_feature_a make 

获得正确的构建。

我想使用这个代码库但使用CMake来复制这样的东西。 我在网上尝试了几种方法,但我没有让它发挥作用。

 set_target_properties(with_feature_a PROPERTIES COMPILE_DEFINITIONS "WITH_FEATURE_A=1" ) 

这不起作用,因为如果我跑

 make with_feature_a 

我没有在预处理器命令行中看到with_feature_a

我做的第二次尝试是直接用内容集写一个文件到我想要的东西,但我不明白如何将file()命令连接到我的目标。

我把它放在我的CMakeLists.txt中

 file(WRITE local/config_in.h "#define WITH_FEATURE_A 1" ) 

但这并不是每次都执行,我不知道如何将其设置为单个目标。

任何帮助表示赞赏。 感谢您阅读所有这些内容。 对不起长话:)

UPDATE

这里提供的解决方案是解决问题之路上的一大亮点。 问题是不允许递归定义。 我举了一个例子:

在CMakeLists.txt我放置:

 if (WITH_FEATURE_A) MESSAGE(STATUS "WITH_FEATURE_A") add_definitions(-DUSE_FEATURE_A=1) add_definitions(-DWITH_FEABURE_B=1) endif() if (WITH_FEABURE_B) MESSAGE(STATUS "WITH_FEATURE_B") add_definitions(-DUSE_FEATURE_D=1) endif() if (WITH_FEABURE_C) MESSAGE(STATUS "WITH_FEATURE_C") add_definitions(-DUSE_FEATURE_D=1) endif() if (WITH_FEABURE_D) MESSAGE(STATUS "WITH_FEATURE_D") endif() 

在这种情况下,如果我用-DWITH_FEATURE_A = 1执行cmake,我很乐意在输出中看到:

 WITH_FEATURE_A WITH_FEATURE_B WITH_FEATURE_D 

实际上这段代码打印出来

 WITH_FEATURE_A 

您可以通过避免创建虚拟目标并删除配置文件来简化操作。 相反,如果在调用CMake(或通过CMake GUI)时通过命令行传递需求,则只能运行一次make。

例如,您可以将以下内容添加到CMakeLists.txt:

 option(WITH_FEATURE_A "Option description" ON) option(WITH_FEATURE_B "Option description" OFF) if(WITH_FEATURE_A) add_definitions(-DUSE_FEATURE_A) endif() if(WITH_FEATURE_B) add_definitions(-DUSE_FEATURE_B) endif() 

默认情况下,如果您只运行CMake,它会将CMake变量WITH_FEATURE_A设置为ON ,从而将USE_FEATURE_A作为预处理器定义添加到构建中。 USE_FEATURE_B中未定义USE_FEATURE_B

这相当于在代码中执行#define USE_FEATURE_A

如果你真的需要相当于

 #define USE_FEATURE_A 1 #define USE_FEATURE_B 0 

然后在你的CMakeLists.txt中你可以做到:

 option(WITH_FEATURE_A "Option description" ON) option(WITH_FEATURE_B "Option description" OFF) if(WITH_FEATURE_A) add_definitions(-DUSE_FEATURE_A=1) else() add_definitions(-DUSE_FEATURE_A=0) endif() if(WITH_FEATURE_B) add_definitions(-DUSE_FEATURE_B=1) else() add_definitions(-DUSE_FEATURE_B=0) endif() 

要从命令行更改这些默认值,只需执行(例如):

 cmake . -DWITH_FEATURE_A=OFF -DWITH_FEATURE_B=ON make 

一旦通过命令行以这种方式设置了变量,它就会被缓存并保持不变,直到它被命令行上的不同值覆盖,或者删除构建根目录中的CMakeCache.txt文件。

对更新的回应:

正如@Peter所指出的那样,你似乎混淆了CMake变量( WITH_FEATURE... )和预处理器定义( USE_FEATURE... )。 您可以按照建议首先解析选项之间的所有依赖关系,然后设置生成的预处理器定义,或者在这种情况下,流程非常简单,只需一次完成即可:

 if(WITH_FEATURE_A) message(STATUS "WITH_FEATURE_A") add_definitions(-DUSE_FEATURE_A=1) set(WITH_FEATURE_B ON) endif() if(WITH_FEATURE_B) message(STATUS "WITH_FEATURE_B") add_definitions(-DUSE_FEATURE_B=1) set(WITH_FEATURE_D ON) endif() if(WITH_FEATURE_C) message(STATUS "WITH_FEATURE_C") add_definitions(-DUSE_FEATURE_C=1) set(WITH_FEATURE_D ON) endif() if(WITH_FEATURE_D) message(STATUS "WITH_FEATURE_D") add_definitions(-DUSE_FEATURE_D=1) endif() 

听起来你想介绍你的选择之间的关系。 如果您分开步骤,这将更容易。 首先解决关系,然后在结果上设置C定义。 请记住,WITH_FEATURE_A是一个cmake变量,USE_FEATURE_A是使用ADD_DEFINITIONS的C预处理器定义集:

 # Specify the inter-feature dependencies if (WITH_FEATURE_A) # A requires B because  set(WITH_FEATURE_B ON) endif() if (WITH_FEATURE_B) set(WITH_FEATURE_D ON) endif() if (WITH_FEATURE_C) set(WITH_FEATURE_D ON) endif() # Now generate the C defines for passing the options to the compiler if (WITH_FEATURE_A) MESSAGE(STATUS "WITH_FEATURE_A") add_definitions(-DUSE_FEATURE_A=1) endif() if (WITH_FEATURE_B) MESSAGE(STATUS "WITH_FEATURE_B") add_definitions(-DUSE_FEATURE_B=1) endif() if (WITH_FEATURE_C) MESSAGE(STATUS "WITH_FEATURE_C") add_definitions(-DUSE_FEATURE_C=1) endif() if (WITH_FEATURE_D) MESSAGE(STATUS "WITH_FEATURE_D") add_definitions(-DUSE_FEATURE_D=1) endif() 

我偶然发现了这个问题,我想我分享了另一种选择: TARGET_COMPILE_DEFINITIONS 。 您可以在CMakeLists.txt文件中有两个目标,每个配置一个,并且具有类似的function

 ADD_EXECUTABLE (versionA, ...) TARGET_COMPILE_DEFINITIONS (versionA, PUBLIC -DWITH_FEATURE_A=1 -DWITH_FEATURE_B=0) ADD_EXECUTABLE (versionB, ...) TARGET_COMPILE_DEFINITIONS (versionB, PUBLIC -DWITH_FEATURE_A=0 -DWITH_FEATURE_B=1) 

这告诉cmake添加宏的WITH_FEATURE_AWITH_FEATURE_B (具有正确的值)的预处理器定义,就像在* pp文件中定义它们一样。 然后你可以告诉make编译哪个版本:

 make versionA make versionB