How to Install Boost in Any C++ Project: CMake, vcpkg, Conan, and Manual Linking
If you have spent any real time writing C++, you have probably reached for Boost. It has the networking primitives that the standard library still does not ship, a filesystem abstraction that predates std::filesystem, regex engines, random number generators, and about 160 other libraries that fill genuine gaps. But installing it is where things get messy. The wrong approach costs you an afternoon of linker errors and cryptic CMake failures.
This post covers every practical way to get Boost into a C++ project. I have included the exact commands, the CMake snippets that actually work, and the traps that caught me along the way.
What Even Needs Linking?
Boost is not one library. It is a collection of roughly 160 libraries, and they fall into two categories.
Header-only libraries need nothing but an #include. Drop boost/asio.hpp into your file and move on. Examples include asio, beast, hana, mp11, spirit, leaf, pfr, describe, and static_string.
Compiled libraries ship as .so, .dylib, or .a files that you must link against. These include filesystem, program_options, thread, chrono, regex, serialization, locale, log, coroutine, context, json, url, iostreams, date_time, random, graph, wave, test, and python.
One detail that trips people up: boost::system has been mostly header-only since Boost 1.69. If you are on a recent version, you rarely need -lboost_system anymore, even though older tutorials insist on it.
Method 1: CMake find_package with System Boost
The simplest path is installing Boost through your system package manager and letting CMake handle detection.
The CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(MyBoostApp)
find_package(Boost 1.71 REQUIRED COMPONENTS filesystem program_options)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE
Boost::filesystem
Boost::program_options
Boost::boost # header-only libraries
)
For a header-only project, skip COMPONENTS entirely:
find_package(Boost 1.71 REQUIRED)
target_link_libraries(my_app PRIVATE Boost::boost)
Boost::boost is the legacy target name. Since CMake 3.15, Boost::headers is an alias for the same thing.
Controlling Which Variant CMake Finds
Set these variables before find_package:
set(Boost_USE_STATIC_LIBS ON) # prefer .a over .so
set(Boost_USE_DEBUG_LIBS OFF) # skip debug builds
set(Boost_USE_MULTITHREADED ON) # prefer multi-threaded variants
If CMake picks the wrong Boost installation, force it:
cmake -B build -DBOOST_ROOT=/usr/local/boost-1.91
cmake -B build -DCMAKE_PREFIX_PATH=/usr/local/boost-1.91
Installing Boost on Every Platform
Ubuntu and Debian:
# Full Boost (headers + all compiled libs, shared and static)
sudo apt install libboost-all-dev
# Headers only
sudo apt install libboost-dev
# Specific components only
sudo apt install libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev
Ubuntu versions ship different Boost releases: 20.04 has 1.71, 22.04 has 1.74, and 24.04 has 1.83. If you need a newer version, skip the system package and build from source or use Conan.
One warning: libboost-all-dev pulls in roughly 500 MB of packages. Install individual libboost-<component>-dev packages unless you genuinely need everything.
Ubuntu’s -dev packages ship both shared (.so) and static (.a) libraries. You do not need to build from source just to get static linking.
Fedora and RHEL:
sudo dnf install boost-devel # full Boost
sudo dnf install boost-filesystem boost-program-options # specific
sudo dnf install boost-static # static libs
Arch Linux:
sudo pacman -S boost boost-libs
boost contains the development headers. boost-libs contains the compiled shared libraries. Arch keeps them separate, which is useful when you want headers without 40 .so files.
macOS with Homebrew:
brew install boost
Homebrew’s formula builds with link=shared,static, so both .dylib and .a files are installed. CMake finds it automatically through Homebrew’s prefix paths. Files live under /opt/homebrew on Apple Silicon and /usr/local on Intel Macs.
Windows with vcpkg (classic mode):
git clone https://github.com/Microsoft/vcpkg.git C:\vcpkg
cd C:\vcpkg
.\bootstrap-vcpkg.bat
# Install specific libraries
.\vcpkg install boost-filesystem:x64-windows # shared
.\vcpkg install boost-filesystem:x64-windows-static # static
# One-time CMake integration
.\vcpkg integrate install
# Build with:
cmake -B build -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
Windows with Chocolatey:
choco install cmake boost-msvc-14.3
Chocolatey ships pre-built MSVC binaries, but vcpkg is generally the better choice. It resolves dependencies, supports version pinning, and works across platforms.
Method 2: CMake FetchContent
FetchContent downloads dependencies at configure time. Using it for Boost sounds convenient. It is not.
Why FetchContent Fails with Boost
Boost’s official repository is a superproject with its own build system (b2), not CMake. There is no top-level CMakeLists.txt you can feed to FetchContent directly.
Three workarounds exist, but none handle compiled libraries well.
Option A: The boost-cmake community mirror
include(FetchContent)
FetchContent_Declare(
boost_cmake
GIT_REPOSITORY https://github.com/boost-cmake/boost-cmake
GIT_TAG 1.87.0
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(boost_cmake)
This repackages Boost with CMake build files. It works for some components but lags behind official releases and does not cover every compiled library. Treat it as a convenience for simple cases only.
Option B: Fetch individual header-only repos
Each Boost library lives in its own repository under boostorg/. Some now ship CMakeLists.txt files:
FetchContent_Declare(
boost_asio
GIT_REPOSITORY https://github.com/boostorg/asio.git
GIT_TAG boost-1.91.0
GIT_SHALLOW TRUE
)
FetchContent_Declare(
boost_beast
GIT_REPOSITORY https://github.com/boostorg/beast.git
GIT_TAG boost-1.91.0
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(boost_asio boost_beast)
In practice this is fragile. Asio’s CMakeLists.txt links to Boost::system, which links to Boost::assert, Boost::config, and several others. You need to fetch the entire dependency tree manually. Use a real package manager instead.
Option C: CPM.cmake
file(DOWNLOAD
https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake
${CMAKE_BINARY_DIR}/cmake/CPM.cmake
)
include(${CMAKE_BINARY_DIR}/cmake/CPM.cmake)
CPMAddPackage("gh:boostorg/asio@boost-1.91.0")
CPMAddPackage("gh:boostorg/beast@boost-1.91.0")
Same limitations apply. CPM is a nicer syntax wrapper around FetchContent, but it does not solve the transitive dependency problem.
Verdict: FetchContent works for a handful of header-only Boost libraries if you carefully manage dependencies. For anything that needs compilation, use find_package, vcpkg, or Conan.
Method 3: Manual g++ Linking
Sometimes you do not want a build system. You just want to compile and move on.
Header-Only Usage
g++ -std=c++17 -I/usr/include -o my_app main.cpp
No -l flags needed. Just #include <boost/asio.hpp> and you are done.
Compiled Library Usage
g++ -std=c++17 -I/usr/include \
-L/usr/lib/x86_64-linux-gnu \
-lboost_filesystem \
-lboost_program_options \
-o my_app main.cpp
On Debian-based distros, libraries live under /usr/lib/x86_64-linux-gnu/, not /usr/lib/.
Static Linking
g++ -std=c++17 -I/usr/include \
/usr/lib/x86_64-linux-gnu/libboost_filesystem.a \
/usr/lib/x86_64-linux-gnu/libboost_program_options.a \
-lpthread \
-o my_app main.cpp
Library Naming Conventions
Boost library files follow a predictable pattern:
ls /usr/lib/x86_64-linux-gnu/libboost_filesystem*
# /usr/lib/x86_64-linux-gnu/libboost_filesystem.a
# /usr/lib/x86_64-linux-gnu/libboost_filesystem.so -> libboost_filesystem.so.1.83.0
# /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.83.0
The linking flag drops the lib prefix and extension. If you built from source with --layout=versioned, names look like libboost_filesystem-gcc14-mt-x64-1_91.so. With --layout=system, they are the short form shown above.
Link Order Matters
The linker resolves undefined symbols when it encounters a library. If the library appears before the code that needs it, there are no undefined symbols yet, so nothing is extracted:
# WRONG — undefined reference errors
g++ -lboost_filesystem -lboost_system main.cpp -o my_app
# CORRECT — libraries after the code that uses them
g++ main.cpp -lboost_filesystem -lboost_system -o my_app
Transitive Dependencies
boost::filesystem depends on boost::system and sometimes boost::atomic. With Boost 1.69+, boost::system is almost entirely header-only, so the transitive dependency is usually satisfied without an extra -l flag. If you use boost::thread, add -lpthread on Linux.
Method 4: vcpkg Manifest Mode
vcpkg manifest mode is the cleanest approach for cross-platform projects. You declare dependencies in a JSON file, and vcpkg handles download, build, and CMake integration.
Create a vcpkg.json in your project root:
{
"name": "my-boost-app",
"version": "1.0.0",
"dependencies": [
"boost-filesystem",
"boost-program-options",
"boost-asio",
"boost-beast"
]
}
Your CMakeLists.txt stays the same as Method 1:
cmake_minimum_required(VERSION 3.16)
project(MyBoostApp)
find_package(Boost REQUIRED COMPONENTS filesystem program_options)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE
Boost::filesystem
Boost::program_options
Boost::boost
)
Add vcpkg as a git submodule and configure:
git submodule add https://github.com/Microsoft/vcpkg.git
cd vcpkg && ./bootstrap-vcpkg.sh && cd ..
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE=${PWD}/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_TARGET_TRIPLET=x64-linux
cmake --build build
On Windows:
cmake -B build -S . `
-DCMAKE_TOOLCHAIN_FILE="$PWD/vcpkg/scripts/buildsystems/vcpkg.cmake" `
-DVCPKG_TARGET_TRIPLET=x64-windows
vcpkg manifest mode gives you reproducible builds without a separate install step. Dependencies live in version control. vcpkg resolves transitive dependencies automatically.
For pinning exact versions, add an overrides block:
{
"overrides": [
{ "name": "boost-filesystem", "version": "1.91.0" }
]
}
Important: vcpkg has a boost meta-package that installs all ~160 Boost libraries at once. Avoid it unless you genuinely need everything; it will compile for well over an hour.
Method 5: Conan
Conan is popular in professional environments with complex dependency graphs.
Install Conan:
pip install conan
Create a conanfile.txt:
[requires]
boost/1.91.0
[generators]
CMakeDeps
CMakeToolchain
Install dependencies:
mkdir build && cd build
conan install .. --build=missing
The --build=missing flag tells Conan to compile Boost from source if it does not have a pre-built binary for your compiler and platform. The first build can take 30 to 60 minutes. After that, Conan caches the result.
Your CMakeLists.txt remains identical to the find_package approach. Build with:
cmake --preset conan-release
cmake --build --preset conan-release
For finer control, use a conanfile.py:
from conan import ConanFile
class MyAppConan(ConanFile):
name = "my-app"
version = "1.0"
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeDeps", "CMakeToolchain"
def requirements(self):
self.requires("boost/1.91.0")
def configure(self):
self.options["boost"].shared = False # static libraries
self.options["boost"].without_locale = True # skip locale
self.options["boost"].without_mpi = True # skip MPI
Excluding unused components saves significant build time. A full Boost Conan build compiles every library; disabling components can cut that time in half.
Note: Conan 2.x introduced breaking changes from 1.x. The snippets above use Conan 2 syntax.
Method 6: Building from Source with b2
When you need a configuration that package managers do not offer, build Boost yourself.
Download and extract:
wget https://archives.boost.io/release/1.91.0/source/boost_1_91_0.tar.gz
tar xzf boost_1_91_0.tar.gz
cd boost_1_91_0
Bootstrap the build system:
./bootstrap.sh --prefix=/usr/local/boost-1.91
On Windows, run bootstrap.bat.
Build only what you need:
./b2 install \
--prefix=/usr/local/boost-1.91 \
--with-filesystem \
--with-program_options \
variant=release \
link=shared \
threading=multi \
-j$(nproc)
For a full build with both shared and static libraries:
./b2 install \
--prefix=/usr/local/boost-1.91 \
variant=release \
link=shared,static \
threading=multi \
cxxstd=17 \
-j$(nproc)
Notice cxxstd=17 instead of cxxflags="-std=c++17". Both work, but cxxstd is the idiomatic b2 feature. It adjusts the C++ standard flag in a toolset-aware way.
Key b2 Flags
| Flag | Purpose |
|---|---|
--prefix=<path> | Where to install |
--with-<lib> | Build only this component |
--without-<lib> | Skip this component |
variant=release|debug | Build variant |
link=shared|static | Library type |
threading=multi | Multi-threaded |
cxxstd=17 | C++ standard (idiomatic) |
-j<N> | Parallel build jobs |
--layout=system | Short library names |
Use --layout=system for clean names like libboost_filesystem.so. The default versioned layout produces names like libboost_filesystem-gcc14-mt-x64-1_91.so.1.91.0, which is useful for side-by-side installs but harder to reference manually.
After installing, point CMake at your custom build:
cmake -B build -DCMAKE_PREFIX_PATH=/usr/local/boost-1.91
Build Dependencies
Several Boost components need external libraries:
- ICU (
libicu-devon Ubuntu,icuon Arch): Required for full Unicode support inboost::localeandboost::regex. - OpenSSL: Required for SSL/TLS support in
boost::asio. - zlib / bzip2: Required for compression filters in
boost::iostreams. - Python dev headers: Required for
boost::pythonandboost::numpy.
Pass custom paths to b2 with flags like -sICU_PATH=/usr or -sOPENSSL_ROOT=/path/to/openssl.
A full Boost source build takes 15 to 45 minutes depending on your CPU. Use --with-<lib> to build only what you need.
Method 7: Nix and NixOS
If you use Nix, Boost is a one-liner:
nix-shell -p boost
For a project shell:
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = [ pkgs.boost ];
}
CMake picks it up through CMAKE_PREFIX_PATH automatically.
Method 8: Docker and Dev Containers
For reproducible CI builds:
FROM ubuntu:24.04
RUN apt update && apt install -y build-essential cmake libboost-all-dev
Then use find_package(Boost) as in Method 1. Docker avoids platform-specific headaches entirely.
Which Method Should You Use?
| Your situation | Use this |
|---|---|
| Quick prototype on Linux | apt install libboost-all-dev + find_package |
| Cross-platform production app | vcpkg manifest mode or Conan |
| Windows-first project | vcpkg manifest mode |
| Linux CI pipeline | System package manager in Docker |
| Need custom build flags | b2 from source |
| Only using header-only libraries | FetchContent with careful dependency management |
| Reproducible research / Nix shop | Nix shell |
Common Pitfalls
- Link order. Put Boost libraries after your object files on the
g++command line. The linker resolves undefined symbols when it encounters a library. If the library comes first, there are no undefined symbols yet, so nothing is extracted. - Wrong Boost installation. If CMake finds Boost 1.71 when you installed 1.91, you have multiple versions on the system. Use
-DBOOST_ROOTor-DCMAKE_PREFIX_PATHto pick the right one. - Using FetchContent for compiled Boost. Do not. Individual repos have transitive CMake dependencies that are painful to chase manually. Use a package manager.
- ICU or OpenSSL not installed.
b2will not tell you it failed to find ICU. It builds a crippledboost::localewithout Unicode support. Install the dev packages first. - Debug or release mismatch on Windows. If your CMake build type is Debug but your vcpkg triplet is
x64-windows(which installs release libs), linking fails. Match them or use mixed triplets. - vcpkg
boostmeta-package.vcpkg install boostpulls all ~160 Boost libraries. Use individual packages likeboost-filesystemto avoid a multi-hour build.
Frequently Asked Questions
What is the latest stable Boost release?
As of May 2026, the latest stable Boost release is 1.91.0, released on April 22, 2026.
Is Boost header-only?
Some Boost libraries are header-only (like asio, beast, mp11), but about 40 libraries require compilation and linking (like filesystem, thread, regex, json). Check the list at the top of this post.
How do I link Boost statically with CMake?
Set set(Boost_USE_STATIC_LIBS ON) before find_package(Boost ...). On Ubuntu, the -dev packages already include .a files. On macOS, Homebrew installs both .dylib and .a by default.
Can I use FetchContent with Boost?
Only for individual header-only libraries, and even then you must manually fetch all transitive dependencies. For compiled Boost libraries, use vcpkg, Conan, or find_package with a system installation.
What is the difference between vcpkg classic mode and manifest mode?
Classic mode installs packages globally through the command line (vcpkg install boost-filesystem). Manifest mode uses a vcpkg.json file in your project root, making dependencies reproducible and version-controlled. Manifest mode is recommended for new projects.
How long does it take to build Boost from source?
A full build of all libraries takes 15 to 45 minutes depending on your CPU. Building only the libraries you need with --with-<lib> cuts this down significantly.