I'm currently learning CMake and don't want to get bad habits since there is always 2 ways to do something in CMake (old way and modern way from what I have seen)
After reading some documentation about preprocessor in CMake and checking this post: Define preprocessor macro through cmake
I've come to the conclusion that I could either define a preprocessor as :
add_compile_definitions(FOO)
target_compile_definitions(myTarget PRIVATE FOO)
add_definitions(-DFOO)
and after some test they does actually all works as intended and define FOO
But now my question is what's the most "modern" way that I should use and what is really the difference between each functions, the only difference I noticed is that if I use target_compile_definitions(myTarget PUBLIC FOO)
it then define FOO
in parent target.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With