326

How do I define a preprocessor variable through CMake?

The equivalent code would be #define foo.

jww
  • 83,594
  • 69
  • 338
  • 732
Mythli
  • 5,127
  • 2
  • 21
  • 31

3 Answers3

430

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.

jww
  • 83,594
  • 69
  • 338
  • 732
ypnos
  • 45,954
  • 14
  • 88
  • 130
  • 4
    From the linked page: "Note This command has been superseded by alternatives: Use add_compile_definitions() to add preprocessor definitions." Maybe this answer needs an edit? – M.Herzkamp Jul 10 '18 at 09:01
  • 11
    In cmake 3.10.2, `add_compile_definitions` throws `CMake Error at CMakeLists.txt:6 (add_compile_definitions): Unknown CMake command "add_compile_definitions".`. Had to use `add_compile_options(-D )` instead. – code_dredd Jul 22 '18 at 09:25
  • @code_dredd In case of old CMake I would prefer `add_definitions`, see the previous version of my answer https://stackoverflow.com/revisions/9017635/2 – ypnos Jul 26 '18 at 21:47
  • Hi @ypnos, can you do this "from the outside"? For example, `cmake -D ADD_COMPILE_DEFINITION=DEBUG_CHESSBOARD ..`. – mannyglover Nov 26 '18 at 19:13
  • 2
    @mannyglover I don't think so, but you can set the compiler flags with -D, something along the lines of `cmake -D CMAKE_CXXFLAGS='-DDEBUG_CHESSBOARD'` (not tested) – ypnos Nov 27 '18 at 14:46
  • 2
    It's really new... in fact it's in More Modern CMake (> 3.11). A pain that it's so hard to know when a command was introduced. – Sandburg Apr 19 '19 at 07:19
  • Please specify `cmake --version`. Without it, it gets more confusing than helpful. – eigenfield Oct 11 '19 at 12:32
  • Does CMake define any default definitions to point the compilation is done using CMake? – Royi Feb 06 '20 at 17:41
  • @Royi I'm not sure if I get your question. CMake provides default flags for compiling Release, Debug, etc. build types on a specific platform. – ypnos Feb 06 '20 at 18:46
  • I meant like `MSVC` sets its Macros Definitions, does CMAKE propagate default definitions? – Royi Feb 06 '20 at 18:56
  • Yes, that's the ones I am talking about. You can find a list here: https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html – ypnos Feb 06 '20 at 20:30
  • 1
    @Sandburg You can open the link to the last documentation: `https://cmake.org/cmake/help/v3.17/command/add_compile_definitions.html#command:add_compile_definitions` and start changing the version number down until the page disappears. That would be the version where it not yet exists. In the next move you can go to the `Whats new` section to find a new command or feature. So its not so hard. – Andry May 22 '20 at 10:41
  • @Andry I agree with Sandburg, it really sucks to have to go to these great lengths. – ypnos May 22 '20 at 12:24
  • 1
    @ypnos Two underscores are required: e.g. `cmake -D CMAKE_CXX_FLAGS='-DDEBUG_CHESSBOARD'`. – user2023370 Mar 31 '21 at 14:29
  • 1
    Thanks @user2023370 Unfortunately I cannot edit my comment anymore. – ypnos Apr 01 '21 at 10:33
270

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.

erenon
  • 17,952
  • 2
  • 56
  • 83
Jim Hunziker
  • 11,545
  • 7
  • 50
  • 57
  • 2
    @JimHunziker How is `target_compile_definitions(my_target PRIVATE FOO=1)` different from `set_source_files_properties(foo.cpp PROPERTIES COMPILE_DEFINITIONS -DFOO=1)` ? – John Strood Jul 15 '16 at 21:00
  • 1
    @JohnStrood The difference is at scope level. `target_compile_definitions` sets the value for WHOLE executable/library, where as 'set_source_files_properties` sets the value for only the specified file. Latter command allows for files to compiled using a different language; i.e.: `set_source_files_properties(compile_me_as_objc.c PROPERTIES -x objective-c`. Note that `-x objective-c` here is a flag specific to GCC/Clang. – Julian Kirsch Apr 08 '20 at 22:48
26

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(....)
Leos313
  • 3,729
  • 4
  • 29
  • 61
  • 5
    Per the [documentation](https://cmake.org/cmake/help/latest/command/add_definitions.html), this solution is actually the older, more antiquated approach. The other answers offer the more modern solutions. – squareskittles Jul 23 '19 at 15:51
  • 2
    When I wrote the answer, I did try the other solution but none of them was working. – Leos313 Jul 24 '19 at 13:23
  • @squareskittles, any idea why the solution of the other answer did not work correctly? CMake give errors if I try them – Leos313 Aug 08 '19 at 11:20
  • 3
    If you are using CMake 3.3.2, as you indicated in your answer, you have to use `add_definitions()` or `target_compile_definitions()`. The more modern command, `add_compile_definitions()`, was not added until CMake 3.12. @Leos313 – squareskittles Aug 08 '19 at 12:13