Define Preprocessor Macro Through Cmake

Define preprocessor macro through CMake?

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.

Defining preprocessor in modern CMake

The general trend in modern CMake is to move from global settings to target-centric settings. Based on this rule alone, target_compile_definitions() is the most modern approach. It also allows control of whether the settings are used in the target only (PRIVATE), in other targets consuming this target (INTERFACE), or both (PUBLIC). Internally, it works by modifying the target's properties COMPILE_DEFINITIONS and INTERFACE_COMPILE_DEFINITIONS.

Next down in terms of being modern is add_compile_definitions(). It adds the macro definitions to all targets defined in the current directory and subdirectories; its scope is similar to include_directories() in this regard. Internally, it works by modifying the COMPILE_DEFINITIONS property of the current directory. So: it's still using the correct "modern" mechanisms, but is directory-oriented instead of target-oriented.

At the bottom of the list, we have the very old function add_definitions(). This is really best avoided in modern CMake. While intended for specifying preprocessor definitions (hence its name), it actually allows passing arbitrary compiler options in (which is also why you need to specify -DFOO instead of just FOO as its argument). It tries to figure out whether the things passed in are actually preprocessor macro definitions, in which case they are moved into the directory's COMPILE_DEFINTIIONS property. If they are not identified as such (which can happen for macros with complicated replacement strings), they are left in the list of flags.

How to define a C++ preprocessor macro through the command line with CMake?

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.

How to change the macro value before comipling using Make or CMake? [duplicate]

You need a compilation flag -DLED=8 where you replace the 8 with whatever value you want.

You should also wrap the LED macro with

#ifndef LED
#define LED 8
#endif

This way, the -DLED=X will define the macro as X and, since it's already defined, the header file won't try to redefine it.

Regarding CMake, try adding add_compile_definitions(LED=8). Check this for more info.

CMake: How to pass preprocessor macros

add_definitions(-DCOMPILE_UNIT_TESTS) (cf. CMake's doc) or modify one of the flag variables (CMAKE_CXX_FLAGS, or CMAKE_CXX_FLAGS_<configuration>) or set COMPILE_FLAGS variable on the target.

Also, identifiers that begin with an underscore followed by an uppercase letter are reserved for the implementation. Identifiers containing double underscore, too. So don't use them.

How to declare a function like macro using CMake

From the Visual Studio documentation on /D:

The /D option doesn't support function-like macro definitions. To insert definitions that can't be defined on the command line, consider the /FI (Name forced include file) compiler option.

For completeness, GCC does support defining function macros from the commandline:

If you wish to define a function-like macro on the command line, write its argument list with surrounding parentheses before the equals sign (if any). Parentheses are meaningful to most shells, so you should quote the option. With sh and csh, -D'name(args…)=definition' works.

Is there a way to define a preprocessor macro that includes preprocessor directives?

You cannot define preprocessing directives the way you show in the question.

Yet you may be able to use the _Pragma operator for your purpose:

#if defined __GNUC__ && __GNUC__ >= 8
#define foo _Pragma("GCC unroll 128") _Pragma("GCC ivdep")
#elif defined __clang__
#define foo _Pragma("clang loop vectorize(enable) interleave(enable)")
#else
#define foo
#endif

Use value from C/C++ macro in CMake

I'd go with file(READ ...) to read the header followed by string(REGEX ...) to extract desired define.

Example code:

file(READ "foo.h" header)
string(REGEX MATCH "#define FOO_MAJOR_VERSION [0-9]+" macrodef "${header}")
string(REGEX MATCH "[0-9]+" FooMajorVersion "${macrodef}")


Related Topics



Leave a reply



Submit