C++ Package Management
Overview
Package management is an important part of modern software development. It simplifies the process of acquiring, compiling, and integrating third-party libraries. There are multiple package management solutions in the C++ ecosystem. This chapter introduces mainstream package managers and dependency management best practices.
📦 vcpkg Package Manager
Installation and Basic Usage
bash
# Clone vcpkg repository
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
# Windows
.\bootstrap-vcpkg.bat
# Linux/macOS
./bootstrap-vcpkg.sh
# Integrate into system
./vcpkg integrate install
# Search for packages
./vcpkg search boost
./vcpkg search json
# Install packages
./vcpkg install boost
./vcpkg install nlohmann-json
./vcpkg install fmt
# View installed packages
./vcpkg list
# Remove packages
./vcpkg remove boostCMake Integration
cmake
# Method 1: Toolchain file
# cmake -DCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake
# Method 2: Environment variable
# export VCPKG_ROOT=/path/to/vcpkg
# CMakeLists.txt
find_package(fmt CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(Boost REQUIRED COMPONENTS system filesystem)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE
fmt::fmt
nlohmann_json::nlohmann_json
Boost::system
Boost::filesystem
)vcpkg.json Manifest Mode
json
{
"name": "my-application",
"version": "1.0.0",
"description": "My C++ application",
"homepage": "https://github.com/user/my-app",
"documentation": "https://github.com/user/my-app/wiki",
"license": "MIT",
"dependencies": [
{
"name": "boost-system",
"version>=": "1.82.0"
},
{
"name": "nlohmann-json",
"version>=": "3.11.2"
},
"fmt",
"spdlog",
{
"name": "openssl",
"platform": "!uwp"
}
],
"builtin-baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc",
"overrides": [
{
"name": "boost",
"version": "1.82.0"
}
],
"features": {
"tools": {
"description": "Build development tools",
"dependencies": [
"gtest",
"benchmark"
]
}
}
}Custom Ports
cmake
# ports/mylib/portfile.cmake
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO myuser/mylib
REF v1.0.0
SHA512 1234567890abcdef...
HEAD_REF master
)
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
-DBUILD_EXAMPLES=OFF
-DBUILD_TESTS=OFF
)
vcpkg_cmake_build()
vcpkg_cmake_install()
vcpkg_cmake_config_fixup(
CONFIG_PATH lib/cmake/mylib
)
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")🍃 Conan Package Manager
Installation and Basic Usage
bash
# Install Conan
pip install conan
# Detect profile configuration file
conan profile detect --force
# Search for packages
conan search boost
conan search openssl
# Create conanfile.txt
[requires]
boost/1.82.0
openssl/[^1.1]
zlib/1.2.13
[generators]
CMakeDeps
CMakeToolchain
[options]
boost:shared=True
openssl:shared=False
# Install dependencies
conan install . --build=missing
# Use specific profile file
conan install . -pr:b=default -pr:h=my_profile --build=missingCMake Integration
cmake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(MyApp)
# Include Conan generated files
include(${CMAKE_BINARY_DIR}/conan_toolchain.cmake)
find_package(Boost REQUIRED COMPONENTS system filesystem)
find_package(OpenSSL REQUIRED)
find_package(ZLIB REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp
Boost::system
Boost::filesystem
OpenSSL::SSL
OpenSSL::Crypto
ZLIB::ZLIB
)conanfile.py
python
from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps
class MyAppConan(ConanFile):
name = "myapp"
version = "1.0"
# Package configuration
settings = "os", "compiler", "build_type", "arch"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
# Dependencies
def requirements(self):
self.requires("boost/1.82.0")
self.requires("openssl/[^1.1]")
self.requires("fmt/9.1.0")
def build_requirements(self):
self.test_requires("gtest/1.14.0")
def layout(self):
cmake_layout(self)
def generate(self):
deps = CMakeDeps(self)
deps.generate()
tc = CMakeToolchain(self)
tc.generate()
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def package(self):
cmake = CMake(self)
cmake.install()
def package_info(self):
self.cpp_info.libs = ["myapp"]Custom Profile Files
ini
# myprofile
[settings]
os=Linux
arch=x86_64
compiler=gcc
compiler.version=11
compiler.libcxx=libstdc++11
build_type=Release
[options]
[buildenv]
[runenv]
[conf]
tools.system.package_manager:mode=install
tools.system.package_manager:sudo=True🏗️ CPM.cmake
Basic Usage
cmake
# Download CPM.cmake
include(cmake/CPM.cmake)
# Add dependencies
CPMAddPackage("gh:nlohmann/json@3.11.2")
CPMAddPackage("gh:gabime/spdlog@1.12.0")
CPMAddPackage(
NAME fmt
GITHUB_REPOSITORY fmtlib/fmt
GIT_TAG 9.1.0
OPTIONS "FMT_INSTALL ON"
)
CPMAddPackage(
NAME Catch2
GITHUB_REPOSITORY catchorg/Catch2
VERSION 3.4.0
OPTIONS "CATCH_INSTALL_DOCS OFF"
)
# Use dependencies
target_link_libraries(myapp PRIVATE
nlohmann_json::nlohmann_json
spdlog::spdlog
fmt::fmt
Catch2::Catch2WithMain
)Advanced Configuration
cmake
# CPM cache
set(CPM_SOURCE_CACHE $ENV{HOME}/.cache/CPM)
# Local package priority
set(CPM_USE_LOCAL_PACKAGES ON)
# Conditional addition
if(BUILD_TESTING)
CPMAddPackage("gh:google/googletest@1.14.0")
endif()
# Version constraints
CPMAddPackage(
NAME boost_algorithm
URL https://github.com/boostorg/algorithm/archive/boost-1.82.0.tar.gz
VERSION 1.82.0
OPTIONS "BUILD_TESTING OFF"
)
# Source modification
CPMAddPackage(
NAME MyLibrary
GITHUB_REPOSITORY user/mylibrary
GIT_TAG main
PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/patches/mylib.patch
)🔧 Hunter Package Manager
Basic Configuration
cmake
# CMakeLists.txt
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.24.0.tar.gz"
SHA1 "a3d7f4372b1dcd52faa6ff4a3bd5358e1d0e5efd"
)
project(MyProject)
# Find packages
hunter_add_package(Boost COMPONENTS system filesystem)
hunter_add_package(OpenSSL)
hunter_add_package(nlohmann_json)
find_package(Boost CONFIG REQUIRED system filesystem)
find_package(OpenSSL REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
# Link
target_link_libraries(myapp
Boost::system
Boost::filesystem
OpenSSL::SSL
nlohmann_json::nlohmann_json
)Custom Hunter Configuration
cmake
# cmake/Hunter/config.cmake
hunter_config(
Boost
VERSION 1.82.0
CMAKE_ARGS
BUILD_SHARED_LIBS=OFF
BOOST_BUILD_DYNAMIC_VSRUNTIME=OFF
)
hunter_config(
OpenSSL
VERSION 1.1.1
CMAKE_ARGS
OPENSSL_NO_TESTS=ON
)📋 Dependency Management Best Practices
Version Management Strategy
json
// package-lock.json concept
{
"dependencies": {
"boost": {
"version": "1.82.0",
"resolved": "https://github.com/boostorg/boost/releases/tag/boost-1.82.0",
"integrity": "sha512-..."
},
"fmt": {
"version": "9.1.0",
"resolved": "https://github.com/fmtlib/fmt/releases/tag/9.1.0",
"integrity": "sha512-..."
}
}
}Multi-environment Configuration
bash
# Development environment
conan install . -pr:b=default -pr:h=debug --build=missing
# Production environment
conan install . -pr:b=default -pr:h=release --build=missing
# Cross-compilation
conan install . -pr:b=default -pr:h=armv8 --build=missingDependency Conflict Resolution
python
# conanfile.py
def requirements(self):
# Version conflict resolution
self.requires("boost/1.82.0", override=True)
self.requires("openssl/[^1.1]")
# Conditional dependencies
if self.settings.os == "Windows":
self.requires("winsdk/10.0")
elif self.settings.os == "Linux":
self.requires("linux-headers/5.4")
def configure(self):
# Option configuration
if self.options.shared:
self.options["boost"].shared = True
self.options["openssl"].shared = True🔗 Integration Strategies
Mixed Package Management
cmake
# Priority strategy: vcpkg > Conan > system packages > source build
# 1. Try vcpkg
find_package(fmt CONFIG QUIET)
if(NOT fmt_FOUND)
# 2. Try Conan
find_package(fmt REQUIRED)
endif()
if(NOT fmt_FOUND)
# 3. Try system packages
find_package(PkgConfig REQUIRED)
pkg_check_modules(fmt REQUIRED fmt)
endif()
if(NOT fmt_FOUND)
# 4. Build from source
include(FetchContent)
FetchContent_Declare(fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 9.1.0
)
FetchContent_MakeAvailable(fmt)
endif()CI/CD Integration
yaml
# .github/workflows/build.yml
- name: Setup vcpkg
uses: lukka/run-vcpkg@v11
with:
vcpkgGitCommitId: '${{ env.VCPKG_COMMIT_ID }}'
- name: Configure CMake
run: |
cmake -B build \
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \
-DCMAKE_BUILD_TYPE=Release
- name: Cache Conan packages
uses: actions/cache@v3
with:
path: ~/.conan2
key: conan-${{ runner.os }}-${{ hashFiles('conanfile.txt') }}
- name: Install Conan dependencies
run: |
conan install . --build=missing -pr:b=defaultDockerized Dependencies
dockerfile
# Dockerfile.deps
FROM ubuntu:22.04 as deps
RUN apt-get update && apt-get install -y \
cmake ninja-build g++ git python3-pip
# Install vcpkg
RUN git clone https://github.com/Microsoft/vcpkg.git /vcpkg
RUN /vcpkg/bootstrap-vcpkg.sh
# Install dependencies
COPY vcpkg.json /workspace/
WORKDIR /workspace
RUN /vcpkg/vcpkg install
# Main build stage
FROM deps as build
COPY . /workspace
RUN cmake -B build -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake
RUN cmake --build build
FROM ubuntu:22.04 as runtime
RUN apt-get update && apt-get install -y libssl1.1
COPY --from=build /workspace/build/myapp /usr/local/bin/
CMD ["myapp"]Summary
Package Manager Comparison
| Feature | vcpkg | Conan | CPM | Hunter |
|---|---|---|---|---|
| Learning curve | Simple | Medium | Simple | Medium |
| Ecosystem | Rich | Rich | Medium | Medium |
| CMake integration | Excellent | Excellent | Native | Good |
| Cross-platform | Excellent | Excellent | Good | Good |
| Performance | Good | Excellent | Fast | Medium |
Selection Suggestions
- New projects: vcpkg or Conan
- Simple dependencies: CPM.cmake
- Complex projects: Conan
- Windows projects: vcpkg
- Cross-platform: Conan
Best Practices
- Version locking: Use exact version numbers
- Build isolation: Avoid global installation
- Caching strategy: Use CI cache to accelerate builds
- Dependency audit: Regularly check for security vulnerabilities
- Documentation: Clearly document dependency usage and version requirements
Future Trends
- C++20 modules: Changing dependency models
- Standard package manager: Official C++ package manager
- Build caching: Distributed build cache
- Security: Package signing and verification
Package management is the infrastructure of modern C++ development. Choosing the right package manager and establishing standardized dependency management processes is crucial for project success.