I have tried git submodules, ExternalProject, FetchContent and other approaches for getting our dependencies (including boost). I now use vcpkg and I am pretty content. I have not used Conan or Spack but I the impression they are great too. As a result, I would recommend using a package manger.
To get boost using vcpkg in manifest mode you:
- Add vcpkg as a submodule of your repository and bootstrap it (see https://vcpkg.io/en/getting-started).
- Add a vcpkg.json file with your dependencies to the top level of your project.
- Ensure that
CMAKE_TOOLCHAIN_FILE
is set to the vcpkg toolchain file and your toolchain file is chain-loaded (if you have one) by setting VCPKG_CHAINLOAD_TOOLCHAIN_FILE
.
A vcpkg.json file might look like:
{
"name": "sample",
"builtin-baseline":"030c53833b977f1580b2a4817bb22edbdde606d4",
"version": "13.0.0",
"dependencies": [
"benchmark",
"boost-asio",
"boost-container",
"boost-date-time",
"boost-filesystem",
"boost-histogram",
"boost-thread"
]
}
A CMakePresets.json might then look something like (if you are not using CMakePresets.json files, you will need to adjust whatever you use to control the toolchain file):
{
"version": 3,
"configurePresets": [
{
"name": "sample-defaults",
"hidden": true,
"binaryDir": "${sourceParentDir}/build/${sourceDirName}-${presetName}",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake",
"VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/scripts/clang17.cmake"
}
},
...
Then you just find_package()
in your CMakeLists.txt:
cmake_minimum_required(VERSION 3.21)
project(
Sample-ThirdParty
LANGUAGES CXX
VERSION 2023.0.0
)
find_package(Boost REQUIRED COMPONENTS container filesystem thread)
...
Admittedly the following (taken from link provided by @sehe) seems to work pretty well:
cmake_minimum_required(VERSION 3.21)
project(boost_test)
include(FetchContent)
set(BOOST_ENABLE_CMAKE ON)
FetchContent_Declare(build_boost
GIT_REPOSITORY https://github.com/boostorg/boost.git
GIT_TAG boost-1.82.0
)
FetchContent_GetProperties(build_boost)
if(NOT build_boost_POPULATED)
FetchContent_Populate(build_boost)
add_subdirectory(
${build_boost_SOURCE_DIR}
${build_boost_BINARY_DIR}
EXCLUDE_FROM_ALL
)
endif()
add_executable(boost_test boost_test.cpp)
target_link_libraries(boost_test PRIVATE Boost::format)
However, I don't think I would go back to using FetchContent. Now that we have vcpkg set up for our project means that we can experiment with new dependencies trivially. I like that the dependencies are documented in a single location. It also keeps the CMakeLists.txt file(s) as simple as possible.
I realise that I now have an extra dependency, that is vcpkg. However, my view is that the maintainers of vcpkg are providing more value than it costs me to manage vcpkg. Some of the things they provide:
- Unified control over settings such as static linking.
- Good defaults for projects (eg NLopt defaults to building bindings for several other languages but these are disabled).
- Transitive dependencies.
- Testing of compatibility of libraries with each other.