CMake conditional preprocessor define on code

╄→гoц情女王★ 提交于 2019-12-02 15:55:00

You can simplify things by avoiding creating the dummy targets and removing the config file. Instead, if you pass the requirements via the command line when you invoke CMake (or via the CMake GUI), you can run make only once.

For example, you could add the following to your 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()

By default, if you just run CMake, it will set the CMake variable WITH_FEATURE_A to ON which consequently adds USE_FEATURE_A as a preprocessor definition to the build. USE_FEATURE_B is undefined in the code.

This would be equivalent to doing #define USE_FEATURE_A in your code.


If you really need the equivalent of

#define USE_FEATURE_A 1
#define USE_FEATURE_B 0

then in your CMakeLists.txt you can do:

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()


To change these defaults from the command line, simply do (e.g.):

cmake . -DWITH_FEATURE_A=OFF -DWITH_FEATURE_B=ON
make

Once a variable has been set via the command line this way, it is cached and will remain unchanged until either it is overwritten with a different value on the command line, or you delete the CMakeCache.txt file in your build root.


Response to update:

As @Peter noted, you appear to be mixing up CMake variables (the WITH_FEATURE... ones) and the preprocessor definitions (the USE_FEATURE... ones). You can as suggested resolve all the dependencies between options first, then set the resulting preprocessor definitions, or in this case where the flow is quite straightforward, just do it all in one go:

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()


It sounds like you want to introduce relationships between your options. This will be easier if you separate the steps. First resolve the relationships, then set the C defines on the results. Remember that WITH_FEATURE_A is a cmake variable, and USE_FEATURE_A is C preprocessor define set with ADD_DEFINITIONS:

# Specify the inter-feature dependencies
if (WITH_FEATURE_A)
    # A requires B because <somereason>
    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()

I stumbled on this question and I figured I shared another option: TARGET_COMPILE_DEFINITIONS. You could have two targets in your CMakeLists.txt file, one per configuration, and have something like this

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)

This is tells cmake to add the preprocessors definitions of macros WITH_FEATURE_A and WITH_FEATURE_B (with the proper value), just like if you defined them in your *pp files. Then you can tell make which version to compile:

make versionA
make versionB
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!