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.

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

FlagPurpose
--prefix=<path>Where to install
--with-<lib>Build only this component
--without-<lib>Skip this component
variant=release|debugBuild variant
link=shared|staticLibrary type
threading=multiMulti-threaded
cxxstd=17C++ standard (idiomatic)
-j<N>Parallel build jobs
--layout=systemShort 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-dev on Ubuntu, icu on Arch): Required for full Unicode support in boost::locale and boost::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::python and boost::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 situationUse this
Quick prototype on Linuxapt install libboost-all-dev + find_package
Cross-platform production appvcpkg manifest mode or Conan
Windows-first projectvcpkg manifest mode
Linux CI pipelineSystem package manager in Docker
Need custom build flagsb2 from source
Only using header-only librariesFetchContent with careful dependency management
Reproducible research / Nix shopNix 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_ROOT or -DCMAKE_PREFIX_PATH to 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. b2 will not tell you it failed to find ICU. It builds a crippled boost::locale without 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 boost meta-package. vcpkg install boost pulls all ~160 Boost libraries. Use individual packages like boost-filesystem to 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.

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.