Reputation: 4519
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.
Upvotes: 308
Views: 836867
Reputation: 85481
Since CMake 3.13 there is the add_link_options
command.
It applies to all subsequent add_library
and add_executable
commands in the same scope and sub-scopes.
This can be useful for project-wide settings. For example:
add_link_options("-fexceptions")
add_executable(first-test first.cpp)
For specific targets there is target_link_options
:
add_executable(first-test first.cpp)
target_link_options(first-test PUBLIC "-fexceptions")
PUBLIC|PRIVATE|INTERFACE
as usual determines how the option is propagated to downstream dependencies.
There's also a BEFORE
flag for cases when the option needs to be prepended instead of appended.
Upvotes: 4
Reputation: 6107
Edit: My general advice is to avoid adding compiler flags explicitly via CMake altogether. Toolchain files are for configuring novel toolchains, not customising an existing GCC toolchain. A project's CMake is more clean, portable, and future-proof when it is toolchain-agnostic. Separate the concern of describing how your artefacts are constituted (using CMake) from the concern of customising compiler flags. I find environment variables, such as CXXFLAGS are much better at maintaining this separation of concerns. However, in answer to the OP...
The preferred way to specify toolchain-specific options is using CMake's toolchain facility. This ensures that there is a clean division between:
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:
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.)
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.)
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")
Upvotes: 9
Reputation: 19860
Please be aware that due to the evolution of CMake since the writing of this answer in 2012, the majority of the recommendations provided here are now obsolete or no longer recommended, with improved alternatives available.
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:
The easiest one (not clean, but easy and convenient, and works only for compiler flags, C & C++ at once):
add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
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}")
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.
Upvotes: 305
Reputation: 55665
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 clearer.
Upvotes: 259
Reputation: 65951
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.
Upvotes: 60
Reputation: 89422
With CMake 3.4+, APPEND
can be used with the string
command to add flags.
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fexceptions")
Upvotes: -1
Reputation: 1391
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
.....
Upvotes: 1
Reputation: 1434
You can also add linker flags to a specific target using the LINK_FLAGS
property:
set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${flag}")
If you want to propagate this change to other targets, you can create a dummy target to link to.
Upvotes: 4