Skip to content

Linking targets

The strategy to link libraries depend on how they have been fetched.

Header-only libraries

Boost header-only libraries can be linked with the Boost::headers interface target:

add_executable(http-client-sync http-client-sync.cpp)
target_link_libraries(http-client-sync Boost::headers)

The advantage of the interface target Boost::headers is that find_package(Boost) also provides this target, so that the "find-or-fetch" pattern works transparently.

find_package(Boost COMPONENTS container)
if (NOT Boost_FOUND)
    include(cmake/FetchBoostContent.cmake)

    # Example fetching Boost.Beast
    FetchBoostContent_Declare(
            boost_beast
            GIT_REPOSITORY https://github.com/boostorg/beast
            GIT_TAG        master
    )
    # fetch library...

This assumes the library was integrated with FetchBoostContent_MakeAvailable or the interface target was created manually with a pattern such as

# Create an interface target for all the include dirs
add_library(boost_headers INTERFACE)
add_library(Boost::headers ALIAS boost_headers)
# <library>_SOURCE_DIRS contains the source dir for all <library> dependencies
foreach (dir ${boost_beast_SOURCE_DIRS})
    target_include_directories(boost_headers INTERFACE ${dir}/include)
endforeach()

Individual interface targets

Header-only modules also provide interface targets representing a single library in their build script.

if (NOT Boost_FOUND)
    add_executable(circular_buffer circular_buffer.cpp)
    target_link_libraries(circular_buffer Boost::circular_buffer)

This assumes the library was integrated with FetchBoostContent_MakeAvailable or the module targets were created manually by including their subdirectories:

FetchBoostContent_Declare(
        boost_circular_buffer
        GIT_REPOSITORY https://github.com/boostorg/circular_buffer
        GIT_TAG        master
)
FetchBoostContent_MakeAvailable(boost_circular_buffer)
FetchBoostContent_Populate(boost_container)
foreach (dir ${boost_container_SOURCE_DIRS})
    add_subdirectory(${dir})
endforeach()

The advantage of these targets is that only include the directories required for a given target are associated with the executable.

However, note that the integration script used by find_package(Boost) is not generated with the usual CMake facilities to export targets. Thus, not all targets available from module CMake build scripts are also provided with find_package(Boost).

In this case, we need special treatment for the case when find_package(Boost) has been used.

Compiled libraries

Targets are provided for modules that require building and linking:

add_executable(container container.cpp)
target_link_libraries(container Boost::container)

This also assumes the library was integrated with FetchBoostContent_MakeAvailable or the module targets were created manually by including their subdirectories. Otherwise, a customized script should be provided to build these modules.

The advantage of targets such as Boost::<module> is that find_package(Boost COMPONENTS <modules>) also provides this target, so that the "find-or-fetch" pattern works transparently.

Summary

When fetching libraries, we usually want to build the libraries as if find_package(Boost) was being used. This allows us to use the targets in such a way that they can be linked transparently, without special treatment for each of the integration methods.

In practice, this means we should generate the Boost::headers and Boost::<module> targets. Boost::headers includes all libraries and Boost::<module> represent individual compiled libraries.

To achieve this, we can usually import the libraries with the following relationship between the strategies presented above:

  1. Use find_package with the required COMPONENTS when possible. Importing a Boost installation is faster than fetching and building all modules.
  2. Use FetchBoostContent_MakeAvailable when possible. This creates compatible targets for header-only (Boost::headers) and compiled libraries (Boost::<module>).
  3. Use FetchBoostContent_MakeAvailable for the library dependencies when possible so that not all libraries have to be included manually.
  4. Add the library include directories to the Boost::headers target when creating targets manually.