73

At the beginning of my CMake project, I'm setting general compilation flags in the variable CMAKE_CXX_FLAGS, like

set(CMAKE_CXX_FLAGS "-W -Wall ${CMAKE_CXX_FLAGS}")

Later on, I need to append additional configuration-specific compilation flags (stored in BUILD_FLAGS). Can I use the following command for this:

set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS ${BUILD_FLAGS})

or do I have to add the CMAKE_CXX_FLAGS manually:

set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BUILD_FLAGS}")

to prevent CMAKE_CXX_FLAGS being overriden by BUILD_FLAGS?

1
  • 2
    I believe that they are appended to the CMAKE_CXX_FLAGS, you can verify this by invoking a verbose make file make target VERBOSE=1 Commented Feb 23, 2011 at 21:49

2 Answers 2

77

The accepted answer is still working but outdated since 2013.
This answer is based and new functions from CMake v2.8.12, v3.3 and v3.13.

Since CMake-2.8.12 (2013)

Two new commands to set CMAKE_CXX_FLAGS:

The documentation of last version has not changed a lot since cmake-2.8.12:

In you case you can use:

target_compile_options(${TARGET} PRIVATE ${BUILD_FLAGS})

Or simply if you have a single target:

add_compile_options(${BUILD_FLAGS})

More examples

target_compile_options(mylib PRIVATE   -O2) # only internal
target_compile_options(mylib INTERFACE -gl) # only external
target_compile_options(mylib PUBLIC    -g)  # same as PRIVATE + INTERFACE

# multiple targets and flags
target_compile_options(mylib1 mylib2 PRIVATE -Wall -Wextra)

target_compile_options(    mylib PUBLIC -DUSEXX)  # Bad
target_compile_definitions(mylib PUBLIC -DUSEXX)  # OK

add_compile_options(-Wall -Wextra) # for all targets in current directory
add_compile_options(-DUSEXX)       # Bad
add_definitions(-DUSEXX)           # OK

Deprecated COMPILE_FLAGS

cmake-3.0 documentation flags COMPILE_FLAGS as deprecated:

COMPILE_FLAGS

Additional flags to use when compiling this target’s sources.

The COMPILE_FLAGS property sets additional compiler flags used to build sources within the target. Use COMPILE_DEFINITIONS to pass additional preprocessor definitions.

This property is deprecated. Use the COMPILE_OPTIONS property or the target_compile_options command instead.

If you still want to use set_target_properties() you may use COMPILE_OPTIONS instead of COMPILE_FLAGS:

set_target_properties(${TARGET} PROPERTIES COMPILE_OPTIONS ${BUILD_FLAGS})

Since CMake-3.3 (2015)

Anton Petrov suggests to use generator expressions as presented in an answer of ar31.

The CMake generator expressions applies your ${BUILD_FLAGS} to:

  • C++ language using $<COMPILE_LANGUAGE:CXX> (can also be C, CUDA...)
  • Clang compiler using $<CXX_COMPILER_ID:Clang>
    (can also be GNU for gcc, or MSVCfor Visual C++... see full list)
    (use $<C_COMPILER_ID:Clang> instead if language is C)
  • and more as supported C++ feature or compiler version... (see documentation)

In you case you can use:

target_compile_options(${TARGET} PRIVATE
          $<$<COMPILE_LANGUAGE:CXX>:${BUILD_FLAGS_FOR_CXX}>
          $<$<COMPILE_LANGUAGE:C>:${BUILD_FLAGS_FOR_C}>)

or about compilers:

target_compile_options(${TARGET} PRIVATE
          $<$<CXX_COMPILER_ID:Clang>:${BUILD_FLAGS_FOR_CLANG}>
          $<$<CXX_COMPILER_ID:GNU>:${BUILD_FLAGS_FOR_GCC}>
          $<$<CXX_COMPILER_ID:MSVC>:${BUILD_FLAGS_FOR_VISUAL}>)

Since CMake-3.13 (2018)

A new function target_link_options() allow to pass options to the linker, as mentioned by Craig Scott.

Different options for C and C++ files

The best way is to distinguish C files and C++ files using two different targets.

Sign up to request clarification or add additional context in comments.

13 Comments

What if you have mixed target? For example C and C++. How do you set options only for C target?
Hi @Martin. I do not know about a target mixing C and C++ files using different options each kind of source file. I may suggest to split this target in two : one target for C source code and the other one for C++. ... OK I am starting to add a section in may answer to propose a way to address this complex situation...
Why can't I use set_target_properties() with LINK_FLAGS the same way? It seems it never accepts more than one flag (Even in list form).
@olibre Please see this answer stackoverflow.com/a/21561742/423959 for language specific options. The right way is to use generator expressions.
$<$<COMPILE_LANGUAGE:C>:${BUILD_FLAGS_FOR_CXX}> is probably a mistake, it should rather be $<$<COMPILE_LANGUAGE:C>:${BUILD_FLAGS_FOR_C}>
|
62

Use the first one:

set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS ${BUILD_FLAGS})

The flags stored in BUILD_FLAGS are appended after CMAKE_CXX_FLAGS when compiling the sources of TARGET. The documentation hints at this, but I've just tried it to make sure.

COMPILE_FLAGS

   Additional flags to use when compiling this target's sources. 
   
   The COMPILE_FLAGS property sets additional compiler flags used to
   build sources within the target.  Use COMPILE_DEFINITIONS to
   pass additional preprocessor definitions.

The full command line will be the equivalent of:

${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS} -o foo.o -c foo.cc

And as Ramon said, you can always check with make VERBOSE=1.

1 Comment

You are right, thank you very much (and to Ramon too). I also didn't know about the VERBOSE parameter before and it is now much easier for me to learn how CMake actually processes my commands.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.