I am trying to modify compiler flags for all the directories below a certain directory (i.e. for all the current directories subdirectories and all their subdirectories recursively). So I found here there is two ways:
add_directory(dir1)
# ...
add_directory(dirN)
add_compile_options(flag1 flag2 ...)
# or for CMake versions < 3.0 to do something more like:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} flag1 flag2 ...")
The man page for add_compile_options
is very clear in stating that the effect will be "current directory and below" (which is what I want) but for set(CMAKE_CXX_FLAGS ...)
I am not so sure.
Is Cmake set variable recursive?
The short answer is, that each sub-directory has it's own variable scope initialized with a copy of the current variable values at the time of the
add_subdirectory()
call.For the long answer please see What's the CMake syntax to set and use variables?
Directory & Target Properties vs (Global) Variables
There is a difference between how
add_compile_options()
andCMAKE_CXX_FLAGS
are processed by CMake:Everything that you specify with
add_compile_options()
is appended to theCOMPILE_OPTIONS
directory property. Then "this property is used to initialize theCOMPILE_OPTIONS
target property when a target is created" withadd_library()
oradd_executable()
.And the current state of directory properties are used to initialize sub-directory properties when the parser gets to a
add_subdirectory()
call.The
CMAKE_CXX_FLAGS
is a global cached variable. You can extend/overwrite it by defining a local directory scoped variable (hiding the globally cached one).Those variable's context is copied into a sub-directories scope on
add_subdirectory()
(propagating to sub-directories).And CMake looks into its value at the end of the each
CMakeLists.txt
file and applies this to all targets in the sameCMakeLists.txt
(allowing late declarations, see also Complete Formula and Test Code below).So for CMake versions < 3.0 the equivalent to
add_compile_options()
wasadd_definitions()
. The functionality is still there, but it was strange to mix definitions with compile options. Soadd_compile_options()
was invented.The complete Generator-Formula for Compiler Flags
It's in CMake's code (see
cmCommonTargetGenerator::GetFlags()
,cmLocalGenerator::AddCompileOptions()
andcmLocalGenerator::AddLanguageFlags()
).This example shows a
DEBUG
build configuration library without exports, not taking into account the feature-based flags or something likeCMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES
orCMAKE_QUOTE_INCLUDE_PATHS
:Test Code
For a better understanding here is my code for testing the compiler options and the results I get:
Note: Normally I would use
add_definitions()
andtarget_compile_definitions()
instead ofadd_compile_options()
andtarget_compile_options()
to set compiler definitions, but to demonstrate the propagating of compiler options I (mis-)used-D
flags.CMakeLists.txt
lib/CMakeLists.txt
Would result in the following messages:
And the following pre-processor definitions being set:
lib
main
The interesting parts here are the
LATE
CXX flags and theLIB
compile option propagated the the linked library.References