I'm migrating a makefile project to CMake. The person who wrote the makefile the first time had done a module for writing certain values in an include file.
There's a main config.h file that includes a config_in.h. The config.h file contains something like this:
#ifndef USE_FEATURE_A
#define USE_FEATURE_A 0
#endif
#ifndef USE_FEATURE_B
#define USE_FEATURE_B 0
#endif
In the makefile there's a fake target like with_feature_a
that writes in config_in.h
#define USE_FEATURE_A 1
In this way someone can type
make with_feature_a
make
to get the right build.
I want to replicate something like this using this codebase but using CMake. I tried a couple of approaches suggested on the net, but I didn't get it to work.
set_target_properties(with_feature_a PROPERTIES COMPILE_DEFINITIONS
"WITH_FEATURE_A=1"
)
This isn't working because if I run
make with_feature_a
I don't see with_feature_a
in the preprocessor command line.
The second attempt I made is to write a file directly with the content set to whatever I want, but I didn't understand how to connect the file()
command to my target.
I placed this in my CMakeLists.txt
file(WRITE
local/config_in.h
"#define WITH_FEATURE_A 1"
)
but this isn't executed everytime and I don't know how to set it to a single target.
Any help is appreciated. Thank you for reading all this stuff. Sorry for the long story :)
UPDATE
The solution provided here is a big enhacement on the road to solution. The problem is that is don't allow recursive definitions. I show an example:
in CMakeLists.txt I placed:
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()
in this case if I execute cmake with -DWITH_FEATURE_A=1 I'd love to see in the output:
WITH_FEATURE_A
WITH_FEATURE_B
WITH_FEATURE_D
actually this code print just
WITH_FEATURE_A
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:
By default, if you just run CMake, it will set the CMake variable
WITH_FEATURE_A
toON
which consequently addsUSE_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
then in your CMakeLists.txt you can do:
To change these defaults from the command line, simply do (e.g.):
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 (theUSE_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: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 thisThis is tells cmake to add the preprocessors definitions of macros
WITH_FEATURE_A
andWITH_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: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: