Use -isystem instead of -I with CMake - gcc

Is there any way in CMake to force a path specified via include_directories (or perhaps through a different function) to use the -isystem flag instead of the -I flag when building with gcc?
See http://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html#Directory-Options for details on -I and -isystem.

Yes you force a path to be a system include by using the optional SYSTEM flag
include_directories(SYSTEM path)
https://cmake.org/cmake/help/latest/command/include_directories.html
Starting with CMake 2.8.12 you can use the new target_include_directories to include system directory includes at the target level, while leveraging the new usage requirement features of cmake:
target_include_directories(foo SYSTEM PUBLIC path)
Now target foo will use path as a system include, and anything that links to foo will also use path as automatically as a system include. You can control the propagation of these usage requirements by changing the PUBLIC keyword to PRIVATE or INTERFACE.
https://cmake.org/cmake/help/latest/command/target_include_directories.html

As stated already, the correct way to include system paths is:
include_directories(SYSTEM path1 path2)
However as of CMake 2.8.4 and Makefiles, This is only used for C++ and not C, I looked into it and GNU.cmake does not initialize: CMAKE_INCLUDE_SYSTEM_FLAG_C
So you can set this yourself right after calling project().
if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ")
endif()
Update:
The CMake developers have fixed this in 2.8.5

You could try using CMAKE_C_FLAGS and CMAKE_CXX_FLAGS to add additional flags.

Related

How to add CFLAGS and CXXFLAGS and LDFLAGS to file.cmake? [duplicate]

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.
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:
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})
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.
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.
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.
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:
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")
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.
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")

How to change the default-search-path values for GNU GCC for regular usage?

GNU GCC Compiler Environment Variables Default-Search-Path — I am trying to change default values of GCC environment variables to new custom values so that the default search path will contain any needed additional libraries or include header files that I would like to use on a regular basis.
My version of GNU GCC is: gcc (MinGW.org GCC Build-2) 9.2.0
Include directories for .h header files for this <…> not "…" which would be in the same directory as .c file extension.
Include Header Directories:
CPATH
C_INCLUDE_PATH
CPLUS_INCLUDE_PATH
OBJC_INCLUDE_PATH
Library File Directories:
LIBRARY_PATH
I realized that these are Windows Environment Variables.
And That I could Simply just create Windows User Environment Variables.
Here is a command which will show default search paths for GNU GCC Compiler.
cpp -v
This shows include directory default search path.
gcc -print-search-dirs
This shows library directory default search path.
This Command Prompt Command tells me the default-search-paths which are set during installation of GNU GCC Compiler I assume these are considered Environment Variables and I am looking to see if anyone on the web could give me any urls in regards to changing this default search path value.
Here are a few links related to what I am doing. I used that information although I was still unable to accomplish what I was intending to accomplish.
GCC environment variables
C Preprocessor search path
C preprocessor environment variables
GCC configuration
Recent GCC compilers have some (optional) .spec files.
You could edit yours, and that file drives the actual compilation processes. As you know, gcc is mostly starting some cc1 / cc1plus internal program (then ld)
But I recommend to not edit your .spec file.
Instead of that, configure your build procedure, e.g. edit your Makefile for GNU make or your build.ninja file (actually, the generator of that file) for ninja builder.
Of course, read the chapter about Invoking GCC.
BTW, GNU make has a lot of built-in rules. Use make -p to understand them.
You could also take inspiration from GNU autoconf.
You could also code your own GCC plugin, implementing your own #pragma which would customize the behavior of gcc. I am not sure it is a good idea.
How to change the default-search-path values?
don't do that, learn to use GCC instead
You might want, from time to time, to compile your code with Clang, to check that your code base is not tied to one particular compiler.
You could use Frama-C or the Clang static analyzer on your C code. In some cases, some bugs could be found at compile time. You certainly want to pass explicitly both -Wall and -Wextra to gcc (and notice that clang accepts them also)
PS. This is from a GNU/Linux perspective. Adapt that to your proprietary operating system. Or consider getting the permission to switch to Linux (see also this draft report funded by the CHARIOT European project).

How to specify new GCC path for CMake

My OS is centos which has a default gcc in path /usr/bin/gcc. But it is old, I need a new version of gcc. So I install a new version in a new path /usr/local/bin/gcc.
But when I run cmake, it still uses the old version gcc path(/usr/bin/gcc) . How can I specify the gcc to new path(/usr/local/bin/gcc).
I have tried to overwrite /usr/bin/gcc with /usr/local/bin/gcc, but it not work.
Do not overwrite CMAKE_C_COMPILER, but export CC (and CXX) before calling cmake:
export CC=/usr/local/bin/gcc
export CXX=/usr/local/bin/g++
cmake /path/to/your/project
make
The export only needs to be done once, the first time you configure the project, then those values will be read from the CMake cache.
UPDATE: longer explanation on why not overriding CMAKE_C(XX)_COMPILER after Jake's comment
I recommend against overriding the CMAKE_C(XX)_COMPILER value for two main reasons: because it won't play well with CMake's cache and because it breaks compiler checks and tooling detection.
When using the set command, you have three options:
without cache, to create a normal variable
with cache, to create a cached variable
force cache, to always force the cache value when configuring
Let's see what happens for the three possible calls to set:
Without cache
set(CMAKE_C_COMPILER /usr/bin/clang)
set(CMAKE_CXX_COMPILER /usr/bin/clang++)
When doing this, you create a "normal" variable CMAKE_C(XX)_COMPILER that hides the cache variable of the same name. That means your compiler is now hard-coded in your build script and you cannot give it a custom value. This will be a problem if you have multiple build environments with different compilers. You could just update your script each time you want to use a different compiler, but that removes the value of using CMake in the first place.
Ok, then, let's update the cache...
With cache
set(CMAKE_C_COMPILER /usr/bin/clang CACHE PATH "")
set(CMAKE_CXX_COMPILER /usr/bin/clang++ CACHE PATH "")
This version will just "not work". The CMAKE_C(XX)_COMPILER variable is already in the cache, so it won't get updated unless you force it.
Ah... let's use the force, then...
Force cache
set(CMAKE_C_COMPILER /usr/bin/clang CACHE PATH "" FORCE)
set(CMAKE_CXX_COMPILER /usr/bin/clang++ CACHE PATH "" FORCE)
This is almost the same as the "normal" variable version, the only difference is your value will be set in the cache, so users can see it. But any change will be overwritten by the set command.
Breaking compiler checks and tooling
Early in the configuration process, CMake performs checks on the compiler: Does it work? Is it able to produce executables? etc. It also uses the compiler to detect related tools, like ar and ranlib. When you override the compiler value in a script, it's "too late", all checks and detections are already done.
For instance, on my machine with gcc as default compiler, when using the set command to /usr/bin/clang, ar is set to /usr/bin/gcc-ar-7. When using an export before running CMake it is set to /usr/lib/llvm-3.8/bin/llvm-ar.
This question is quite old but still turns up on Google Search. The accepted question wasn't working for me anymore and seems to be aged. The latest information about cmake is written in the cmake FAQ.
There are various ways to change the path of your compiler. One way would be
Set the appropriate CMAKE_FOO_COMPILER variable(s) to a valid compiler
name or full path on the command-line using cmake -D. For example:
cmake -G "Your Generator" -D CMAKE_C_COMPILER=gcc-4.2 -D CMAKE_CXX_COMPILER=g++-4.2 path/to/your/source
instead of gcc-4.2 you can write the path/to/your/compiler like this
cmake -D CMAKE_C_COMPILER=/path/to/gcc/bin/gcc -D CMAKE_CXX_COMPILER=/path/to/gcc/bin/g++ .
Set CMAKE_C_COMPILER to your new path.
See here: http://www.cmake.org/Wiki/CMake_Useful_Variables
Change CMAKE_<LANG>_COMPILER path without triggering a reconfigure
I wanted to compile with an alternate compiler, but also pass -D options on the command-line which would get wiped out by setting a different compiler. This happens because it triggers a re-configure. The trick is to disable the compiler detection with NONE, set the paths with FORCE, then enable_language.
project( sample_project NONE )
set( COMPILER_BIN /opt/compiler/bin )
set( CMAKE_C_COMPILER ${COMPILER_BIN}/clang CACHE PATH "clang" FORCE )
set( CMAKE_CXX_COMPILER ${COMPILER_BIN}/clang++ CACHE PATH "clang++" FORCE )
enable_language( C CXX )
Use a Toolchain file
The more sensible choice is to create a toolchain file.
set( CMAKE_SYSTEM_NAME Darwin )
set( COMPILER_BIN /opt/compiler/bin )
set( CMAKE_C_COMPILER ${COMPILER_BIN}/clang CACHE PATH "clang" )
set( CMAKE_CXX_COMPILER ${COMPILER_BIN}/clang++ CACHE PATH "clang++" )
Then you invoke Cmake with an additional flag
cmake -D CMAKE_TOOLCHAIN_FILE=/path/to/toolchain_file.cmake ...
Export should be specific about which version of GCC/G++ to use, because if user had multiple compiler version, it would not compile successfully.
export CC=path_of_gcc/gcc-version
export CXX=path_of_g++/g++-version
cmake path_of_project_contain_CMakeList.txt
make
In case project use C++11 this can be handled by using -std=C++-11 flag in CMakeList.txt
An alternative solution is to configure your project through cmake-gui, starting from a clean build directory. Among the options you have available at the beginning, there's the possibility to choose the exact path to the compilers
This not only works with cmake, but also with ./configure and make:
./configure CC=/usr/local/bin/gcc CXX=/usr/local/bin/g++
Which is resulting in:
checking for gcc... /usr/local/bin/gcc
checking whether the C compiler works... yes

Pass option to cmake for future option to crosscompilation (CROSS_COMPILE)

IF(UNIX)
# CROSS COMPILATION! ON/OFF
#SET(CMAKE_C_COMPILER /home/username/projects/buildroot/output/host/usr/bin/arm-linux-gcc)
#SET(CMAKE_CXX_COMPILER /home/username/projects/buildroot/output/host/usr/bin/arm-linux-g++)
#SET(CMAKE_C_COMPILER /home/username/CodeSourcery/Sourcery_G++_Lite/bin/arm-none-eabi-gcc)
#SET(CMAKE_CXX_COMPILER /home/username/CodeSourcery/Sourcery_G++_Lite/bin/arm-none-eabi-g++)
here is what I do now for cross-compilation. I want to add option to run it alike that:
make CROSS_COMPILE=~/projects/buildroot/output/host/usr/bin/arm-linux-
and if I do not path CROSS_COMPILE to make (not to cmake) it must use system defaults so cmake must path this option to makefile. How can I make it?
Buildroot generates a CMake toolchain file for you. Depending on your Buildroot, it might be directly in the output directory, or in output/host/usr/share/buildroot. The file is named toolchainfile.cmake. Then to build your CMake applications, do:
cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/buildroot/output/host/usr/share/buildroot/toolchainfile.cmake
This file contains all the definitions of the cross-compiler paths, pkg-config environment variables, headers and libraries location, etc.
For the simplest method, do this:
SET(CMAKE_C_COMPILER $(CROSS_COMPILE)gcc)
SET(CMAKE_CXX_COMPILER $(CROSS_COMPILE)g++)
When the CROSS_COMPILE variable is passed to make, it will be substituted with the cross compiler path.
Now, the proper way. Ideally, the CROSS_COMPILE variable should be defined when CMake is run as it is meant to be cross-platform. Using the first solution could break if other CMake generators are used.
This can be done as:
IF(UNIX)
SET(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc)
SET(CMAKE_CXX_COMPILER ${CROSS_COMPILE}g++)
Then define the variable:
cmake -G "Unix Makefiles" -DCROSS_COMPILE=~/projects/buildroot/output/host/usr/bin/arm-linux-
In this case, CMake will generate proper build files, based on whether CROSS_COMPILE is defined or not.

How to set the LDFLAGS in CMakeLists.txt?

I set the CFLAGS in CMake by CMAKE_C_FLAGS.
Is something like this to set LDFLAGS?
It depends a bit on what you want:
A) If you want to specify which libraries to link to, you can use find_library to find libs and then use link_directories and target_link_libraries to.
Of course, it is often worth the effort to write a good find_package script, which nicely adds "imported" libraries with add_library( YourLib IMPORTED ) with correct locations, and platform/build specific pre- and suffixes. You can then simply refer to 'YourLib' and use target_link_libraries.
B) If you wish to specify particular linker-flags, e.g. '-mthreads' or '-Wl,--export-all-symbols' with MinGW-GCC, you can use CMAKE_EXE_LINKER_FLAGS. There are also two similar but undocumented flags for modules, shared or static libraries:
CMAKE_MODULE_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS
CMAKE_STATIC_LINKER_FLAGS
Look at:
CMAKE_EXE_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS
CMAKE_STATIC_LINKER_FLAGS
If you want to add a flag to every link, e.g. -fsanitize=address then I would not recommend using CMAKE_*_LINKER_FLAGS. Even with them all set it still doesn't use the flag when linking a framework on OSX, and maybe in other situations. Instead use link_libraries():
add_compile_options("-fsanitize=address")
link_libraries("-fsanitize=address")
This works for everything.
You can specify linker flags in target_link_libraries.
For linking against libraries see Andre's answer.
For linker flags - the following 4 CMake variables:
CMAKE_EXE_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS
CMAKE_STATIC_LINKER_FLAGS
can be easily manipulated for different configs (debug, release...) with the ucm_add_linker_flags macro of ucm

Resources