330
votes

How do I define a preprocessor variable through CMake?

The equivalent code would be #define foo.

4

4 Answers

437
votes

For a long time, CMake had the add_definitions command for this purpose. However, recently the command has been superseded by a more fine grained approach (separate commands for compile definitions, include directories, and compiler options).

An example using the new add_compile_definitions:

add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION})
add_compile_definitions(WITH_OPENCV2)

Or:

add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION} WITH_OPENCV2)

The good part about this is that it circumvents the shabby trickery CMake has in place for add_definitions. CMake is such a shabby system, but they are finally finding some sanity.

Find more explanation on which commands to use for compiler flags here: https://cmake.org/cmake/help/latest/command/add_definitions.html

Likewise, you can do this per-target as explained in Jim Hunziker's answer.

274
votes

To do this for a specific target, you can do the following:

target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)

You should do this if you have more than one target that you're building and you don't want them all to use the same flags. Also see the official documentation on target_compile_definitions.

27
votes

The other solutions proposed on this page are useful for some versions of Cmake < 3.3.2. Here the solution for the version I am using (i.e., 3.3.2). Check the version of your Cmake by using $ cmake --version and pick the solution that fits your needs. The cmake documentation can be found on the official page.

With CMake version 3.3.2, in order to create

#define foo

I needed to use:

add_definitions(-Dfoo)   # <--------HERE THE NEW CMAKE LINE inside CMakeLists.txt
add_executable( ....)
target_link_libraries(....)

and, in order to have a preprocessor macro definition like this other one:

#define foo=5

the line is so modified:

add_definitions(-Dfoo=5)   # <--------HERE THE NEW CMAKE LINE inside CMakeLists.txt
add_executable( ....)
target_link_libraries(....)
1
votes

i'd like to recommend use target_*** operations instead of add_*** operations when your solution include many projects.