CMake Cookbook
上QQ阅读APP看书,第一时间看更新

There is more

Let us now show the use of the object library functionality made available in CMake. We will use the same source files, but modify CMakeLists.txt:

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(recipe-03 LANGUAGES CXX)

add_library(message-objs
OBJECT
Message.hpp
Message.cpp
)

# this is only needed for older compilers
# but doesn't hurt either to have it
set_target_properties(message-objs
PROPERTIES
POSITION_INDEPENDENT_CODE 1
)

add_library(message-shared
SHARED
$<TARGET_OBJECTS:message-objs>
)

add_library(message-static
STATIC
$<TARGET_OBJECTS:message-objs>
)

add_executable(hello-world hello-world.cpp)

target_link_libraries(hello-world message-static)

First, notice that the add_library command changed to add_library(message-objs OBJECT Message.hpp Message.cpp). Additionally, we have to make sure that the compilation to object files generates position-independent code. This is done by setting the corresponding property of the message-objs target, with the set_target_properties command.

The need to explicitly set the POSITION_INDEPENDENT_CODE property for the target might only arise on certain platforms and/or using older compilers.

This object library can now be used to obtain both the static library, called message-static, and the shared library, called message-shared. It is important to note the generator expression syntax used to refer to the object library: $<TARGET_OBJECTS:message-objs>. Generator expressions are constructs that CMake evaluates at generation time, right after configuration time, to produce configuration-specific build output. See also: https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html. We will delve into generator expressions later in Chapter 5, Configure-time and Build-time Operations. Finally, the hello-world executable is linked with the static version of the message library.

Is it possible to have CMake generate the two libraries with the same name? In other words, can both of them be called message instead of message-static and message-shared? We will need to modify the properties of these two targets:

add_library(message-shared
SHARED
$<TARGET_OBJECTS:message-objs>
)
set_target_properties(message-shared
PROPERTIES
OUTPUT_NAME "message"
)

add_library(message-static
STATIC
$<TARGET_OBJECTS:message-objs>
)
set_target_properties(message-static
PROPERTIES
OUTPUT_NAME "message"
)

Can we link against the DSO? It depends on the operating system and compiler:

  1. On GNU/Linux and macOS, it will work, regardless of the chosen compiler.
  2. On Windows, it will not work with Visual Studio, but it will work with MinGW and MSYS2.

Why? Generating good DSOs requires the programmer to limit symbol visibility. This is achieved with the help of the compiler, but conventions are different on different operating systems and compilers. CMake has a powerful mechanism for taking care of this and we will explain how it works in Chapter 10, Writing an Installer.