CMake cross-compile with specific linker doesn't pass arguments to armlink - c

I am trying to cross-compile a project for embedded ARM Cortex builds, but I am unable to get the linker working. I want to use armlink, but no files are passed to armlink and hence no .elf file is produced.
My CMakeLists.txt is pretty simple and given below. The failure is shown after that which shows that armlink was invoked by the makefile without any arguments.
Any pointers will help - I searched and read many posts, but they all seem to have more involved requirements.
cmake_minimum_required(VERSION 2.8)
project(test_arm)
enable_language(C ASM)
# Cross-compilation for ARM
SET(CMAKE_C_COMPILER armcc)
SET(CMAKE_LINKER armlink)
SET(CMAKE_C_LINK_EXECUTABLE armlink)
SET(CMAKE_C_FLAGS "--cpu=Cortex-M3")
SET(LINK_FLAGS "--map --ro-base=0x0 --rw-base=0x0008000 --first='boot.o(RESET)' --datacompressor=off")
SET(CMAKE_EXE_LINKER_FLAGS "--map --ro-base=0x0 --rw-base=0x0008000 --first='boot.o(RESET)' --datacompressor=off")
include_directories(../include)
add_executable(blinky blinky.c)
set_target_properties(blinky PROPERTIES LINKER_LANGUAGE C)
The failure is as follows, but I guess it would be obvious to someone given that I have some stupid issue in my CMakeLists:
$ make VERBOSE=1
[100%] Building C object CMakeFiles/blinky.dir/blinky.c.o
/usr/bin/cmake -E cmake_link_script CMakeFiles/blinky.dir/link.txt --verbose=1
armlink
Linking C executable blinky
Product: DS-5 Professional 5.21.0 [5210017]
Component: ARM Compiler 5.05 update 1 (build 106)
Tool: armlink [4d0efa]
For support see http://www.arm.com/support/
Software supplied by: ARM Limited
Usage: armlink option-list input-file-list
where
....
I was expecting the CMake generated Makefile to invoke armlink with something like:
armlink --map --ro-base=0x0 --rw-base=0x0008000 \
--first='boot.o(RESET)' --datacompressor=off \
CMakeFiles/blinky.dir/blinky.c.o -o blinky.elf

Starting with CMake v3.5 you don't need a toolchain anymore for Keil ARM C/C++ compilation tools:
Support was added for the ARM Compiler (arm.com) with compiler id ARMCC.
Just set your C/CXX compiler variables accordingly
cmake -DCMAKE_C_COMPILER:PATH="C:\Program Files (x86)\DS-5\bin\armcc.exe"
-DCMAKE_CXX_COMPILER:PATH="C:\Program Files (x86)\DS-5\bin\armcc.exe"
...
References
ARMCC toolchain support
Add support for the ARM Compiler (arm.com)
CMake Error at CMakeLists.txt:30 (project): No CMAKE_C_COMPILER could be found

From my experience, you cannot set CMAKE_EXE_LINKER_FLAGS in a CMakeLists.txt file. It has to be passed via a CMAKE_TOOLCHAIN_FILE when CMake is invoked the very first time in a build directory.
I don't find any documentation regarding this problem, but there is the cross-compilation with CMake page which you should use it if you do cross-compilation.
For a start, just put your set-calls in a toolchain file and run
cmake -DCMAKE_TOOLCHAIN_FILE=<yourfile.toolchain>
in a clean build directory.

A toolchain file may be a good idea. Here is what I've came up the last time I tried CMake 2.8.10 with the DS-5 toolchain (it could still be optimized, but it should give you a starting point):
INCLUDE(CMakeForceCompiler)
# This one is important
SET(CMAKE_SYSTEM_NAME Generic)
SET(CMAKE_SYSTEM_PROCESSOR arm)
# Specify the cross compiler
SET(CMAKE_C_COMPILER "C:/Program Files (x86)/DS-5/bin/armcc.exe")
SET(CMAKE_CXX_COMPILER "C:/Program Files (x86)/DS-5/bin/armcc.exe")
SET(CMAKE_AR "C:/Program Files (x86)/DS-5/bin/armar.exe" CACHE FILEPATH "Archiver")
#CMAKE_FORCE_C_COMPILER("C:/Program Files (x86)/DS-5/sw/gcc/bin/arm-linux-gnueabihf-gcc.exe" GNU)
#CMAKE_FORCE_CXX_COMPILER("C:/Program Files (x86)/DS-5/sw/gcc/bin/arm-linux-gnueabihf-g++.exe" GNU)
UNSET(CMAKE_C_FLAGS CACHE)
SET(CMAKE_C_FLAGS "--cpu=Cortex-A9 --thumb -Ospace" CACHE STRING "" FORCE)
UNSET(CMAKE_CXX_FLAGS CACHE)
SET(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS} CACHE STRING "" FORCE)
UNSET(CMAKE_EXE_LINKER_FLAGS CACHE)
SET(CMAKE_EXE_LINKER_FLAGS "" CACHE STRING "" FORCE)
UNSET(CMAKE_AR_FLAGS CACHE)
SET(CMAKE_AR_FLAGS "-p -armcc,-Ospace" CACHE STRING "" FORCE)
# set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> ${CMAKE_AR_FLAGS} -o <TARGET> <OBJECTS>" CACHE STRING "C Archive Create")
# set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> ${CMAKE_AR_FLAGS} -o <TARGET> <OBJECTS>" CACHE STRING "CXX Archive Create")
include_directories("C:/Program Files (x86)/DS-5/include")
#include_directories("C:/Program Files (x86)/DS-5/sw/gcc/arm-linux-gnueabihf/libc/usr/include/arm-linux-gnueabi")
# Where is the target environment
SET(CMAKE_FIND_ROOT_PATH "C:/Program Files (x86)/DS-5")
# Search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Regarding your question
Some failure analysis
What you have tried should work (see also e.g. How do I add a linker or compile flag in a CMake file?). But it seems something goes wrong during the configuration step.
I don't know your command line call for CMake's configuration/generation steps, so some general tips to find the root cause:
You could try calling
cmake.exe --trace ...
to see what went wrong with your CMAKE_EXE_LINKER_FLAGS variable. This will generate a lot of output, so here are some basics on what CMake does:
The project() command will trigger the compiler evaluation
This will write CMAKE_EXE_LINKER_FLAGS into your CMakeCache.txt
You are overwriting it with a local variable (see variable scope docu here)
If you look into share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake:
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS_INIT} $ENV{LDFLAGS}"
CACHE STRING "Flags used by the linker.")
You could use CMAKE_EXE_LINKER_FLAGS_INIT, but you have to set it before the project() command or in the toolchain file.
Because you set the link language to C take a look into share\cmake-2.8\Modules\CMakeCInformation.cmake:
if(NOT CMAKE_C_LINK_EXECUTABLE)
set(CMAKE_C_LINK_EXECUTABLE
"<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endif()
So you can use CMAKE_C_LINK_EXECUTABLE to overwrite the complete linker call or you could use CMAKE_C_LINK_FLAGS to set additional flags.
The "official" way
The official way to set the target's linker and compiler flags would be (before CMake 2.8.12):
set_property(TARGET blinky APPEND_STRING PROPERTY COMPILE_FLAGS "--cpu=Cortex-M3")
set_property(TARGET blinky APPEND_STRING PROPERTIES LINK_FLAGS "--map --ro-base=0x0 --rw-base=0x0008000 --first='boot.o(RESET)' --datacompressor=off")
Starting with CMake 2.8.12 it would be something like:
add_compile_options("--cpu=Cortex-M3")

Related

why is cmake producing a binary with debug_info and not stripped [duplicate]

This question already has answers here:
How to config cmake for strip file
(4 answers)
Closed 12 months ago.
why is cmake producing a binary with debug_info and not stripped?
here is my CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
# project name
project(c-program)
set(CMAKE_C_COMPILER "/usr/bin/gcc")
set(CMAKE_C_STANDARD "90")
set(CMAKE_C_STANDARD_REQUIRED true)
set(CMAKE_C_FLAGS "-ansi -Wall")
set(CMAKE_C_FLAGS_DEBUG "-g3 -ggdb3")
set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")
add_executable(c-program c-program.c)
i build like this from the project root folder
$ cmake -S . -B build/release -DCMAKE_BUILD_TYPE=Release
$ cmake --build build/release
when running
$ file build/release/c-program
i get
build/release/c-program: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, with debug_info, not stripped
i am confused about how debug/release builds are supposed to work, and nothing in the cmake tutorial guides or docs or otherwise online is helping me figure out why this is happening
there are some issues with setting flags in CMakeLists.txt, so adding and using a toolchain file helped, and setting appropriate CMAKE_<LANG>_FLAGS_<CONFIG>_INIT vars in the toolchain file. also, the linker is adding debug info. adding -s flag to cmake release flags, and adding -Wl,--strip-debug to linker flags is what i was looking for
here is my final CMakeLists.txt and toolchain files
#CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
# set toolchain file
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/toolchain.cmake"
CACHE PATH "Path to the desired toolchain file.")
# project name
project(c-program C)
add_executable(c-program c-program.c)
# toolchain.cmake
# CMake toolchain file
# c compiler and standard
set(CMAKE_C_COMPILER "/usr/bin/gcc")
set(CMAKE_C_STANDARD "90")
set(CMAKE_C_STANDARD_REQUIRED YES)
# linker flags
set(CMAKE_EXE_LINKER_FLAGS_INIT "-Wl,--strip-debug")
# cflags
set(CMAKE_C_FLAGS_INIT "-ansi -Wall")
# cflags for debug build
set(CMAKE_C_FLAGS_DEBUG_INIT "-g3 -ggdb3")
# cflags for release build
set(CMAKE_C_FLAGS_RELEASE_INIT "-O3 -DNDEBUG -s")

How to link to FreeGlut instead of Glut on macOS using cmake and find_package?

I have the latest version of macOS Big Sur, running intel based cpu, clang12, cmake 3.19 and brew. I have installed freeglut via brew.
However whenever I called find_package(GLUT) it always finds my system GLUT (/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/Library/Frameworks/GLUT.framework) over the FreeGLUT brew has installed. I have tried changing the find_package to FreeGlut with no success.
I am sure its something really simple I am missing but not knowing a lot about the macOS linking process, this has me rather confused.
Here is my cmake command line being used...
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -G Ninja
Here is my cmake file.
# Set cmake minimum version.
cmake_minimum_required(VERSION 3.15)
# Set the project details.
set(PROJECT_NAME Project)
project(${PROJECT_NAME} LANGUAGES C)
# Treat warnings as errors.
option(WarningsAsErrors "WarningsAsErrors" OFF)
# If enabled, the post build symlink will copy instead.
option(CopyResources "CopyResources" OFF)
option(GenerateDoxygen "GenerateDoxygen" OFF)
# Disable in-source builds.
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
# Set build type to debug by default.
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
# Add Linux flag.
if(UNIX AND NOT APPLE)
set(LINUX TRUE)
endif()
# Define the executable.
add_executable(${PROJECT_NAME})
set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 11)
# Find dependencies.
# find_package(OpenGL REQUIRED COMPONENTS OpenGL)
find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)
# Build 3rd Party Libraries
add_subdirectory(lib)
# Define source files.
add_subdirectory(src)
if (MSVC)
string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()
# Treat warnings as errors if enabled.
if (WarningsAsErrors)
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:-Werror>
$<$<CXX_COMPILER_ID:MSVC>:/WX>
)
endif(WarningsAsErrors)
# Set compile flags.
target_compile_options(${PROJECT_NAME} PRIVATE
# Clang
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
-Weverything -fcolor-diagnostics
# Disable specific warnings.
-Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded
-Wno-deprecated-declarations -Wno-exit-time-destructors
-Wno-switch-enum -Wno-weak-vtables -Wno-global-constructors>
# GCC
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wpedantic -fdiagnostics-color=always>
# Visual Studio
$<$<CXX_COMPILER_ID:MSVC>:/W4>
# Enable the clang sanitizer.
$<$<AND:$<CONFIG:Debug>,$<CXX_COMPILER_ID:Clang>,$<PLATFORM_ID:${SANITIZER_OS}>>:${SANITIZER_FLAGS}>
)
# Link against the clang sanitizer.
target_link_options(${PROJECT_NAME} PRIVATE
$<$<AND:$<CONFIG:Debug>,$<CXX_COMPILER_ID:Clang>,$<PLATFORM_ID:${SANITIZER_OS}>>:${SANITIZER_FLAGS}>
)
if (LINUX)
target_link_libraries(${PROJECT_NAME} PRIVATE -lm)
endif()
# Include and link against dependencies.
target_link_libraries(${PROJECT_NAME} PRIVATE OpenGL::GL OpenGL::GLU GLUT::GLUT stb OpenAL SndFile::sndfile BigBalls::Physics lua ${CMAKE_DL_LIBS})
if (GenerateDoxygen)
find_package(Doxygen)
if (DOXYGEN_FOUND)
set(DOXYGEN_IN ${CMAKE_SOURCE_DIR}/.doxyconf)
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} #ONLY)
add_custom_target(doc ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_IN}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM)
endif (DOXYGEN_FOUND)
endif (GenerateDoxygen)
# Symlink or copy the resources to the binary location.
if (NOT DisablePostBuild)
if (NOT CopyResources)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink
${CMAKE_SOURCE_DIR}/res $<TARGET_FILE_DIR:${PROJECT_NAME}>/res)
else()
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/res $<TARGET_FILE_DIR:${PROJECT_NAME}>/res)
endif()
endif()
So FindGLUT is a builtin module
ref: https://cmake.org/cmake/help/latest/module/FindGLUT.html
looking at the source code:
see https://github.com/Kitware/CMake/blob/master/Modules/FindGLUT.cmake
so it seems to use find_path()
find_path(GLUT_INCLUDE_DIR glut.h ${OPENGL_LIBRARY_DIR})
You can try to set GLUT_ROOT or OPENGL_LIBRARY_DIR as default path to help CMake to find the correct one...
ref https://cmake.org/cmake/help/latest/command/find_path.html

Configuring Cmake file for library dependency [duplicate]

Work on Ubuntu 16
I used g++ main.cpp -lpq command for compiler my small project. Now I use Clion and wanna do same what I do with g++. But I can't add compiler flags in cmake file and get compile error.
cmake_minimum_required(VERSION 3.5.1)
project(day_g)
set(CMAKE_CXX_FLAGS "-lpq")
add_definitions(-lpq)
message("CMAKE_CXX_FLAGS is ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(day_g ${SOURCE_FILES})
Also I run only cmake file and get CMAKE_CXX_FLAGS with -lpq flag.
CMAKE_CXX_FLAGS is -lpq
-- Configuring done
-- Generating done
How properly add compiler flags to cmake file?
Flag -l is for linker, not for compiler. This flag is used for link with libraries. CMake has special command target_link_libraries for that purpose:
target_link_libraries(day_g pq)
-lq is not a compiler flag (CFLAGS) but a linker flag.
To pass a library in a CMake project you should use:
target_link_libraries(target_name libraries...)
Note that if you specify 'q' as library the project will link with libq.a or, if you are on windows q.dll.
... in your CMakeLists.txt the correct line to add is:
target_link_libraries(day_g pq)
Note also that when you add a CFLAG you should also "remember" the previous ones that may be added by libraries or by your platform, ie:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
To check the exact flags cmake is passing to compiler or linker you can always run, from the build directory, the following command:
make VERBOSE=1

How to include header files in external library in CMake

I have a C application which is running on Raspberry Pi 3 and currently, I have to build it on PI with Cmake. I am trying to build it on Ubuntu machine. I have added a CMAKE_TOOLCHAIN_FILE as described here.
I could run cmake. -DCMAKE_TOOLCHAIN_FILE without any problem but the "make" command is not successful and it can not find a header file inside one of the external library: "mirsdrapi-rsp". The error message is:
fatal error: mirsdrapi-rsp.h: No such file or directory
#include "mirsdrapi-rsp.h"
^
compilation terminated.
I have created a folder named "lib" and have put the "libmirsdrapi-rsp.so" file inside it.
my CMakeLists.txt is as below:
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -Wextra -v -g -D_XOPEN_SOURCE")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Wextra -v ")
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-v")
set (SDR_API_PATH ${CMAKE_SOURCE_DIR}/lib)
include_directories (include ${SDR_API_PATH})
include_directories("${CMAKE_SOURCE_DIR}/lib")
find_library(mirslocation NAMES mirsdrapi-rsp HINTS ${SDR_API_PATH} NO_CMAKE_FIND_ROOT_PATH)
message(STATUS ${mirslocation})
add_library(mirs STATIC IMPORTED)
set_target_properties(mirs PROPERTIES IMPORTED_LOCATION ${mirslocation})
target_link_libraries (raspberryPiDaemon mirs)
target_link_libraries(raspberryPiDaemon m)
Cmake is printing the right path of the library mirsdrapi-rsp while running "find_library" and as I mentioned I am getting the error message just while running "make" command and not "cmake" command.
My content of CMAKE_TOOLCHAIN_FILE is as below:
# Define our host system
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
# Define the cross compiler locations
SET(CMAKE_C_COMPILER ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc)
# Define the sysroot path for the RaspberryPi distribution in our tools folder
SET(CMAKE_FIND_ROOT_PATH ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot/SET)
# Use our definitions for compiler tools
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Search for libraries and headers in the target directories only
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
add_definitions(-Wall -std=c11)
Anybody knows how I can add the header file from mirsdrapi-rsp library to include path?
I guess that you're setting include_directories to the wrong path (it is set 2 times to ${CMAKE_SOURCE_DIR}/lib which must be the folder of libraries not the header files). Check again the correct location of the missing header file.
More precisely: you need to find the path of mirsdrapi-rsp.h and let CMake know it just like for find_library:
find_path(MIRSDRAPI_INCLUDE_DIRS NAMES mirsdrapi-rsp.h PATHS {proper-location})
if (MIRSDRAPI_INCLUDE_DIRS)
target_include_directories(raspberryPiDaemon PRIVATE ${MIRSDRAPI_INCLUDE_DIRS})
endif()
In addition, you can set the INTERFACE_INCLUDE_DIRECTORIES property to the library like this:
set_property(TARGET mirsdrapi-rsp APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${MIRSDRAPI_INCLUDE_DIRS})
This way, target_include_directories might be unnecessary and target_link_directories should be enough.

CMake: Static and dynamic linking based on BUILD_TYPE

I am developing a small simulation software that depends on two libraries, the GSL and the libconfig. As a build system, I use CMake. For both the GSL and libconfig, I found cmake files and copied them into the cmake/ directory of my project.
The scenario is the following: I want the project to have several different build types, like debug, release, etc., but also a custom one called cluster, which adds -static to the GCC flags and links against the .a libraries of the GSL and the libconfig, which I assume exist.
My CMakeLists.txt looks like this so far:
# version
SET(PACKAGE_VERSION "1.0")
SET(PACKAGE_NAME "INTERFACE")
PROJECT(interface C CXX)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# dirs -----------------------------------------------------
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
FIND_PACKAGE(GSL REQUIRED)
INCLUDE_DIRECTORIES(${GSL_INCLUDE_DIRS})
SET(LIBS ${LIBS} ${GSL_LIBRARIES})
FIND_PACKAGE(LibConfig REQUIRED)
INCLUDE_DIRECTORIES(${LIBCONFIG_INCLUDE_DIRS})
SET(LIBS ${LIBS} ${LIBCONFIG_LIBRARIES})
CONFIGURE_FILE("res/config.h.in" "config.h")
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
SET_DIRECTORY_PROPERTIES(PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES "config.h"
)
# compilation ----------------------------------------------
ADD_EXECUTABLE( interface
interface.c interface.h config.h
helpers.c
output.c
lattice.c
genetic.c
)
# optional CFLAGS
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -std=c99")
SET(CMAKE_C_FLAGS_RELEASE "-O3 -ffast-math")
SET(CMAKE_C_FLAGS_CLUSTER "-O3 -ffast-math -static")
SET(CMAKE_C_FLAGS_DEBUG "-g")
SET(CMAKE_C_FLAGS_PROFILE "-g -ffast-math -pg")
TARGET_LINK_LIBRARIES(interface m ${LIBS})
# installation --------------------------------------------
INSTALL(TARGETS interface DESTINATION bin)
This adds the -static to the compiler, when I use -DCMAKE_BUILD_TYPE=cluster. The thing is, that it still links against the .so versions of the libs, which causes gcc to throw errors. At least the FindLibConfig.cmake scripts sets both a LIBCONFIG_LIBRARY and a LIBCONFIG_STATIC_LIBRARY variable, which I could use.
What is the most elegant or smart way to reach my goal?
Acording to cmake documentation, cmake uses the variable BUILD_SHARED_LIBS to determine the default for add_library().
If you set to ON cmake will assume all add_library() call will be as
add_library(target SHARED lib1 lib2 ...)
For example something like -DBUILD_SHARED_LIBS=ON on the cmake command line may do what you are asking.
I solved it like this:
The User can specify an additional variable -DSTATIC_LINKING=TRUE. Then, the script looks like this. (Only the important parts for the static linking and compilation are shown!)
# determine, whether we want a static binary
SET(STATIC_LINKING FALSE CACHE BOOL "Build a static binary?")
# do we want static libraries?
# When STATIC_LINKING is TRUE, than cmake looks for libraries ending
# with .a. This is for linux only!
IF(STATIC_LINKING)
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
ENDIF(STATIC_LINKING)
# set -static, when STATIC_LINKING is TRUE and set LINK_SEARCH_END_STATIC
# to remove the additional -bdynamic from the linker line.
IF(STATIC_LINKING)
SET(CMAKE_EXE_LINKER_FLAGS "-static")
SET_TARGET_PROPERTIES(surface PROPERTIES
LINK_SEARCH_END_STATIC 1)
ENDIF(STATIC_LINKING)

Resources