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