65

I try to set a preprocessor macro in the command line of CMake. I've tried:

set generator="Visual Studio 8 2005"
set params=-D MY_MACRO=1
cmake.exe -G %generator% %params% ..\some_project

but it's neither defined when I compile nor can I find the name MY_MACRO in the files generated by CMake at all, except for CMakeCache.txt where it's present in the form:

MY_MACRO:UNINITIALIZED=1

How can I do it?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • 2
    If you solved this by now I would be interested in the solution – Tim Meyer Mar 02 '12 at 10:03
  • 1
    @ybungalobill: You can't inject macros from the commandline, you can only modify existing macros that are defined in CMakeLists.txt. Also, *set params=-D MY_MACRO=1* should be *set params=-DMY_MACRO=1* – NeoH4x0r Jan 08 '18 at 08:57
  • @TimMeyer: yes, see my answer below. – Yakov Galka Apr 07 '19 at 22:45
  • @ybungalobill I was interested 7 years ago ;) Thanks for providing an answer anyway, I'm sure it will help many others. – Tim Meyer Apr 08 '19 at 20:23

4 Answers4

40

A good alternative would be to define a cmake option:

OPTION(DEFINE_MACRO "Option description" ON) # Enabled by default

Followed by a condition:

IF(DEFINE_MACRO)
    ADD_DEFINITIONS(-DMACRO)
ENDIF(DEFINE_MACRO)

Then you can turn that option ON/OFF via command line with cmake using the -D flag. Example:

cmake -DDEFINE_MACRO=OFF ..

To make sure the compiler is receiving the definition right, you can call make in verbose mode and check for the macro being defined or not:

make VERBOSE=1

This is a good solution also because make will recompile your code when any of cmake options changes.

freitass
  • 6,542
  • 5
  • 40
  • 44
  • 40
    This requires modifications of the CMakeLists, so it's not a solution (-1). – Yakov Galka Nov 18 '16 at 07:17
  • 3
    @YakovGalka not entierly true, he suggest to change the CmakeLists.txt prior, so the macro can be defined/undefined at subsequent builds. Agree it doesn't provide mose flexiblity, but for most use-cases it is what people need. – Tomer W Jan 23 '21 at 16:03
  • 1
    One can use `add_compile_definitions` instead of `add_definitions`. See [define preprocessor macro through cmake](https://stackoverflow.com/questions/9017573/define-preprocessor-macro-through-cmake). – Burak Apr 26 '21 at 01:04
22

Try this: -D CMAKE_CXX_FLAGS=/DMY_MACRO=1

SlavaNov
  • 2,447
  • 1
  • 18
  • 26
  • 10
    It half works indeed. It overwrites the value of `CMAKE_CXX_FLAGS`. I've tried `-D CMAKE_CXX_FLAGS="/DMY_MACRO=1 ${CMAKE_CXX_FLAGS}"` but `${CMAKE_CXX_FLAGS}` is not get expanded. Anyone knows how to fix this? – Yakov Galka Dec 19 '11 at 16:58
  • 1
    Double-quoted strings on the command line will be expanded by bash. Since you have no environment variable named CMAKE_CXX_FLAGS, bash expands it to "", before cmake even sees it. Use single quotes instead. – Tolli Jul 27 '15 at 15:36
  • 1
    @Tolli that doesn't seem to work either. It prevents bash from expanding the variable, but cmake doesn't expand it either. It passes the literal value `/DMY_MACRO=1 ${CMAKE_CXX_FLAGS}` directly to the compiler. – pavon Mar 16 '16 at 18:12
  • 1
    @Tolli: I didn't run it on bash. Not all the world is bash. – Yakov Galka Nov 18 '16 at 07:15
  • 5
    ` -DCMAKE_CXX_FLAGS:="-D_GLIBCXX_USE_CXX11_ABI=0 -DTSI_OPENSSL_ALPN_SUPPORT=0"` seems work for me – wcy Apr 21 '17 at 10:09
21

The motivation behind the question was to batch build 3rd party libraries, which is why I wanted to avoid modifying CMakeLists. So years later, even though I don't need that anymore, I figured out that it's easily achievable by means external to CMake:

  • Invoke CMake as usual, no special flags.

  • Then:

    • With MSVC: The compiler reads the CL environment variable to get extra command line arguments. So

        set CL=/DMY_MACRO=1 %CL%
      

      then invoke MSBuild to do its job.

    • With Makefiles: The generated makefiles use the CFLAGS and CXX_FLAGS variables as makefiles are expected to do. So the build can be started by

        make CXX_FLAGS=-DMY_MACRO=1
      

      or by setting the corresponding environment variables.

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • 2
    This is a good workaround for command line building but I'd also want users to be able to open the generated solution file with the IDE in which case this wouldn't work. It's a pity that even in 2020 there's no way to add to CMAKE_CXX_FLAGS rather than specifying (overwriting) them. – wonko realtime Sep 21 '20 at 08:20
  • 2
    After stumbling on this problem, I found that `cmake -E env CXXFLAGS="-DMY_MACRO" cmake SourcePath` works in my case (src: https://stackoverflow.com/a/44357387/1666181). Not sure though if this would override completely too. – lippertsjan Feb 15 '21 at 19:27
-8

Unless you have a good reason not to, you should use ADD_DEFINITIONS(<name>=<value>[, ...]).

Just add the following line to your CMakeLists.txt:

ADD_DEFINITIONS("MY_MACRO=1")

CMake will take care of the syntax of the switches (be it -D<name>=<value>, or /D<name>=<value>).

hiobs
  • 618
  • 1
  • 6
  • 20
  • 24
    modifying CMakeLists.txt doesn't count as a command-line solution. And yes, I have a good reason to not do this. I have to automate the build process, and I *should not* change the sources. – Yakov Galka Dec 19 '11 at 18:57
  • Sorry about the space; I wanted to add a commandline solution, but it wasn't quite what you were looking for. Nonetheless, doing it from the commandline is only going to make your day miserable, trust me. – hiobs Dec 19 '11 at 19:16
  • 2
    Sometimes the commandline is more useful than a gui application and sometimes not. I really don't think that you can say that this will make your day miserable, as it really depends on the situation, skill of the user, and personal preference. – NeoH4x0r Jan 08 '18 at 08:46