[2026] C++ Package Management: Escape Dependency Hell with vcpkg & Conan [#40-1]

[2026] C++ Package Management: Escape Dependency Hell with vcpkg & Conan [#40-1]

이 글의 핵심

vcpkg manifest mode, CMake toolchain, Conan profiles & lockfiles, CI caching, and common CMake errors. Complete guide with real-world examples and production patterns.

Introduction: “How do I add this library?”

Manual downloads and include paths diverge per machine. vcpkg (Microsoft, CMake-first) and Conan (cross-platform, rich profiles) turn dependencies into declared, reproducible builds. Covers: vcpkg.json manifest, triplets, overlays; conanfile.txt/py, profiles, lockfiles; CMake integration; CI; error catalog; best practices.

Table of contents

  1. Dependency hell scenarios
  2. vcpkg complete guide
  3. Conan complete guide
  4. Comparison
  5. Real-world examples
  6. Performance comparison
  7. Common errors
  8. Debugging tips
  9. Best practices
  10. Production patterns
  11. Summary

1. Dependency hell scenarios

Scenario 1: Different paths per developer

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# Dev A (Windows)
set BOOST_ROOT=C:\boost_1_78_0
# Dev B (Linux)
export BOOST_ROOT=/usr/local/boost_1_79_0
# CI (Docker)
# No BOOST_ROOT set, build fails

Scenario 2: Version skew

아래 코드는 cmake를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# Project A needs spdlog 1.9
find_package(spdlog 1.9 REQUIRED)
# Project B (dependency) needs spdlog 1.10
# Conflict! Which version wins?

Scenario 3: Transitive dependencies

다음은 간단한 code 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

Your project
  └─ libA (needs OpenSSL 1.1)
      └─ libB (needs OpenSSL 3.0)
          # Conflict!

Solution: Package managers with dependency resolution. 아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

flowchart LR
  subgraph before[Manual]
    A1[Dev A path] --- X[Mismatch]
    B1[CI path] --- X
  end
  subgraph after[Manager]
    M[vcpkg.json] --> U[Same graph everywhere]
  end

2. vcpkg complete guide

Installation

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# Clone vcpkg
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
# Bootstrap
./bootstrap-vcpkg.sh  # Linux/Mac
.\bootstrap-vcpkg.bat # Windows

Create vcpkg.json in your project root: 아래 코드는 json를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

{
  "name": "my-project",
  "version": "1.0.0",
  "dependencies": [
    "fmt",
    "spdlog",
    {
      "name": "boost-asio",
      "version>=": "1.78.0"
    }
  ],
  "builtin-baseline": "2024-01-15"
}

CMake integration

다음은 cmake를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
# Set toolchain BEFORE project()
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake"
    CACHE STRING "Vcpkg toolchain file")
project(MyProject)
# Now find_package works!
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE fmt::fmt spdlog::spdlog)

Triplets (platform selection)

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# List available triplets
vcpkg help triplet
# Common triplets
x64-linux          # Dynamic linking
x64-linux-static   # Static linking
x64-windows        # Dynamic (DLL)
x64-windows-static # Static
arm64-osx          # Apple Silicon

Specify in vcpkg.json: 아래 코드는 json를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

{
  "name": "my-project",
  "dependencies": [fmt],
  "builtin-baseline": "2024-01-15",
  "overrides": [
    {
      "name": "fmt",
      "version": "10.1.1"
    }
  ]
}

Custom ports (overlays)

다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# Create custom port
mkdir -p custom-ports/my-lib
cd custom-ports/my-lib
# portfile.cmake
vcpkg_from_github(
    OUT_SOURCE_PATH SOURCE_PATH
    REPO myorg/my-lib
    REF v1.0.0
    SHA512 abc123...
)
vcpkg_cmake_configure(SOURCE_PATH ${SOURCE_PATH})
vcpkg_cmake_install()
vcpkg_cmake_config_fixup()

Use overlay:

vcpkg install --overlay-ports=./custom-ports

3. Conan 2 complete guide

Installation

pip install conan
# Detect profile
conan profile detect --force

conanfile.txt (simple)

아래 코드는 ini를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

[requires]
fmt/10.1.1
spdlog/1.12.0
[generators]
CMakeDeps
CMakeToolchain
[options]
fmt/*:shared=False

conanfile.py (advanced)

다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
class MyProjectConan(ConanFile):
    name = "my-project"
    version = "1.0"
    settings = "os", "compiler", "build_type", "arch"
    
    def requirements(self):
        self.requires("fmt/10.1.1")
        self.requires("spdlog/1.12.0")
    
    def build_requirements(self):
        self.tool_requires("cmake/3.27.0")
    
    def layout(self):
        cmake_layout(self)
    
    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()

Install and build

아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# Install dependencies
conan install . --output-folder=build --build=missing
# Configure CMake with Conan toolchain
cmake -B build -S . \
  -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake \
  -DCMAKE_BUILD_TYPE=Release
# Build
cmake --build build

Profiles

다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# View default profile
conan profile show default
# Create custom profile
conan profile detect --name gcc11
conan profile show gcc11
# Edit profile
[settings]
os=Linux
arch=x86_64
compiler=gcc
compiler.version=11
compiler.libcxx=libstdc++11
build_type=Release
[conf]
tools.cmake.cmaketoolchain:generator=Ninja

Lockfiles (reproducibility)

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# Create lockfile
conan lock create . --lockfile-out=conan.lock
# Install with lockfile
conan install . --lockfile=conan.lock --output-folder=build

Binary caching

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# Local cache
conan cache path
# Remote cache (Artifactory)
conan remote add mycompany https://artifactory.mycompany.com/conan
conan remote login mycompany admin -p password
# Upload packages
conan upload "*" -r=mycompany --confirm

4. vcpkg vs Conan (detailed)

FeaturevcpkgConan
CMake integrationToolchain one-linerGenerated toolchain
Binary cachingLocal only (default)Artifactory, S3, etc.
Custom recipesOverlays (CMake-based)conanfile.py (Python)
ProfilesTripletsRich profiles (compiler, flags)
LockfilesBaseline commitconan.lock
EnterpriseGitHub portsPrivate remotes
Learning curveLow (CMake users)Medium (Python DSL)
Cross-compilationTripletsProfiles
VersioningGit baselineSemantic versioning
Recommendation:
  • vcpkg: CMake-first teams, Windows/MSVC, simpler setup
  • Conan: Multi-compiler, binary caching, complex profiles

5. Real-world examples

Example 1: Microservice with vcpkg

다음은 json를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

{
  "name": "api-server",
  "version": "2.1.0",
  "dependencies": [
    "boost-asio",
    "fmt",
    "spdlog",
    "nlohmann-json",
    "openssl",
    {
      "name": "grpc",
      "features": [codegen]
    }
  ],
  "builtin-baseline": "2024-01-15"
}

다음은 cmake를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

find_package(Boost REQUIRED COMPONENTS system)
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(gRPC CONFIG REQUIRED)
add_executable(api-server main.cpp)
target_link_libraries(api-server PRIVATE
    Boost::system
    fmt::fmt
    spdlog::spdlog
    nlohmann_json::nlohmann_json
    OpenSSL::SSL
    gRPC::grpc++
)

Example 2: Game engine with Conan

다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

from conan import ConanFile
class GameEngineConan(ConanFile):
    name = "game-engine"
    version = "1.0"
    settings = "os", "compiler", "build_type", "arch"
    
    def requirements(self):
        self.requires("sdl/2.28.0")
        self.requires("glew/2.2.0")
        self.requires("glm/0.9.9.8")
        self.requires("assimp/5.2.5")
        self.requires("bullet3/3.24")
        
    def configure(self):
        if self.settings.build_type == "Debug":
            self.options[sdl].shared = True
        else:
            self.options[sdl].shared = False

Example 3: CI/CD with GitHub Actions

다음은 yaml를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

name: Build
on: [push, pull_request]
jobs:
  build-vcpkg:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          submodules: true
      
      - name: Cache vcpkg
        uses: actions/cache@v3
        with:
          path: |
            vcpkg/buildtrees
            vcpkg/packages
            vcpkg/downloads
          key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }}
      
      - name: Build
        run: |
          cmake -B build -S . \
            -DCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake
          cmake --build build

6. Performance comparison

Build time comparison (clean build)

ProjectvcpkgConanSystem packages
Small (3 deps)2m 30s1m 45s30s
Medium (10 deps)8m 15s5m 30s2m
Large (30 deps)25m18m8m
Notes:
  • vcpkg builds from source by default
  • Conan uses binary cache when available
  • System packages fastest but not portable

Disk usage

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# vcpkg
~/.vcpkg/          # 5-10 GB
project/vcpkg/     # 2-5 GB per project
# Conan
~/.conan2/         # 3-8 GB
project/build/     # 500 MB - 2 GB

CI cache efficiency

# vcpkg cache hit: 90% faster
# Conan binary cache: 95% faster
# No cache: Full rebuild every time

7. Common errors and fixes

Error 1: Could not find package configuration file

CMake Error at CMakeLists.txt:10 (find_package):
  Could not find a package configuration file provided by "fmt"

Fix:

# Add BEFORE project()
set(CMAKE_TOOLCHAIN_FILE "vcpkg/scripts/buildsystems/vcpkg.cmake")

Error 2: Conan find_package fails

CMake Error: Could not find a package configuration file for spdlog

Fix:

# Forgot to set toolchain
cmake -B build -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake

Error 3: Version conflict

error: version conflict detected
  fmt/9.1.0 (required by A)
  fmt/10.0.0 (required by B)

Fix (vcpkg): 아래 코드는 json를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// 실행 예제
{
  "overrides": [
    {"name": "fmt", "version": "10.0.0"}
  ]
}

Fix (Conan):

def requirements(self):
    self.requires("fmt/10.0.0", override=True)

Error 4: C++ standard mismatch

error: 'std::format' is not a member of 'std'

Fix:

target_compile_features(main PRIVATE cxx_std_20)

Error 5: Triplet not found

Error: Triplet x64-linux-custom not found

Fix:

# Create custom triplet
cp vcpkg/triplets/x64-linux.cmake vcpkg/triplets/community/x64-linux-custom.cmake
# Edit as needed

8. Debugging tips

Tip 1: Visualize dependency graph

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# vcpkg
vcpkg depend-info fmt
# Conan
conan graph info . --format=html > graph.html

Tip 2: Check installed packages

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# vcpkg
vcpkg list
# Conan
conan list "*"

Tip 3: Verbose build

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# vcpkg
vcpkg install --debug
# Conan
conan install . -vv

Tip 4: Clean cache

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# vcpkg
vcpkg remove --outdated
rm -rf vcpkg/buildtrees/*
# Conan
conan remove "*" -c

Tip 5: Inspect generated files

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# vcpkg
cat build/vcpkg_installed/x64-linux/share/fmt/fmtConfig.cmake
# Conan
cat build/conan_toolchain.cmake
cat build/fmtConfig.cmake

9. Best practices

1. Version pinning

아래 코드는 json를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// vcpkg.json
{
  "builtin-baseline": "2024-01-15",  // Pin all versions
  "overrides": [
    {"name": "fmt", "version": "10.1.1"}  // Explicit override
  ]
}
# conanfile.py
def requirements(self):
    self.requires("fmt/10.1.1")  # Exact version

2. Commit manifests, not binaries

아래 코드는 gitignore를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# .gitignore
vcpkg/buildtrees/
vcpkg/packages/
vcpkg/downloads/
build/
.conan2/

다음은 간단한 bash 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# Commit these
git add vcpkg.json
git add conanfile.txt
git add conan.lock

3. Document triplets/profiles

아래 코드는 markdown를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# README.md
## Build instructions
### vcpkg (Windows)
cmake -B build -DVCPKG_TARGET_TRIPLET=x64-windows-static
### Conan (Linux)
conan install . --profile=gcc11 --build=missing

4. Prefer CONFIG mode

아래 코드는 cmake를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# Explicit CONFIG mode
find_package(fmt CONFIG REQUIRED)
# Not this (may find system package)
find_package(fmt REQUIRED)

5. CI caching

아래 코드는 yaml를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# GitHub Actions
- uses: actions/cache@v3
  with:
    path: |
      ~/.conan2
      vcpkg/buildtrees
    key: ${{ runner.os }}-deps-${{ hashFiles('**/conan.lock', 'vcpkg.json') }}

10. Production patterns

Pattern 1: CMakePresets.json

다음은 json를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

{
  "version": 3,
  "configurePresets": [
    {
      "name": "vcpkg-release",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
      }
    },
    {
      "name": "conan-debug",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug",
        "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/build/conan_toolchain.cmake"
      }
    }
  ]
}

Pattern 2: Docker base images

아래 코드는 dockerfile를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

FROM ubuntu:22.04
# Install vcpkg
RUN git clone https://github.com/Microsoft/vcpkg.git /opt/vcpkg && \
    /opt/vcpkg/bootstrap-vcpkg.sh
ENV VCPKG_ROOT=/opt/vcpkg
ENV CMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake
# Pre-install common packages
COPY vcpkg.json /tmp/
RUN cd /tmp && vcpkg install

Pattern 3: Monorepo with shared dependencies

아래 코드는 code를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

monorepo/
├── vcpkg.json          # Shared dependencies
├── service-a/
│   └── CMakeLists.txt
├── service-b/
│   └── CMakeLists.txt
└── CMakeLists.txt      # Root

아래 코드는 cmake를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# Root CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake")
project(Monorepo)
add_subdirectory(service-a)
add_subdirectory(service-b)

11. Summary

vcpkg strengths

  • ✅ Seamless CMake integration
  • ✅ Large port collection (2000+)
  • ✅ Microsoft backing
  • ✅ Simple for CMake users

Conan strengths

  • ✅ Binary caching (Artifactory, S3)
  • ✅ Rich profiles (compiler flags, etc.)
  • ✅ Python-based recipes (flexible)
  • ✅ Cross-platform excellence

When to use what

Keywords

vcpkg, Conan, CMake dependencies, reproducible build, C++ package manager, dependency management

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3