Skip to content

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 boost

CMake 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=missing

CMake 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=missing

Dependency 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=default

Dockerized 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

FeaturevcpkgConanCPMHunter
Learning curveSimpleMediumSimpleMedium
EcosystemRichRichMediumMedium
CMake integrationExcellentExcellentNativeGood
Cross-platformExcellentExcellentGoodGood
PerformanceGoodExcellentFastMedium

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
  • 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.

Content is for learning and research only.