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

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.

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")

Finding library during compilation in mingw64 environment (libgcrypt and libgpg-error)

I'm a real beginner at this, so apologies in advance for obvious questions. I'm trying to compile a custom build of ffmpeg that has some extra dependencies the normal build does not. Among those is libgcrypt and libgpg-error - I know this, because when I run configure, it fails, and the log contains:
C:/workspace/windows/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lgcrypt
C:/workspace/windows/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/6.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lgpg-error
With this in mind, I cloned the repo for libgpg-error, ran make and make install, which created libgpg-error.dll.a and libgpg-error.la in /home/myuser/w64root/lib. I've tried adding this path to my $LIB environment variable, but the configure run still says it can't find the library.
How can I make it visible? I also have pkg-config available on the machine - would manually creating a .pc file help me any?
Thanks!
If you run ./configure -h, you should see this in the output:
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir>
LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
CPP C preprocessor
CXX C++ compiler command
CXXFLAGS C++ compiler flags
Note LDFLAGS in particular. That covers your case, since /home/myuser/w64root/lib
is not among the linker's standard search directories. Therefore run:
export LDFLAGS='-L/home/myuser/w64root/lib'; ./configure
and you should be OK.

make without makefile after cmake

I try to use the c++ language bindings for the ev3dev lego brick: https://github.com/ddemidov/ev3dev-lang-cpp
The instruction is as follows:
mkdir build
cd build
cmake .. -DEV3DEV_PLATFORM=EV3
make
I am running windows and have cmake and mingw available. After running cmake it creates some files in the build directory. However: There is no makefile which could be picked of by make. So I am wondering how iam supposed to compile these bindings
On Windows, CMake generates a MSVC solution by default. Check for a .sln file in your build directory.
The instructions you linked are assuming a Unix-ish platform, where the default is to create Makefiles.
If you actually want Makefiles on Windows, add -G "Unix Makefiles" to the cmake line.
If you want to use MSVC as compiler but work on the command line, another option is -G "NMake Makefiles", and calling nmake after that.
Make sure to delete your build directory before trying to build a new generator target. CMake can be touchy about that.
Check cmake --help for a list of available options. (Especially the generator targets are platform-specific.)

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

passing CC/CFLAGS/LDFLAGS from Makefile to ./configure of Tk/Tcl

I'm trying to compile one library (xcrysden, based on Make file) which during its compilation execute ./configure of an external dependencies - Tk and Tcl 8.5 - and compiles them.
So, the structure is roughly like this:
The main Makefile:
...
cd external/src; make;
external dependencies (pre-)makefile (Tk):
include ../Make.sys
cd /unix
./configure
make
make install
Make.sys included by external makefile:
...
CFLAGS =...
CC =...
The configure, obviously, produces another makefile in /external/src/unix to be used by Tk.
In Tk documentation it is written:
If you wish to specify a particular compiler, set the CC environment variable before calling configure. You can also specify CFLAGS prior to configure and they will be used during compilation.
But from the resulting Makefile i definitely see that neither the defined compiler (CC) nor flags (CFLAGS) are used. Does it qualify as 'environment variable' when it is set in another make file?
I actually have problems compiling Tk, so i try to pass not only compiler but linking info
LDFLAGS = -L/opt/local/lib -lfontconfig .
I want to do it in a neat way (that is, modifying only Make.sys of the library dependent on Tk). But then i face the problem that not only don't i know how to pass LDFLAGS to Tk configure, but even CC/CFLAGS are not there. I'm not sure if this is specific to particular library (Tk) using ./configure or I misunderstand the general usage of ./configure.
p/s/ i'm compiling on OS-X using gnu compilers.
The problem is that the variables you define in ../Make.sys are currently local to the shell that processes the include; the configure and make are run in subprocesses and don't find out that you've got any preferences. The right thing to do is to add:
export CFLAGS CC
between the include and the call to ./configure.
You could also put it inside Make.sys, or invoke configure as CFLAGS=$CFLAGS CC=$CC ./configure. You probably shouldn't set the values directly in the invocation of make though; setting the compiler can mean that different other flags are required as well.

Resources