Overview & History
Boost is a collection of over 160 peer-reviewed C++ libraries that serve as a proving ground for additions to the C++ standard. Libraries like shared_ptr, optional, filesystem, and variant all originated in Boost before being adopted into ISO C++. Today, Boost remains essential for features not yet standardized — Asio (networking), Beast (HTTP), Spirit (parsing), and Geometry are among its most popular offerings.
Boost's CMake integration has evolved significantly. Historically, Boost relied on its own build system (b2/bjam), making CMake integration awkward. Since Boost 1.70, the project ships official CMake config-mode files, enabling first-class find_package() support with imported targets like Boost::filesystem.
FindBoost.cmake module handles discovery — but it cannot produce modern imported targets on all platforms. Always prefer config-mode when available.
Finding Boost with find_package
The standard approach uses CMake's find_package() command in config mode (preferred) or module mode (fallback):
# CMakeLists.txt — Finding Boost with components
cmake_minimum_required(VERSION 3.20)
project(MyApp LANGUAGES CXX)
# Prefer config mode (Boost 1.70+)
find_package(Boost 1.74 REQUIRED COMPONENTS filesystem thread system)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE
Boost::filesystem
Boost::thread
Boost::system
)
# Print discovered version and location
message(STATUS "Boost version: ${Boost_VERSION}")
message(STATUS "Boost include: ${Boost_INCLUDE_DIRS}")
message(STATUS "Boost libraries: ${Boost_LIBRARIES}")
When Boost is installed in a non-standard location, guide CMake with hints:
# Point CMake to a custom Boost installation
set(BOOST_ROOT "/opt/boost-1.84" CACHE PATH "Boost installation prefix")
# Or use environment variable
# export BOOST_ROOT=/opt/boost-1.84
# For Windows, specify library architecture
set(Boost_ARCHITECTURE "-x64" CACHE STRING "Boost library architecture suffix")
find_package(Boost 1.84 REQUIRED COMPONENTS json url)
The key variables controlling Boost discovery:
# Force static or shared linkage
set(Boost_USE_STATIC_LIBS ON) # Link static .a/.lib
set(Boost_USE_MULTITHREADED ON) # Use -mt variants
set(Boost_USE_STATIC_RUNTIME OFF) # Don't link static CRT
# Debug discovery issues
set(Boost_DEBUG ON) # Verbose find output
set(Boost_VERBOSE ON) # Even more detail
Header-Only Components
The majority of Boost libraries are header-only — no compiled binary is needed. For these, you only need the include path. Modern CMake provides the Boost::headers target:
# Header-only usage — no COMPONENTS needed
cmake_minimum_required(VERSION 3.20)
project(HeaderOnlyDemo LANGUAGES CXX)
find_package(Boost 1.74 REQUIRED)
add_executable(demo main.cpp)
target_link_libraries(demo PRIVATE Boost::headers)
// main.cpp — Using header-only Boost libraries
#include <boost/optional.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
#include <vector>
int main() {
// Boost.Optional
boost::optional<int> value = 42;
if (value) {
std::cout << "Value: " << *value << "\n";
}
// Boost.Algorithm
std::string text = "Hello, Boost World!";
boost::to_upper(text);
std::cout << text << "\n";
// Boost.LexicalCast
std::string num_str = "3.14159";
double pi = boost::lexical_cast<double>(num_str);
std::cout << "Pi: " << pi << "\n";
return 0;
}
Popular header-only Boost libraries include: Algorithm, Any, Asio (when used header-only), Container, Geometry, Graph, Hana, MPL, Optional, Preprocessor, Range, Spirit, Tokenizer, Tuple, TypeTraits, Uuid, and Variant2.
Compiled Components
Some Boost libraries require compiled binaries. These must be listed as COMPONENTS in find_package():
# Common compiled Boost libraries
cmake_minimum_required(VERSION 3.20)
project(CompiledBoost LANGUAGES CXX)
find_package(Boost 1.74 REQUIRED COMPONENTS
filesystem # Path manipulation, directory iteration
thread # Threading primitives
system # Error codes (dependency of many libs)
program_options # Command-line argument parsing
serialization # Object serialization
log # Logging framework
regex # Regular expressions (prefer std::regex in C++17)
chrono # Time utilities
iostreams # Stream extensions (compression, etc.)
locale # Internationalization
)
add_executable(server server.cpp)
target_link_libraries(server PRIVATE
Boost::filesystem
Boost::thread
Boost::program_options
Boost::log
)
A practical example using Boost.Filesystem and Boost.ProgramOptions together:
// server.cpp — Boost compiled libraries example
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <iostream>
namespace fs = boost::filesystem;
namespace po = boost::program_options;
int main(int argc, char* argv[]) {
po::options_description desc("Allowed options");
desc.add_options()
("help,h", "produce help message")
("dir,d", po::value<std::string>()->default_value("."),
"directory to scan");
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
if (vm.count("help")) {
std::cout << desc << "\n";
return 0;
}
fs::path target_dir(vm["dir"].as<std::string>());
if (!fs::exists(target_dir)) {
std::cerr << "Directory not found: " << target_dir << "\n";
return 1;
}
std::size_t file_count = 0;
for (const auto& entry : fs::recursive_directory_iterator(target_dir)) {
if (fs::is_regular_file(entry)) {
++file_count;
}
}
std::cout << "Found " << file_count << " files in "
<< target_dir << "\n";
return 0;
}
Version Requirements
Specifying version constraints ensures your project gets a compatible Boost installation:
# Exact version
find_package(Boost 1.83.0 EXACT REQUIRED COMPONENTS json)
# Minimum version (most common)
find_package(Boost 1.74 REQUIRED COMPONENTS filesystem)
# Version range (CMake 3.19+)
find_package(Boost 1.74...1.85 REQUIRED COMPONENTS filesystem)
# Check version after discovery
find_package(Boost 1.70 REQUIRED COMPONENTS filesystem)
if(Boost_VERSION VERSION_LESS "1.78")
message(WARNING "Boost < 1.78 — Boost.JSON not available")
endif()
Boost_VERSION variable contains the full string, while Boost_VERSION_MAJOR, Boost_VERSION_MINOR, and Boost_VERSION_PATCH are the individual components.
Boost as Superbuild Dependency
For projects that need to build Boost from source — common in embedded or isolated environments — use ExternalProject or FetchContent:
# Superbuild pattern with ExternalProject
cmake_minimum_required(VERSION 3.20)
project(BoostSuperbuild)
include(ExternalProject)
set(BOOST_VERSION "1.84.0")
string(REPLACE "." "_" BOOST_VERSION_UNDERSCORE ${BOOST_VERSION})
ExternalProject_Add(boost_external
URL "https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION_UNDERSCORE}.tar.gz"
URL_HASH SHA256=cc4b893acf645c9d4b698e9a0f08ca8846aa5d6c68275c14c3e7c949c24109e4
BUILD_IN_SOURCE ON
CONFIGURE_COMMAND ./bootstrap.sh
--prefix=<INSTALL_DIR>
--with-libraries=filesystem,thread,system,program_options
BUILD_COMMAND ./b2
variant=release
link=static
threading=multi
runtime-link=shared
-j8
INSTALL_COMMAND ./b2 install
BUILD_BYPRODUCTS
<INSTALL_DIR>/lib/libboost_filesystem.a
<INSTALL_DIR>/lib/libboost_thread.a
<INSTALL_DIR>/lib/libboost_system.a
)
For a simpler FetchContent approach with header-only usage:
# FetchContent for header-only Boost (lightweight)
cmake_minimum_required(VERSION 3.24)
project(BoostFetch LANGUAGES CXX)
include(FetchContent)
FetchContent_Declare(boost_headers
URL "https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.xz"
URL_HASH SHA256=...
DOWNLOAD_EXTRACT_TIMESTAMP ON
)
FetchContent_MakeAvailable(boost_headers)
add_executable(myapp main.cpp)
target_include_directories(myapp PRIVATE ${boost_headers_SOURCE_DIR})
Common Pitfalls
Boost_USE_STATIC_LIBS and Boost_USE_STATIC_RUNTIME consistently with your project's /MD or /MT flag.
# Windows: Consistent static/shared configuration
if(WIN32)
# If using /MD (shared CRT), use shared Boost
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_STATIC_RUNTIME OFF)
# If using /MT (static CRT), use static Boost
# set(Boost_USE_STATIC_LIBS ON)
# set(Boost_USE_STATIC_RUNTIME ON)
endif()
find_package(Boost 1.74 REQUIRED COMPONENTS filesystem)
Boost::headers target doesn't exist. Fall back to the legacy variables:
# Backward-compatible header-only usage
find_package(Boost 1.65 REQUIRED)
add_executable(myapp main.cpp)
if(TARGET Boost::headers)
# Modern Boost (1.70+)
target_link_libraries(myapp PRIVATE Boost::headers)
else()
# Legacy Boost — use variables
target_include_directories(myapp PRIVATE ${Boost_INCLUDE_DIRS})
endif()
log depends on filesystem, thread, chrono, and system). With imported targets these are handled transitively, but with legacy variables you must list all dependencies explicitly.
# Boost.Log pulls in many dependencies automatically via targets
find_package(Boost 1.74 REQUIRED COMPONENTS log)
add_executable(logger logger.cpp)
# Boost::log transitively links Boost::filesystem, Boost::thread, etc.
target_link_libraries(logger PRIVATE Boost::log)
- Always specify a minimum Boost version in
find_package() - Use imported targets (
Boost::filesystem) not legacy variables - Set
Boost_USE_STATIC_LIBSbefore callingfind_package() - Use
Boost::headersfor header-only usage (cleaner than raw include dirs) - Enable
Boost_DEBUGwhen troubleshooting discovery issues - Prefer system Boost from package managers over manual builds