[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
- Dependency hell scenarios
- vcpkg complete guide
- Conan complete guide
- Comparison
- Real-world examples
- Performance comparison
- Common errors
- Debugging tips
- Best practices
- Production patterns
- 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
Manifest mode (recommended)
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)
| Feature | vcpkg | Conan |
|---|---|---|
| CMake integration | Toolchain one-liner | Generated toolchain |
| Binary caching | Local only (default) | Artifactory, S3, etc. |
| Custom recipes | Overlays (CMake-based) | conanfile.py (Python) |
| Profiles | Triplets | Rich profiles (compiler, flags) |
| Lockfiles | Baseline commit | conan.lock |
| Enterprise | GitHub ports | Private remotes |
| Learning curve | Low (CMake users) | Medium (Python DSL) |
| Cross-compilation | Triplets | Profiles |
| Versioning | Git baseline | Semantic 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)
| Project | vcpkg | Conan | System packages |
|---|---|---|---|
| Small (3 deps) | 2m 30s | 1m 45s | 30s |
| Medium (10 deps) | 8m 15s | 5m 30s | 2m |
| Large (30 deps) | 25m | 18m | 8m |
| 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
- vcpkg: CMake-first, Windows/MSVC, simpler projects
- Conan: Multi-compiler, binary caching, enterprise scale
- Both: Possible but complex—pick one per repo
Next: CI/CD GitHub Actions (#40-2)
Previous: SIMD & execution (#39-3)
Keywords
vcpkg, Conan, CMake dependencies, reproducible build, C++ package manager, dependency management