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:
- Use
find_packagewith the requiredCOMPONENTSwhen possible. Importing a Boost installation is faster than fetching and building all modules. - Use
FetchBoostContent_MakeAvailablewhen possible. This creates compatible targets for header-only (Boost::headers) and compiled libraries (Boost::<module>). - Use
FetchBoostContent_MakeAvailablefor the library dependencies when possible so that not all libraries have to be included manually. - Add the library include directories to the
Boost::headerstarget when creating targets manually.