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

Viewed 673651

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.

7 Answers

The preferred way to specify toolchain-specific options is using CMake's toolchain facility. This ensures that there is a clean division between:

  • instructions on how to organise source files into targets -- expressed in CMakeLists.txt files, entirely toolchain-agnostic; and
  • details of how certain toolchains should be configured -- separated into CMake script files, extensible by future users of your project, scalable.

Ideally, there should be no compiler/linker flags in your CMakeLists.txt files -- even within if/endif blocks. And your program should build for the native platform with the default toolchain (e.g. GCC on GNU/Linux or MSVC on Windows) without any additional flags.

Steps to add a toolchain:

  1. Create a file, e.g. arm-linux-androideadi-gcc.cmake with global toolchain settings:

    set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
    set(CMAKE_CXX_FLAGS_INIT "-fexceptions")
    

    (You can find an example Linux cross-compiling toolchain file here.)

  2. When you want to generate a build system with this toolchain, specify the CMAKE_TOOLCHAIN_FILE parameter on the command line:

    mkdir android-arm-build && cd android-arm-build
    cmake -DCMAKE_TOOLCHAIN_FILE=$(pwd)/../arm-linux-androideadi-gcc.cmake ..
    

    (Note: you cannot use a relative path.)

  3. Build as normal:

    cmake --build .
    

Toolchain files make cross-compilation easier, but they have other uses:

  • Hardened diagnostics for your unit tests.

    set(CMAKE_CXX_FLAGS_INIT "-Werror -Wall -Wextra -Wpedantic")
    
  • Tricky-to-configure development tools.

    # toolchain file for use with gcov
    set(CMAKE_CXX_FLAGS_INIT "--coverage -fno-exceptions -g")
    
  • Enhanced safety checks.

    # toolchain file for use with gdb
    set(CMAKE_CXX_FLAGS_DEBUG_INIT "-fsanitize=address,undefined -fsanitize-undefined-trap-on-error")
    set(CMAKE_EXE_LINKER_FLAGS_INIT "-fsanitize=address,undefined -static-libasan")
    

This worked for me when I needed a precompile definition named "NO_DEBUG":

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DNO_DEBUG")

Then from code

#ifdef NO_DEBUG
.....

With CMake 3.4+, APPEND can be used with the string command to add flags.

string(APPEND CMAKE_EXE_LINKER_FLAGS " -fexceptions")
Related