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. Soset CL=/DMY_MACRO=1 %CL%
then invoke MSBuild to do its job.
With Makefiles: The generated makefiles use the
CFLAGS
andCXX_FLAGS
variables as makefiles are expected to do. So the build can be started bymake 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
While Writting Unittests for a Function, Should I Mock the Internal Function Calls Made
What Is Array to Pointer Decay
What Are Forward Declarations in C++
Is Segmentation Fault Actual Undefined Behavior When We Refer to a Non-Static Data-Member
Why Does C++ Code For Testing the Collatz Conjecture Run Faster Than Hand-Written Assembly
What Is "Rvalue Reference For *This"
How to Print a List of Elements Separated by Commas
Function Does Not Change Passed Pointer C++
Difference Between Float and Double
Subclass/Inherit Standard Containers
Most Efficient Way of Copying a Raw Byte Array into an Empty Byte Vector
What Is the Strict Aliasing Rule
Difference Between 'Struct' and 'Typedef Struct' in C++
How to Parse a String to an Int in C++
How to Remove Code Duplication Between Similar Const and Non-Const Member Functions
Why Do I Get the Same Sequence For Every Run With Std::Random_Device With Mingw Gcc4.8.1