Categories
c++ cmake

How do I add a linker or compile flag in a CMake file?

276

I am using the arm-linux-androideabi-g++ compiler. When I try to compile a simple “Hello, World!” program it compiles fine. When I test it by adding a simple exception handling in that code it works too (after adding -fexceptions .. I guess it is disabled by default).

This is for an Android device, and I only want to use CMake, not ndk-build.

For example – first.cpp

#include <iostream>

using namespace std;

int main()
{
   try
   {
   }
   catch (...)
   {
   }
   return 0;
}

./arm-linux-androideadi-g++ -o first-test first.cpp -fexceptions

It works with no problem…

The problem … I am trying to compile the file with a CMake file.

I want to add the -fexceptions as a flag. I tried with

set (CMAKE_EXE_LINKER_FLAGS -fexceptions ) or set (CMAKE_EXE_LINKER_FLAGS "fexceptions" )

and

set ( CMAKE_C_FLAGS "fexceptions")

It still displays an error.

3

289

Note: Given CMake evolution since this was answer was written in 2012, most of the suggestions here are now outdated/deprecated and have better alternatives.


Suppose you want to add those flags (better to declare them in a constant):

SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS    "-lgcov")

There are several ways to add them:

  1. The easiest one (not clean, but easy and convenient, and works only for compile flags, C & C++ at once):

     add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
    
  2. Appending to corresponding CMake variables:

     SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
     SET(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
    
  3. Using target properties, cf. doc CMake compile flag target property and need to know the target name.

     get_target_property(TEMP ${THE_TARGET} COMPILE_FLAGS)
     if(TEMP STREQUAL "TEMP-NOTFOUND")
       SET(TEMP "") # Set to empty string
     else()
       SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
     endif()
     # Append our values
     SET(TEMP "${TEMP}${GCC_COVERAGE_COMPILE_FLAGS}" )
     set_target_properties(${THE_TARGET} PROPERTIES COMPILE_FLAGS ${TEMP} )
    

Right now I use method 2.

5

  • 4

    why is add_definitions() unclean?

    Oct 9, 2014 at 16:15

  • 17

    @leinaD_natipaC: The official documentation says: This command can be used to add any flags, but it is intended to add preprocessor definitions. I think that’s why.

    Nov 21, 2014 at 17:01


  • 5

    While this is the accepted answer this really show very old style CMAKE, refer to the answer by @vitaut for how any new CMAKE code should be structured with regard to compile time parameters

    Apr 29, 2020 at 13:35

  • 2

    string(APPEND CMAKE_EXE_LINKER_FLAGS "new_value") is shorter and cleaner than set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} new_value")

    – bloody

    Apr 30, 2020 at 13:21


  • 1

    outdated advice

    Mar 17, 2021 at 15:09

230

In newer versions of CMake you can set compiler and linker flags for a single target with target_compile_options and target_link_libraries respectively (yes, the latter sets linker options too):

target_compile_options(first-test PRIVATE -fexceptions)

The advantage of this method is that you can control propagation of options to other targets that depend on this one via PUBLIC and PRIVATE.

As of CMake 3.13 you can also use target_link_options to add linker options which makes the intent more clear.

11

  • 2

    I’ve tried to use it: target_compile_options(main_static PRIVATE --static) but it doesn’t seem to work, any idea why?

    Nov 5, 2016 at 0:12

  • 2

    -static is probably a linker, not compiler option. Try passing it to target_link_libraries.

    – vitaut

    Nov 5, 2016 at 14:25

  • 12

    Oh, target_link_libraries I’ve missed that part of doc: “Specify libraries or flags to use when linking a given target.”. Thanks.

    Nov 5, 2016 at 14:32


  • 7

    A recent addition: CMake 3.13 introduces target_link_options as a cleaner way to specify linker flags. You should avoid using target_link_libraries for linker flags in the future and use target_link_options instead.

    Oct 23, 2018 at 6:59

  • 3

    There is also add_compile_options – see stackoverflow.com/questions/39501481/… and more recently add_link_options

    Dec 7, 2018 at 14:50


55

Try setting the variable CMAKE_CXX_FLAGS instead of CMAKE_C_FLAGS:

set (CMAKE_CXX_FLAGS "-fexceptions")

The variable CMAKE_C_FLAGS only affects the C compiler, but you are compiling C++ code.

Adding the flag to CMAKE_EXE_LINKER_FLAGS is redundant.

4

  • i tried that but it still gives error. Is set(CMAKE_CXX_FLAGS “-fexceptions”) the only way to specify compiler flag.

    – solti

    Aug 2, 2012 at 19:50


  • 3

    i solved the problem but not in a good way its a poor workaround .. i made -DCMAKE_CXX_FLAGS= “-fexceptions” in the command line. for some reason cmake is not reading flags from the .cmake file. 🙁 .. thank you sakra for your answer ..

    – solti

    Aug 2, 2012 at 21:59


  • 9

    -DCMAKE_CXX_FLAGS= “-fexceptions” There should NOT be a space between the = and “

    – evandrix

    Dec 5, 2012 at 8:05

  • 1

    Regarding what you said: “for some reason cmake is not reading flags from the .cmake file.” Make sure you clear up the existing cache. This can be done by deleting everything from the build directory before cmake again.

    – zaizen

    Jul 15, 2016 at 5:32