CMake per-language option flags
CMake can set compiler flags that encompass three broad scopes. We set global and per-language options near the beginning of the top-level CMakeLists.txt, before any targets are declared, to avoid confusion about scope. COMPILE_DEFINITIONS works in a similar fashion.
By default,
add_compile_options()
is global for all languages.
The options are restricted by compiler, language, build configuration, etc. using CMake
generator expressions.
For example, $<COMPILE_LANGUAGE:Fortran>
is used to restrict options to Fortran targets.
A stanza like $<AND:$<COMPILE_LANGUAGE:Fortran>,$<CONFIG:Debug,RelWithDebInfo>>
sets flags for Fortran targets in the debug and RelWithDebInfo build configurations.
Per-target options are set by target_compile_options.
Note: where using
FetchContent,
the main project may desire -Wall
but this may cause megabytes of warnings from a legacy Fetched project.
A solution is to put add_compile_options() in each of the parent project directories and/or use target_compile_options() in the parent project.
This example is for a C and Fortran project, where some flags apply to C and Fortran, and other flags are Fortran-specific.
project(Foo
LANGUAGES C Fortran)
if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
add_compile_options(
-Wall
$<$<COMPILE_LANGUAGE:Fortran>:-fimplicit-none>
$<$<AND:$<COMPILE_LANGUAGE:Fortran>,$<CONFIG:Debug,RelWithDebInfo>>:-Werror=array-bounds>
)
endif()
add_library(old OBJECT legacy.f old.f)
# these options apply only to target "old"
target_compile_options(old PRIVATE -w -fno-implicit-none)
add_executable(main main.f90 $<TARGET_OBJECTS:old>)