linkercmakelibconfig

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?


Solution

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