C++ 패키지 관리 실무: vcpkg와 Conan으로 외부 라이브러리 의존성 지옥 탈출
들어가며: “이 라이브러리 어떻게 넣지?”
헤더 하나 쓰려고 경로 지옥
CMake와 패키지 매니저 개요를 다뤘다면, 40번은 프로젝트 전체 생명 주기를 자동화합니다. 그 첫 단계가 외부 라이브러리다. 수동으로 다운로드·빌드·include 경로를 맞추다 보면 팀원마다 환경이 달라지며, 버전이 꼬입니다.
vcpkg와 Conan은 “필요한 패키지와 버전을 선언하면, 빌드에 맞게 가져와서 경로를 잡아 주는” 도구다. vcpkg는 Microsoft 주도로 CMake와 잘 통합되고, Conan은 크로스 플랫폼·멀티 컴파일러 지원이 강점입니다. 둘 다 재현 가능한 빌드(같은 소스·설정으로 어디서나 같은 결과를 얻는 빌드)의 기반이 됩니다.
같은 문제를 다른 생태계에서는 Python pip·uv·Poetry·npm·Go 모듈·Rust Cargo가 풀고, 빌드 생성기는 CMake가 자주 사용됩니다. 전체 그림은 빌드 시스템 비교, 개별 심화는 vcpkg·Conan 글을 이어서 보세요.
vcpkg의 Manifest 모드·Triplet·CMake 연동과 Conan의 conanfile·프로필을 같은 프로젝트 기준으로 비교하고, 의존성 충돌과 빌드 실패 사례, 팀 규모와 CI 환경에 따른 선택 기준을 정리합니다.
개념을 잡는 비유
빌드·검사·배포 파이프라인은 공장 검수 라인과 비슷합니다. 같은 입력이면 같은 산출물이 나오게 고정하며, Sanitizer·정적 분석은 출하 전 불량 검사 역할을 합니다.
의존성 지옥: 설치 경로·버전·플랫폼 불일치
실제 겪는 상황
"팀원 A는 /usr/local에 설치했는데, 나는 /opt에 설치했습니다."
"Windows에서 빌드되던 게 Linux에서 안 돼요."
"spdlog 1.10으로 빌드했는데, 배포 서버는 1.8입니다."
"find_package(Boost)가 실패해요. Boost는 어디에 있죠?"
"의존성 A는 C++17, 의존성 B는 C++14인데 충돌해요."
원인 분석
- 경로 불일치: 팀원마다 라이브러리 설치 경로가 다름
- 버전 불일치: 개발/CI/운영 환경의 라이브러리 버전 차이
- 플랫폼 차이: Windows/Linux/macOS에서 빌드 설정이 다름
- 의존성 트리: A가 B를, B가 C를 요구하는데 수동으로 맞추기 어려움
추가 문제 시나리오
시나리오 5: 새 팀원 온보딩
"저도 빌드해보고 싶은데, Boost랑 OpenSSL을 어디서 받아야 해요?"
"제가 설치한 버전이 다른데, 왜 제 환경에서는 에러가 나죠?"
수동 설치 환경에서는 새 팀원이 프로젝트를 빌드하는 데 몇 시간이 걸릴 수 있습니다. vcpkg/Conan + README 한 줄이면 cmake -B build -S . 한 번에 끝납니다.
시나리오 6: CI에서 빌드 실패
"로컬에서는 되는데 GitHub Actions에서만 실패해요."
"캐시를 비우므로 갑자기 빌드가 깨졌습니다."
로컬에만 설치된 라이브러리에 의존하면 CI는 실패합니다. Manifest 모드나 conanfile로 의존성을 코드에 포함하면 CI 환경에서도 동일하게 빌드됩니다.
시나리오 7: 의존성 트리 복잡도
프로젝트 → A → B → C
→ D → C
A와 D가 각각 C를 요구하는데, 버전이 다르면 “어떤 C를 쓸까?” 문제가 발생합니다. vcpkg와 Conan은 의존성 해결을 자동으로 수행합니다.
해결 방향
선언적 의존성 관리: vcpkg.json 또는 conanfile.txt에 “필요한 패키지와 버전”만 적어 두면, 도구가 자동으로 다운로드·빌드·경로 설정을 해 줍니다. 코드와 함께 버전 관리되므로 재현 가능한 빌드가 가능해집니다.
flowchart LR
subgraph before[수동 관리]
B1[개발자A] --> B2[경로A]
B3[개발자B] --> B4[경로B]
B5[CI] --> B6[경로C]
B2 -.->|불일치| B4
B4 -.->|불일치| B6
end
subgraph after[패키지 매니저]
A1[vcpkg.json] --> A2[동일 의존성]
A2 --> A3[개발자A]
A2 --> A4[개발자B]
A2 --> A5[CI]
end
주의사항: 여전히 triplet/프로필(OS·아키텍처) 차이는 남으므로, CI용 triplet을 문서화해야 합니다.
vcpkg 사용하기
설치
# Linux/macOS: vcpkg 클론 후 bootstrap
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
# Windows (PowerShell)
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
설치 후: vcpkg 실행 파일이 ./vcpkg(Unix) 또는 vcpkg.exe(Windows)로 생성됩니다. PATH에 추가하거나 절대 경로로 사용합니다.
Manifest 모드 (권장)
Manifest 모드에서는 프로젝트 루트에 vcpkg.json을 두고 의존성을 선언합니다. CMake 설정 시 vcpkg가 자동으로 해당 패키지들을 빌드·설치합니다. “프로젝트가 필요한 패키지 목록”이 코드와 함께 버전 관리되므로 재현 가능한 빌드에 유리합니다.
프로젝트 구조 예시
my-app/
├── CMakeLists.txt
├── vcpkg.json # 의존성 선언
└── src/
└── main.cpp
vcpkg.json
{
"name": "my-app",
"version": "1.0.0",
"description": "vcpkg Manifest 모드 예제",
"dependencies": [
"fmt",
"spdlog",
{
"name": "openssl",
"version>=": "3.0.0"
}
],
"builtin-baseline": "<vcpkg 저장소의 40자리 커밋 SHA>"
}
설명:
dependencies: 필요한 패키지 목록. 문자열만 적으면 baseline이 가리키는 버전을 사용version>=: 최소 버전 지정builtin-baseline: vcpkg 저장소의 특정 커밋 해시(40자리 전체). 재현 가능한 빌드를 위해 권장.vcpkg x-update-baseline --add-initial-baseline으로 현재 커밋을 자동으로 채울 수 있음
baseline의 역할을 이해하면 vcpkg의 버전 선택이 예측 가능해집니다. vcpkg는 “최신 버전”을 가져오는 것이 아니라, baseline 커밋 시점에 각 포트가 가리키던 버전을 기준으로 삼고, version>= 제약이 있으면 그보다 높은 버전만 올려 씁니다. 그래서 같은 vcpkg.json이라면 언제 어디서 빌드해도 같은 버전 조합이 나옵니다. 반대로 baseline 없이 manifest를 쓰면 로컬에 클론한 vcpkg 저장소의 현재 상태에 따라 버전이 달라지고, version>=를 쓰는 순간 error: ... requires a baseline 에러가 납니다.
CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
# vcpkg 툴체인: 반드시 project() 이전에 설정해야 적용됨
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "Vcpkg toolchain file")
project(my-app VERSION 1.0.0 LANGUAGES CXX)
add_executable(my-app src/main.cpp)
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
target_link_libraries(my-app PRIVATE
fmt::fmt
spdlog::spdlog
)
# C++17
target_compile_features(my-app PRIVATE cxx_std_17)
핵심: CMAKE_TOOLCHAIN_FILE을 vcpkg의 vcpkg.cmake로 지정하면, find_package가 vcpkg가 설치한 경로를 자동으로 사용합니다.
툴체인 파일은 project()가 컴파일러를 감지할 때 읽히므로, project() 뒤에서 set(CMAKE_TOOLCHAIN_FILE ...)을 하면 아무 효과가 없고 find_package(fmt)가 “Could not find a package configuration file”로 실패합니다. 이미 한 번 configure한 빌드 디렉터리에서는 툴체인을 나중에 바꿔도 캐시 때문에 반영되지 않으므로, 설정을 바꾼 뒤에는 build/ 디렉터리를 지우고 다시 configure하는 것이 안전합니다. 명령줄의 -DCMAKE_TOOLCHAIN_FILE이나 CMakePresets.json에 두는 방식이 이런 순서 문제를 피하기 쉽습니다.
main.cpp (실행 가능 예제)
#include <spdlog/spdlog.h>
#include <fmt/core.h>
int main() {
spdlog::info("vcpkg Manifest 모드로 빌드됨");
spdlog::info("fmt 예제: {}", fmt::format("Hello, {}!", "vcpkg"));
return 0;
}
빌드 절차
# 1. vcpkg를 프로젝트에 서브모듈로 추가한 경우
git submodule add https://github.com/Microsoft/vcpkg.git vcpkg
# 2. CMake 설정 (vcpkg가 자동으로 의존성 설치)
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="$(pwd)/vcpkg/scripts/buildsystems/vcpkg.cmake"
# 3. 빌드
cmake --build build
./build/my-app
실행 결과: [info] vcpkg Manifest 모드로 빌드됨 등이 출력됩니다.
Triplet
Triplet은 플랫폼·아키텍처·빌드 타입을 지정합니다.
| Triplet | 설명 |
|---|---|
x64-windows | Windows 64비트 |
x64-windows-static | Windows 64비트 정적 링크 |
x64-linux | Linux 64비트 |
arm64-osx | macOS Apple Silicon |
x64-osx | macOS Intel |
# 특정 triplet 사용
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE="$(pwd)/vcpkg/scripts/buildsystems/vcpkg.cmake" \
-DVCPKG_TARGET_TRIPLET=x64-windows-static
CI에서 여러 triplet을 돌리면 멀티 플랫폼 빌드가 가능합니다.
Classic 모드 (레거시)
Classic 모드에서는 vcpkg install로 전역 설치합니다. Manifest 모드보다 재현성이 떨어지므로, 신규 프로젝트는 Manifest 모드를 권장합니다.
vcpkg install fmt spdlog
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
vcpkg 오버레이 (사내 포트)
vcpkg 공식 레지스트리에 없는 라이브러리나, 사내에서 수정한 포트를 사용할 때 오버레이를 씁니다.
# 오버레이 경로 지정
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_OVERLAY_PORTS=/path/to/my-ports
오버레이 디렉터리 구조:
my-ports/
└── my-internal-lib/
├── portfile.cmake
└── vcpkg.json
vcpkg 버전 제약 문법
vcpkg.json에서 버전을 세밀히 제어할 수 있습니다.
{
"dependencies": [
"fmt",
{
"name": "spdlog",
"version>=": "1.11.0"
},
{
"name": "openssl",
"version>=": "3.0.0",
"platform": "!windows"
}
],
"overrides": [
{ "name": "fmt", "version": "10.1.1" }
]
}
version>=: 최소 버전overrides: 특정 버전으로 정확히 고정 (최소 버전 규칙을 무시하고 이 버전을 사용)platform: 특정 플랫폼에서만 의존성 추가 (!windows= Windows 제외)
vcpkg에는 version< 같은 상한 제약이 없습니다. npm이나 Cargo의 범위 지정에 익숙하면 “2.0 미만”을 쓰고 싶어지지만, vcpkg는 최소 버전(version>=)과 baseline, 그리고 정확한 고정(overrides)만으로 버전을 정합니다. 그래서 “이 라이브러리가 새 메이저 버전으로 올라가면 곤란하다”는 요구는 baseline을 올릴 때 변경 내역을 확인하거나 overrides로 고정하는 방식으로 풉니다. 버전 선택 규칙이 단순한 대신, 의존성 트리 전체에서 같은 라이브러리는 항상 하나의 버전만 쓰인다는 점이 vcpkg의 설계 방향입니다.
Conan 사용하기
설치
# Conan 2.x (pip 권장)
pip install conan
# 버전 확인
conan --version
conanfile.txt (간단한 프로젝트)
conanfile.txt는 패키지 이름과 버전만 나열하는 단순한 형식입니다.
프로젝트 구조
my-conan-app/
├── CMakeLists.txt
├── conanfile.txt
└── src/
└── main.cpp
conanfile.txt
[requires]
fmt/10.1.1
spdlog/1.12.1
[generators]
CMakeDeps
CMakeToolchain
설명:
[requires]: 패키지/버전.fmt/10.1.1형식[generators]:CMakeDeps(find_package용),CMakeToolchain(툴체인) 생성
의존성 설치 및 빌드
# 1. Conan 의존성 설치 (build/에 CMake 파일 생성)
conan install . --output-folder=build --build=missing
# 2. CMake 설정 (Conan 툴체인 사용, build_type은 프로필과 일치시킴)
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
# 3. 빌드
cmake --build build
./build/my-conan-app
--build=missing: 필요한 패키지가 로컬 캐시에 없을 때 빌드까지 수행합니다.
-DCMAKE_BUILD_TYPE=Release를 붙인 이유가 있습니다. Conan은 프로필의 build_type(기본 Release)에 맞는 바이너리만 설치하고, CMakeDeps가 만든 설정 파일도 그 구성 전용입니다. Makefile·Ninja 같은 단일 구성 생성기에서 CMake의 빌드 타입을 비워 두거나 Debug로 두면 구성이 어긋나, find_package는 성공해도 타깃에 라이브러리 경로가 비어 링크 단계에서 undefined reference가 나는 식의 헷갈리는 증상이 생깁니다. Debug로 빌드하려면 conan install . -s build_type=Debug ...로 Debug 바이너리를 따로 받아야 합니다.
CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(my-conan-app VERSION 1.0.0 LANGUAGES CXX)
add_executable(my-conan-app src/main.cpp)
find_package(fmt REQUIRED)
find_package(spdlog REQUIRED)
target_link_libraries(my-conan-app PRIVATE
fmt::fmt
spdlog::spdlog
)
target_compile_features(my-conan-app PRIVATE cxx_std_17)
주의: conan install 후 CMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake를 반드시 지정해야 find_package가 Conan 패키지를 찾습니다.
main.cpp
#include <spdlog/spdlog.h>
#include <fmt/core.h>
int main() {
spdlog::info("Conan으로 빌드됨");
spdlog::info("fmt: {}", fmt::format("Hello, Conan!"));
return 0;
}
conanfile.py (고급)
conanfile.py는 빌드 스크립트·옵션·요구사항을 세밀히 제어할 때 사용합니다.
from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMakeDeps, cmake_layout
from conan.tools.build import check_min_cppstd
class MyAppConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
# generate()에서 직접 만들므로 generators 속성은 두지 않음 (둘 다 쓰면 Conan 2가 에러)
default_options = {"spdlog/*:shared": False}
def layout(self):
cmake_layout(self)
def requirements(self):
self.requires("fmt/10.1.1")
self.requires("spdlog/1.12.1")
def validate(self):
check_min_cppstd(self, "17")
def generate(self):
deps = CMakeDeps(self)
deps.generate()
tc = CMakeToolchain(self)
tc.generate()
이 레시피에서 몇 가지는 Conan 1에서 넘어온 예제와 다르게 써야 합니다. 첫째, generators = "CMakeDeps", "CMakeToolchain" 속성과 generate() 메서드 안에서 같은 생성기를 직접 만드는 코드를 동시에 두면 Conan 2는 같은 생성기가 두 번 정의되었다는 에러를 냅니다. 생성기에 옵션을 줄 필요가 없으면 속성만, 세부 설정이 필요하면 generate()만 쓰면 됩니다. 둘째, check_min_cppstd처럼 “이 설정 조합으로는 빌드할 수 없다”를 판단하는 코드는 configure()가 아니라 validate()에 둡니다. validate()에서 발생한 오류는 Conan이 “이 구성은 유효하지 않음”으로 처리해 의존성 그래프 계산과 명확히 분리됩니다. 셋째, 의존성의 옵션은 "패키지/*:옵션" 패턴으로 지정합니다.
프로필
프로필은 컴파일러, 빌드 타입(Release/Debug), 아키텍처를 정의합니다.
# 기본 프로필 확인
conan profile show default
# 프로필 경로
# Linux: ~/.conan2/profiles/default
# Windows: C:\Users\<user>\.conan2\profiles\default
프로필 예시 (~/.conan2/profiles/default):
[settings]
os=Linux
arch=x86_64
compiler=gcc
compiler.version=12
compiler.libcxx=libstdc++11
compiler.cppstd=17
build_type=Release
Conan 1 시절 프로필에 있던 os_build, arch_build 같은 설정은 Conan 2에서 제거되어, 옛 프로필을 그대로 쓰면 'settings.os_build' doesn't exist 에러가 납니다. 빌드 머신과 대상 머신이 다른 크로스 컴파일은 Conan 2에서 -pr:h(host 프로필)와 -pr:b(build 프로필)를 나눠 지정하는 방식으로 바뀌었습니다. 새 환경에서는 conan profile detect로 현재 컴파일러를 감지한 기본 프로필을 만든 뒤 고쳐 쓰는 것이 가장 빠릅니다.
팀·CI에서 프로필을 공유하면 환경이 맞춰집니다.
# 특정 프로필 사용
conan install . --output-folder=build --build=missing -pr=./conanprofile
Conan 옵션 (options)
일부 패키지는 옵션으로 빌드 방식을 바꿀 수 있습니다.
# conanfile.txt
[requires]
spdlog/1.12.1
[options]
spdlog/*:shared=False
spdlog/*:wchar_support=True
conanfile.py에서는 default_options로 지정할 수 있습니다.
default_options = {"spdlog/*:shared": False}
옵션 앞의 spdlog/*: 패턴은 Conan 2 문법입니다. Conan 1의 spdlog:shared=False 형식은 Conan 2에서 인식되지 않거나 경고와 함께 무시되므로, 옵션을 줬는데도 공유 라이브러리가 빌드된다면 이 문법부터 확인합니다. 옵션을 바꾸면 패키지 ID가 달라져 캐시에 있던 바이너리를 쓸 수 없으므로, --build=missing으로 다시 빌드되는 것이 정상입니다.
Conan 레시피 검색
# Conan Center에서 패키지와 사용 가능한 버전 검색 (Conan 2)
conan search "spdlog/*" -r=conancenter
# 원격 저장소의 레시피·리비전 목록 확인
conan list "spdlog/*" -r=conancenter
Conan 빌드 흐름 다이어그램
sequenceDiagram
participant Dev as 개발자
participant Conan as Conan
participant Cache as 캐시
participant CMake as CMake
Dev->>Conan: install
Conan->>Cache: 패키지?
alt 있음
Cache-->>Conan: 제공
else 없음
Conan->>Conan: 빌드
Conan->>Cache: 저장
end
Conan->>Dev: toolchain
Dev->>CMake: configure
CMake->>Conan: find_package
Conan-->>CMake: 경로 전달
vcpkg vs Conan 비교
| 항목 | vcpkg | Conan |
|---|---|---|
| 통합 | CMake 툴체인 한 줄로 연동 | conan install + CMakeToolchain |
| 패키지 수 | 공식 레지스트리 2,000+ | Conan Center 1,000+ |
| 커스텀 빌드 | 포트 수정·오버레이 | conanfile.py로 완전 제어 |
| 멀티 컴파일러 | triplet으로 관리 | 프로필로 관리 |
| 사내 패키지 | 오버레이 포트 | 사설 레포지토리 (Artifactory 등) |
| 캐시 | 로컬 빌드 캐시 | Conan 캐시 (~/.conan2) |
선택 가이드
- vcpkg: Windows·Visual Studio·CMake 중심 프로젝트, Microsoft 생태계
- Conan: 비표준 컴파일러, 사내 라이브러리 패키지 배포, 크로스 플랫폼 강화 이미 vcpkg로 많은 라이브러리를 쓰고 있다면 그대로 가져가고, 사내 라이브러리를 Conan 패키지로 배포하는 구조라면 Conan이 유리할 수 있습니다. 팀 규약과 CI 파이프라인에 맞게 하나를 정해 두는 것이 중요합니다.
package configuration file 없음, baseline 누락, 바이너리 없음 같은 에러
vcpkg 관련
에러 1: “Could not find a package configuration file”
CMake Error: Could not find a package configuration file provided by "fmt"
원인: CMAKE_TOOLCHAIN_FILE을 지정하지 않았거나, vcpkg가 해당 패키지를 아직 빌드하지 않음.
해결법:
# 1. 툴체인 파일 지정 확인
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
# 2. vcpkg.json이 있는데 패키지가 없다면, CMake를 처음부터 다시 실행
# (Manifest 모드는 CMake 설정 시 자동 설치)
rm -rf build
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=...
에러 2: “A suitable version of cmake was not found”
Error: vcpkg was unable to find the version of cmake in your PATH
원인: vcpkg가 내부적으로 CMake를 사용하는데, PATH에 없거나 버전이 낮음. 해결법:
# CMake 3.20 이상 권장
which cmake
cmake --version
# PATH에 추가하거나, vcpkg가 사용할 cmake 경로 설정
에러 3: “Port xxx is not in the baseline”
Error: Could not find a version that satisfies the requirement ...
원인: builtin-baseline이 오래되었거나, 해당 패키지가 baseline에 없음.
해결법:
# 최신 baseline으로 업데이트
cd vcpkg
git pull
git rev-parse HEAD # 이 해시를 vcpkg.json의 builtin-baseline에 넣기
{
"builtin-baseline": "최신_커밋_해시"
}
Conan 관련
에러 4: “fmt/10.1.1: NotFound”
ERROR: Package 'fmt/10.1.1' not found
원인: Conan Center에 해당 버전이 없거나, 레포지토리 설정 문제. 해결법:
# 사용 가능한 버전 확인
conan search fmt --remote=conancenter
# remotes 확인
conan remote list
# conancenter가 있어야 함
에러 5: “find_package(fmt) failed”
원인: CMAKE_TOOLCHAIN_FILE을 Conan이 생성한 conan_toolchain.cmake로 지정하지 않음.
해결법:
# conan install을 먼저 실행한 뒤
conan install . --output-folder=build --build=missing
# CMake에 툴체인 전달 (경로 확인)
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=$(pwd)/build/conan_toolchain.cmake
에러 6: “Binary not found” / “Can’t find a compatible binary”
ERROR: Missing prebuilt package for 'fmt/10.1.1'
원인: 해당 설정(컴파일러, 아키텍처 등)에 맞는 사전 빌드 바이너리가 없음. 해결법:
# --build=missing으로 소스에서 빌드
conan install . --output-folder=build --build=missing
# 특정 패키지만 빌드
conan install . --output-folder=build --build=fmt
공통
에러 7: “C++ 표준 불일치”
error: #error "spdlog requires C++17 or later"
원인: 프로젝트가 C++14로 빌드되는데, 의존성이 C++17을 요구함. 해결법:
# CMakeLists.txt에서 명시
target_compile_features(myapp PRIVATE cxx_std_17)
# 또는
set(CMAKE_CXX_STANDARD 17)
에러 8: “Multiple definitions” / 링크 에러
원인: 헤더 전용 라이브러리를 잘못 링크하거나, 정적/동적 링크 혼용. 해결법:
- vcpkg: triplet을
x64-windows-static등으로 통일 - Conan: 프로필의
build_type을 팀 전체가 동일하게 사용
에러 9: vcpkg “Building package … failed”
Building package xxx:x64-linux failed
원인: 패키지 빌드 중 컴파일 에러, 의존성 누락 등. 해결법:
# 상세 로그 확인
export VCPKG_VERBOSE=1
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=...
# 특정 패키지만 수동 빌드해 보기
./vcpkg install xxx --debug
에러 10: Conan “Version conflict”
ERROR: Conflict in spdlog/1.12.1: requirement 'fmt/9.x' conflicts with 'fmt/10.1.1'
원인: 의존성 간 버전 충돌. spdlog가 fmt 9.x를 요구하는데 프로젝트에서 10.1.1을 요구함. 해결법:
# 호환되는 버전 조합 찾기
conan graph info . --format=html # 의존성 그래프 시각화
# conanfile.txt에서 버전 조정
# spdlog 1.12.1은 fmt 10.x와 호환되는지 확인 후, fmt 버전 낮추기
[requires]
fmt/9.1.0
spdlog/1.12.1
에러 11: “conan_toolchain.cmake not found”
원인: conan install을 실행하지 않았거나, --output-folder 경로가 다름.
해결법:
# output-folder와 CMake의 -B 경로를 일치시키기
conan install . --output-folder=build --build=missing
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake
# build/ 디렉터리가 동일해야 함
baseline 업데이트 주기, Conan lockfile, CONFIG 모드
vcpkg
- Manifest 모드 사용:
vcpkg.json을 프로젝트 루트에 두고 Git에 커밋 - builtin-baseline 고정: 재현 가능한 빌드를 위해 특정 커밋 해시 사용
- 버전 명시: 가능하면
"version>="등으로 최소 버전 지정 - vcpkg를 서브모듈로:
git submodule add https://github.com/Microsoft/vcpkg.git vcpkg - CI에서 캐시: vcpkg 빌드 결과를 캐시하여 CI 시간 단축
Conan
- conanfile.txt 또는 conanfile.py: 팀 규모에 맞게 선택
- 프로필 공유:
conanprofile파일을 저장소에 포함 - lockfile 사용:
conan lock create로 의존성 고정 - 캐시 활용:
~/.conan2를 CI에서 캐시
공통
- 의존성 최소화: 꼭 필요한 패키지만 추가
- 버전 고정: 프로덕션에서는 가능한 한 버전을 고정
- 문서화: README에 “vcpkg 또는 Conan 사용” 및 빌드 절차 명시
조금 더 자세히
vcpkg: baseline 업데이트 주기
builtin-baseline은 vcpkg 포트 저장소의 특정 커밋을 가리킵니다. 주기적으로 업데이트하면 보안 패치·버그 수정을 받을 수 있지만, 갑작스러운 빌드 실패를 피하려면 별도 브랜치에서 테스트 후 업데이트하는 것이 좋습니다.
# vcpkg 최신 커밋으로 baseline 업데이트
cd vcpkg && git pull
git rev-parse HEAD # 이 해시를 vcpkg.json에 넣기
Conan: lockfile 사용
# conan.lock 생성 (의존성 트리 고정)
conan lock create .
# lockfile이 있으면 CI에서 동일한 의존성 사용
conan install . --output-folder=build --lockfile=conan.lock --build=missing
conan.lock을 Git에 커밋하면, 팀 전체가 동일한 의존성 버전으로 빌드됩니다.
find_package 사용 시 CONFIG 모드
vcpkg가 설치한 패키지는 대부분 Config 모드 패키지를 제공합니다. find_package(fmt CONFIG REQUIRED)처럼 CONFIG를 명시하면 Module 모드보다 더 정확하게 찾습니다.
# 권장: CONFIG 모드
find_package(fmt CONFIG REQUIRED)
target_link_libraries(myapp PRIVATE fmt::fmt)
# Module 모드 (구형 패키지)
find_package(Boost REQUIRED COMPONENTS system)
CI Manifest 모드, lockfile 재현성, 사내 레포, Docker 연동
패턴 1: CI에서 vcpkg Manifest 모드
# .github/workflows/build.yml (예시)
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive # vcpkg 서브모듈 포함
- name: Configure CMake
run: |
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DCMAKE_BUILD_TYPE=Release
- name: Build
run: cmake --build build --config Release
패턴 2: Conan lockfile로 재현성 확보
# lockfile 생성 (의존성 트리 고정)
conan lock create .
# lockfile 사용하여 설치
conan install . --output-folder=build --lockfile=conan.lock --build=missing
패턴 3: 멀티 플랫폼 빌드 (vcpkg)
strategy:
matrix:
triplet: [x64-linux, x64-windows, arm64-osx]
steps:
- run: |
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_TARGET_TRIPLET=${{ matrix.triplet }}
패턴 4: 사내 Conan 레포지토리
# 사설 remote 추가
conan remote add company https://artifactory.company.com/artifactory/api/conan/conan-local
# 사내 패키지 사용
# conanfile.txt
[requires]
company-internal-lib/1.0.0
fmt/10.1.1
패턴 5: Docker와 함께 사용
# Dockerfile 예시 (vcpkg)
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y git cmake g++ build-essential
RUN git clone https://github.com/Microsoft/vcpkg.git /vcpkg && \
/vcpkg/bootstrap-vcpkg.sh
ENV CMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake
WORKDIR /app
COPY . .
RUN cmake -B build -S . && cmake --build build
패턴 6: Conan + Docker
# Dockerfile 예시 (Conan)
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3-pip cmake g++ build-essential
RUN pip install conan
WORKDIR /app
COPY . .
# Conan 의존성 설치 (캐시 활용을 위해 의존성 먼저 복사)
RUN conan install . --output-folder=build --build=missing
# CMake 빌드
RUN cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake && \
cmake --build build
패턴 7: Conan + vcpkg CI 캐시
# vcpkg 캐시 (GitHub Actions)
- name: Cache vcpkg
uses: actions/cache@v4
with:
path: ${{ env.VCPKG_ROOT }}/buildtrees
key: vcpkg-${{ runner.os }}-${{ hashFiles('**/vcpkg.json') }}
# Conan 캐시
- name: Cache Conan
uses: actions/cache@v4
with:
path: ~/.conan2
key: conan-${{ runner.os }}-${{ hashFiles('**/conanfile.txt', '**/conanfile.py') }}
패턴 8: vcpkg + CMake Presets
CMakePresets.json으로 팀 전체가 동일한 설정을 사용할 수 있습니다.
{
"version": 3,
"configurePresets": [
{
"name": "vcpkg-default",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
}
}
]
}
# preset 사용
cmake --preset vcpkg-default
cmake --build build
패턴 9: 의존성 업데이트 전략
1. 개발: vcpkg baseline 또는 Conan 버전을 주기적으로 업데이트
2. 스테이징: 업데이트 후 전체 테스트 실행
3. 프로덕션: 검증된 버전만 lockfile/baseline에 고정
같이 보면 좋은 글
- C++ CI/CD 파이프라인: GitHub Actions를 이용한 멀티 OS 자동 빌드·테스트 가이드
- CMake ‘Could NOT find’ 에러
- C++ 패키지 매니저 vcpkg와 Conan 비교: manifest·트리플렛·프로파일과 CMake 연동
- C++23에서 실제로 쓸 기능
- C++26에서 달라지는 것
- C++ 컨테이너 기반 개발: Docker로 빌드 환경 표준화 및 배포 이미지 최적화 [#40-3]
- C++ 의존성 관리 비교
자주 묻는 질문 (FAQ)
Q. vcpkg로 설치했는데 CMake에서 Could not find a package configuration file 에러가 나는 이유는 무엇인가요?
A. 대부분 CMake가 vcpkg의 툴체인 파일을 모른 채로 configure되었기 때문입니다. CMAKE_TOOLCHAIN_FILE을 vcpkg의 scripts/buildsystems/vcpkg.cmake로 지정해야 하고, 이 값은 첫 configure 시점에 들어가야 하므로 이미 만든 빌드 디렉터리가 있다면 캐시를 지우고 다시 configure해야 합니다. 또한 설치한 triplet(예: x64-windows와 x64-linux)이 현재 빌드 대상과 다르면 패키지를 찾지 못하므로 triplet도 함께 확인하는 것이 좋습니다.
Q. vcpkg와 Conan 중 뭘 써야 할까요?
A. Windows·Visual Studio·Microsoft 생태계가 중심이면 vcpkg, 비표준 컴파일러·사내 라이브러리 패키지·크로스 플랫폼 강화가 필요하면 Conan을 고려하세요. 이미 팀에서 하나를 쓰고 있다면 통일하는 것이 좋습니다. vcpkg·Conan으로 의존성을 선언만 하고 빌드·링크를 자동화할 수 있습니다. 다음으로 CI/CD·GitHub Actions(#40-2)를 읽어보면 좋습니다. 다음 글: [DevOps for C++ #40-2] CI/CD 파이프라인: GitHub Actions를 이용한 멀티 OS 자동 빌드 및 테스트 이전 글: [고성능 C++ #39-3] SIMD와 병렬화: std::execution과 인트린직(Intrinsics)을 이용한 연산 가속