C++ vcpkg 고급 활용 | Manifest·Triplet·오버레이·바이너리 캐시 가이드

C++ vcpkg 고급 활용 | Manifest·Triplet·오버레이·바이너리 캐시 가이드

이 글의 핵심

C++ vcpkg 고급 기능 Manifest 모드·커스텀 Triplet·오버레이·버전 제약·바이너리 캐시, CI 연동, 자주 발생하는 에러와 프로덕션 패턴까지 실전 예제로 다룹니다.

들어가며: vcpkg 기본을 넘어서

문제 시나리오

vcpkg로 fmt, spdlog를 설치하고 빌드에 성공했다면, 이제 이런 상황을 마주할 수 있습니다:

"Windows에서는 되는데 Linux 서버에서만 링크 에러가 나요."
"사내에서 수정한 라이브러리를 vcpkg로 쓰고 싶어요."
"CI에서 매번 30분씩 vcpkg 빌드하는데, 캐시로 줄일 수 없나요?"
"프로젝트 A는 Boost 1.82, 프로젝트 B는 1.84를 써야 하는데 충돌해요."
"정적 링크로 배포해야 하는데 triplet 설정이 복잡해요."
"builtin-baseline 업데이트 후 갑자기 빌드가 깨졌어요."

이 글에서 다루는 것:

  • Manifest 모드 심화: 버전 제약, 플랫폼별 의존성, builtin-baseline 전략
  • 커스텀 Triplet: 정적 링크, 특수 컴파일러, 크로스 컴파일
  • 오버레이 포트: 사내 라이브러리, 포트 수정본 통합
  • 바이너리 캐시: CI 빌드 시간 대폭 단축
  • 완전한 실전 예제: 복사 후 바로 사용 가능한 프로젝트 구조
  • 자주 발생하는 에러와 해결법
  • 베스트 프랙티스프로덕션 패턴

요구 환경: vcpkg 2024.01+, CMake 3.20+, C++17 이상


실무 적용 경험: 이 글은 대규모 C++ 프로젝트에서 실제로 겪은 문제와 해결 과정을 바탕으로 작성되었습니다. 책이나 문서에서 다루지 않는 실전 함정과 디버깅 팁을 포함합니다.

목차

  1. 문제 시나리오: vcpkg 고급 활용이 필요한 상황
  2. Manifest 모드 심화
  3. 커스텀 Triplet
  4. 오버레이 포트
  5. 바이너리 캐시
  6. 완전한 vcpkg 고급 예제
  7. 자주 발생하는 에러와 해결법
  8. 베스트 프랙티스
  9. 프로덕션 패턴
  10. 정리

1. 문제 시나리오: vcpkg 고급 활용이 필요한 상황

시나리오 1: 멀티 플랫폼 빌드 실패

개발: Windows (MSVC) → 빌드 성공
CI: Ubuntu (GCC) → "undefined reference to spdlog::..."
배포: macOS (Clang) → "library not found for -lssl"

원인: triplet이 플랫폼별로 다르고, 동적/정적 링크 설정이 통일되지 않음.

해결 방향: 커스텀 triplet으로 팀 전체가 동일한 빌드 설정을 사용.

시나리오 2: 사내 라이브러리 통합

"우리 회사에서 fork한 OpenSSL을 vcpkg로 쓰고 싶어요."
"공식 포트에 버그가 있어서 패치를 적용했어요."

원인: vcpkg 공식 레지스트리에 없는 패키지 또는 수정된 버전 필요.

해결 방향: 오버레이 포트로 사내 포트 디렉터리를 vcpkg에 등록.

시나리오 3: CI 빌드 시간 폭증

"PR마다 vcpkg가 Boost, OpenSSL을 처음부터 빌드해서 40분 걸려요."
"캐시를 넣었는데도 매번 새로 빌드해요."

원인: vcpkg 빌드 결과를 캐시하지 않거나, 바이너리 캐시를 활용하지 않음.

해결 방향: 바이너리 캐시(아티팩트, GitHub Actions cache)로 빌드 결과 재사용.

시나리오 4: 버전 충돌과 재현성

"builtin-baseline을 올렸더니 fmt 10.2로 올라가서 우리 코드가 깨졌어요."
"팀원 A는 빌드되는데 B는 실패해요. vcpkg 버전이 다르대요."

원인: baseline·버전 제약이 없거나 팀원마다 vcpkg 상태가 다름.

해결 방향: builtin-baseline 고정, version>= 제약, vcpkg를 서브모듈로 관리.

flowchart TD
  subgraph problems[문제]
    P1[멀티 플랫폼 불일치]
    P2[사내 라이브러리]
    P3[CI 빌드 지연]
    P4[버전·재현성]
  end
  subgraph solutions[해결]
    S1[커스텀 Triplet]
    S2[오버레이 포트]
    S3[바이너리 캐시]
    S4[Manifest + baseline]
  end
  P1 --> S1
  P2 --> S2
  P3 --> S3
  P4 --> S4

2. Manifest 모드 심화

버전 제약 문법

vcpkg.json에서 의존성 버전을 세밀히 제어할 수 있습니다.

{
  "name": "my-production-app",
  "version": "1.0.0",
  "dependencies": [
    "fmt",
    {
      "name": "spdlog",
      "version>=": "1.11.0",
      "version<": "2.0.0"
    },
    {
      "name": "openssl",
      "version>=": "3.0.0",
      "platform": "!windows"
    },
    {
      "name": "zlib",
      "platform": "windows"
    }
  ],
  "builtin-baseline": "a1b2c3d4e5f6789012345678901234567890abc"
}

설명:

  • version>=: 최소 버전 (이 버전 이상)
  • version<: 최대 버전 (이 버전 미만, 호환성 깨짐 방지)
  • platform: 특정 플랫폼에서만 의존성 추가
    • "windows": Windows에서만
    • "!windows": Windows 제외 (Linux, macOS)
    • "linux", "osx"

builtin-baseline 전략

builtin-baseline은 vcpkg 포트 저장소의 특정 커밋 해시입니다. 이 해시에 따라 사용 가능한 패키지 버전이 결정됩니다.

# vcpkg 최신 커밋 해시 확인
cd vcpkg
git pull
git rev-parse HEAD
# 출력: a1b2c3d4e5f6789012345678901234567890abc

권장 전략:

  1. 프로덕션: baseline을 고정하고, 별도 브랜치에서 업데이트 테스트 후 반영
  2. 개발: 주기적으로 baseline 업데이트, 전체 테스트 후 커밋
  3. CI: vcpkg.jsonvcpkg.lock을 Git에 커밋해 재현성 확보

vcpkg.lock 활용

Manifest 모드로 빌드하면 vcpkg.lock이 생성됩니다. 이 파일을 Git에 커밋하면 정확히 동일한 버전으로 빌드됩니다.

{
  "version": 1,
  "port-version": 0,
  "builtin-baseline": "a1b2c3d4e5f6789012345678901234567890abc",
  "packages": [
    {
      "name": "fmt",
      "version": "10.1.1",
      "port-version": 0
    },
    {
      "name": "spdlog",
      "version": "1.12.1",
      "port-version": 0
    }
  ]
}

주의: vcpkg.lock이 있으면 vcpkg가 이 버전을 우선 사용합니다. 의존성 추가/변경 시 lock 파일이 자동 갱신되므로, 변경 후 테스트하고 커밋하세요.

플랫폼별 의존성 예제

Windows에서는 시스템 SSL 대신 vcpkg OpenSSL, Linux에서는 시스템 OpenSSL을 쓰는 예:

{
  "dependencies": [
    "fmt",
    "spdlog",
    {
      "name": "openssl",
      "platform": "windows"
    }
  ]
}
# CMakeLists.txt - OpenSSL은 Windows에서만 vcpkg, Linux는 시스템
if(WIN32)
  find_package(OpenSSL REQUIRED)
  target_link_libraries(myapp PRIVATE OpenSSL::SSL OpenSSL::Crypto)
endif()

3. 커스텀 Triplet

Triplet이란?

Tripletarch-vendor-os 형식으로, 대상 플랫폼·아키텍처·빌드 타입을 지정합니다.

Triplet설명
x64-windowsWindows 64비트, 동적 링크
x64-windows-staticWindows 64비트, 정적 링크
x64-linuxLinux 64비트
x64-osxmacOS Intel
arm64-osxmacOS Apple Silicon

커스텀 Triplet 생성

정적 링크 + 특정 컴파일러 플래그가 필요할 때 커스텀 triplet을 만듭니다.

triplets/custom-static.cmake (프로젝트 내):

set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE static)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME WindowsDesktop)

# 추가 컴파일러 플래그
set(VCPKG_CXX_FLAGS "/MT /W4")
set(VCPKG_CXX_FLAGS_DEBUG "/MTd /Od")
set(VCPKG_CXX_FLAGS_RELEASE "/MT /O2")

triplets/x64-linux-static.cmake (Linux 정적):

set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE static)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME Linux)

Triplet 사용

cmake -B build -S . \
  -DCMAKE_TOOLCHAIN_FILE="$(pwd)/vcpkg/scripts/buildsystems/vcpkg.cmake" \
  -DVCPKG_TARGET_TRIPLET=custom-static

또는 VCPKG_DEFAULT_TRIPLET 환경 변수:

export VCPKG_DEFAULT_TRIPLET=x64-windows-static
cmake -B build -S .

Triplet 오버레이

프로젝트별 triplet을 triplets/ 디렉터리에 두고 vcpkg에 알려줍니다:

cmake -B build -S . \
  -DCMAKE_TOOLCHAIN_FILE="$(pwd)/vcpkg/scripts/buildsystems/vcpkg.cmake" \
  -DVCPKG_OVERLAY_TRIPLETS="$(pwd)/triplets"

4. 오버레이 포트

오버레이란?

오버레이는 vcpkg 공식 레지스트리보다 우선 적용되는 포트 디렉터리입니다. 사내 라이브러리, 수정된 포트, 아직 upstream되지 않은 패키지를 사용할 때 씁니다.

오버레이 디렉터리 구조

my-ports/
├── company-openssl/          # 사내 fork OpenSSL
│   ├── portfile.cmake
│   └── vcpkg.json
├── patched-spdlog/          # 공식 spdlog에 패치 적용
│   ├── portfile.cmake
│   ├── vcpkg.json
│   └── patches/
│       └── fix-logging.patch
└── internal-lib/             # 완전히 사내 라이브러리
    ├── portfile.cmake
    └── vcpkg.json

사내 포트 예제: internal-lib

my-ports/internal-lib/vcpkg.json:

{
  "name": "internal-lib",
  "version": "1.0.0",
  "description": "사내 공통 라이브러리",
  "license": "Proprietary",
  "dependencies": [fmt]
}

my-ports/internal-lib/portfile.cmake:

vcpkg_from_git(
    OUT_SOURCE_PATH SOURCE_PATH
    URL "https://git.company.com/libs/internal-lib.git"
    REF "v1.0.0"
)

vcpkg_cmake_configure(
    SOURCE_PATH "${SOURCE_PATH}"
)

vcpkg_cmake_install()
vcpkg_copy_pdbs()
file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)

오버레이 사용

cmake -B build -S . \
  -DCMAKE_TOOLCHAIN_FILE="$(pwd)/vcpkg/scripts/buildsystems/vcpkg.cmake" \
  -DVCPKG_OVERLAY_PORTS="$(pwd)/my-ports"

vcpkg.json에서 오버레이 포트를 의존성으로 추가:

{
  "dependencies": [
    "fmt",
    "internal-lib"
  ]
}

공식 포트 패치 적용

공식 spdlog 포트를 복사한 뒤 패치만 추가하는 예:

my-ports/patched-spdlog/portfile.cmake:

# 공식 포트를 가져온 뒤
vcpkg_from_github(
    OUT_SOURCE_PATH SOURCE_PATH
    REPO gabime/spdlog
    REF "v1.12.1"
    SHA512 "..."
)

# 패치 적용
vcpkg_apply_patches(
    SOURCE_PATH "${SOURCE_PATH}"
    PATCHES "${CMAKE_CURRENT_LIST_DIR}/patches/fix-logging.patch"
)

vcpkg_cmake_configure(
    SOURCE_PATH "${SOURCE_PATH}"
    OPTIONS -DSPDLOG_ENABLE_PCH=OFF
)

vcpkg_cmake_install()
vcpkg_copy_pdbs()

5. 바이너리 캐시

바이너리 캐시란?

vcpkg가 패키지를 빌드한 결과를 재사용하는 기능입니다. CI에서 매번 소스부터 빌드하는 대신, 이전에 빌드한 바이너리를 가져와 빌드 시간을 크게 줄입니다.

로컬 디렉터리 캐시

# 빌드 결과를 ./vcpkg-cache에 저장
export VCPKG_BINARY_SOURCES="clear;default,readwrite,./vcpkg-cache"

cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=...

첫 빌드 후 vcpkg-cache/에 바이너리가 쌓이고, 이후 빌드에서는 여기서 읽어옵니다.

GitHub Actions 아티팩트 캐시

# .github/workflows/build.yml
env:
  VCPKG_BINARY_SOURCES: "clear;default,readwrite,github,https://github.com/${{ github.repository }},readwrite"

steps:
  - uses: actions/checkout@v4
    with:
      submodules: recursive

  - name: Configure and Build
    run: |
      cmake -B build -S . \
        -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake
      cmake --build build

주의: GitHub 아티팩트는 저장소별·용량 제한이 있습니다. 대안으로 actions/cache를 사용합니다.

actions/cache로 vcpkg 캐시

- name: Cache vcpkg
  uses: actions/cache@v4
  with:
    path: |
      ${{ github.workspace }}/vcpkg/buildtrees
      ${{ github.workspace }}/vcpkg/packages
      ${{ github.workspace }}/vcpkg/downloads
    key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json', 'vcpkg.lock') }}
    restore-keys: vcpkg-${{ runner.os }}-

- name: Configure CMake
  run: |
    cmake -B build -S . \
      -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake

hashFiles('vcpkg.json', 'vcpkg.lock')가 바뀌면 새 캐시가 만들어지고, 그렇지 않으면 이전 빌드 결과를 재사용합니다.


6. 완전한 vcpkg 고급 예제

예제 1: 프로덕션 수준 프로젝트 구조

my-vcpkg-app/
├── .github/
│   └── workflows/
│       └── build.yml
├── CMakeLists.txt
├── CMakePresets.json
├── vcpkg.json
├── vcpkg.lock          # Git 커밋 권장
├── triplets/
│   └── x64-windows-static.cmake
├── vcpkg/              # git submodule
└── src/
    └── main.cpp

vcpkg.json (완전한 예제)

{
  "name": "my-vcpkg-app",
  "version": "1.0.0",
  "description": "vcpkg 고급 활용 예제",
  "dependencies": [
    {
      "name": "fmt",
      "version>=": "10.0.0"
    },
    {
      "name": "spdlog",
      "version>=": "1.11.0",
      "version<": "2.0.0"
    },
    {
      "name": "openssl",
      "platform": "windows"
    }
  ],
  "builtin-baseline": "a1b2c3d4e5f6789012345678901234567890abc"
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(my-vcpkg-app VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake"
    CACHE STRING "Vcpkg toolchain")

add_executable(my-app src/main.cpp)

find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
if(WIN32)
  find_package(OpenSSL REQUIRED)
  target_link_libraries(my-app PRIVATE OpenSSL::SSL OpenSSL::Crypto)
endif()

target_link_libraries(my-app PRIVATE
    fmt::fmt
    spdlog::spdlog
)

target_compile_features(my-app PRIVATE cxx_std_17)

main.cpp

#include <spdlog/spdlog.h>
#include <fmt/core.h>

int main() {
    spdlog::set_level(spdlog::level::debug);
    spdlog::info("vcpkg 고급 예제: {}", fmt::format("Hello, vcpkg!"));
    return 0;
}

CMakePresets.json (팀 설정 통일)

{
  "version": 3,
  "configurePresets": [
    {
      "name": "vcpkg-default",
      "cacheVariables": {
        "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
      }
    },
    {
      "name": "vcpkg-static",
      "inherits": "vcpkg-default",
      "cacheVariables": {
        "VCPKG_TARGET_TRIPLET": "x64-windows-static"
      }
    }
  ]
}

GitHub Actions 워크플로 (완전한 예제)

name: Build (vcpkg)

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive

      - name: Cache vcpkg
        uses: actions/cache@v4
        with:
          path: |
            ${{ github.workspace }}/vcpkg/buildtrees
            ${{ github.workspace }}/vcpkg/packages
            ${{ github.workspace }}/vcpkg/downloads
          key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json', 'vcpkg.lock') }}
          restore-keys: vcpkg-${{ runner.os }}-

      - name: Configure
        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: 오버레이 + 커스텀 triplet

# vcpkg를 서브모듈로
git submodule add https://github.com/Microsoft/vcpkg.git vcpkg

# CMake 설정 (오버레이 + triplet)
cmake -B build -S . \
  -DCMAKE_TOOLCHAIN_FILE="$(pwd)/vcpkg/scripts/buildsystems/vcpkg.cmake" \
  -DVCPKG_OVERLAY_PORTS="$(pwd)/my-ports" \
  -DVCPKG_OVERLAY_TRIPLETS="$(pwd)/triplets" \
  -DVCPKG_TARGET_TRIPLET=x64-windows-static

7. 자주 발생하는 에러와 해결법

에러 1: “Could not find a package configuration file provided by ‘fmt’”

CMake Error: Could not find a package configuration file provided by "fmt"

원인: CMAKE_TOOLCHAIN_FILE을 지정하지 않았거나, vcpkg가 패키지를 아직 빌드하지 않음.

해결법:

# 1. 툴체인 파일 반드시 지정
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="$(pwd)/vcpkg/scripts/buildsystems/vcpkg.cmake"

# 2. build 폴더 삭제 후 재시도 (캐시된 잘못된 설정 제거)
rm -rf build
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=...

에러 2: “Port xxx is not in the baseline”

Error: Could not find a version that satisfies the requirement ...

원인: builtin-baseline이 오래되었거나, 해당 패키지가 baseline에 없음.

해결법:

cd vcpkg
git pull
git rev-parse HEAD   # 이 해시를 vcpkg.json의 builtin-baseline에 넣기
{
  "builtin-baseline": "최신_커밋_해시"
}

에러 3: “Building package xxx failed”

Building package spdlog:x64-linux failed

원인: 패키지 빌드 중 컴파일 에러, 의존성 누락, 네트워크 오류 등.

해결법:

# 상세 로그로 원인 파악
export VCPKG_VERBOSE=1
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=...

# 특정 패키지만 수동 빌드
./vcpkg install spdlog --debug

에러 4: “A suitable version of cmake was not found”

Error: vcpkg was unable to find the version of cmake in your PATH

원인: PATH에 CMake가 없거나 버전이 낮음 (3.20+ 권장).

해결법:

which cmake
cmake --version
# 3.20 이상이어야 함. PATH에 추가하거나 최신 CMake 설치

에러 5: “Multiple definitions” / 링크 에러

error: multiple definition of 'spdlog::...'

원인: 정적/동적 링크 혼용, triplet 불일치.

해결법:

  • triplet을 팀 전체가 동일하게 사용 (예: x64-windows-static)
  • vcpkg로 설치한 라이브러리와 시스템 라이브러리 혼용 금지

에러 6: “C++ 표준 불일치”

error: #error "spdlog requires C++17 or later"

원인: 프로젝트가 C++14로 빌드되는데 의존성이 C++17 요구.

해결법:

target_compile_features(my-app PRIVATE cxx_std_17)
# 또는
set(CMAKE_CXX_STANDARD 17)

에러 7: 오버레이 포트를 찾을 수 없음

Error: Could not find port internal-lib

원인: VCPKG_OVERLAY_PORTS 경로가 잘못되었거나, 포트 디렉터리 구조가 맞지 않음.

해결법:

# 경로 확인 (절대 경로 권장)
ls -la my-ports/internal-lib/vcpkg.json
cmake -B build -S . \
  -DVCPKG_OVERLAY_PORTS="$(pwd)/my-ports"

에러 8: vcpkg.lock과 vcpkg.json 충돌

Error: Version conflict: lock file expects [email protected] but vcpkg.json allows 10.2.0

원인: vcpkg.json을 수정했는데 vcpkg.lock을 갱신하지 않음.

해결법:

# lock 파일 삭제 후 재생성
rm vcpkg.lock
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=...
# 새 vcpkg.lock 생성됨 → Git 커밋

에러 9: CI에서만 “Could NOT find” 발생

원인: 로컬에 Classic 모드로 설치한 패키지에 의존. CI에는 해당 패키지가 없음.

해결법: Manifest 모드로 전환. vcpkg.json에 의존성 선언하고 CMAKE_TOOLCHAIN_FILE 지정.

에러 10: 바이너리 캐시에서 손상된 패키지

Error: Failed to restore package from binary cache

원인: 캐시가 손상되었거나 triplet/버전이 달라서 호환되지 않음.

해결법:

# 캐시 비우고 재빌드
rm -rf vcpkg-cache
# 또는 CI에서 cache key 변경

8. 베스트 프랙티스

1. Manifest 모드 사용

  • vcpkg.json을 프로젝트 루트에 두고 Git에 커밋
  • Classic 모드(vcpkg install 전역 설치)는 레거시. 신규 프로젝트는 Manifest 모드

2. builtin-baseline 고정

  • 재현 가능한 빌드를 위해 특정 커밋 해시 사용
  • 업데이트 시 별도 브랜치에서 테스트 후 main 반영

3. vcpkg.lock 커밋

  • vcpkg.lock을 Git에 커밋하면 팀 전체가 동일한 버전 사용
  • 의존성 추가/변경 시 lock 갱신 후 테스트·커밋

4. vcpkg 서브모듈

git submodule add https://github.com/Microsoft/vcpkg.git vcpkg
  • vcpkg 버전을 프로젝트와 함께 고정
  • CI에서 submodules: recursive로 체크아웃

5. find_package CONFIG 모드

find_package(fmt CONFIG REQUIRED)
target_link_libraries(my-app PRIVATE fmt::fmt)
  • vcpkg 패키지는 대부분 Config 모드. CONFIG 명시 권장

6. 의존성 최소화

  • 꼭 필요한 패키지만 추가
  • 헤더 전용 라이브러리(nlohmann-json 등)는 빌드 없이 사용 가능

7. CI 캐시 활용

  • buildtrees, packages, downloads 캐시
  • hashFiles('vcpkg.json', 'vcpkg.lock')를 key에 포함

8. CMake Presets

  • CMakePresets.json으로 팀 전체 설정 통일
  • cmake --preset vcpkg-default로 간편 설정

9. 프로덕션 패턴

패턴 1: 멀티 플랫폼 CI 매트릭스

strategy:
  matrix:
    include:
      - os: ubuntu-latest
        triplet: x64-linux
      - os: windows-latest
        triplet: x64-windows-static
      - os: macos-latest
        triplet: arm64-osx
steps:
  - run: |
      cmake -B build -S . \
        -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake \
        -DVCPKG_TARGET_TRIPLET=${{ matrix.triplet }}

패턴 2: 사내 오버레이 공유

회사 레포지토리: company/vcpkg-ports
각 프로젝트에서:
  -DVCPKG_OVERLAY_PORTS="$(pwd)/../vcpkg-ports"
또는 서브모듈로 vcpkg-ports 포함

패턴 3: Docker + 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

패턴 4: 의존성 업데이트 전략

1. 개발: 주기적으로 baseline 업데이트, 로컬 테스트
2. 스테이징: 업데이트 후 CI 전체 통과 확인
3. 프로덕션: vcpkg.lock 커밋으로 버전 고정

패턴 5: 버전 제약으로 호환성 유지

{
  "dependencies": [
    {
      "name": "spdlog",
      "version>=": "1.11.0",
      "version<": "2.0.0"
    }
  ]
}
  • version<로 마이저 업그레이드 시 예기치 않은 깨짐 방지

10. 정리

항목설명
Manifest 심화버전 제약, 플랫폼별 의존성, builtin-baseline, vcpkg.lock
커스텀 Triplet정적 링크, 특수 컴파일러, 오버레이 triplet
오버레이사내 라이브러리, 패치된 포트 통합
바이너리 캐시로컬/CI 캐시로 빌드 시간 단축
에러 해결툴체인 지정, baseline 업데이트, triplet 통일
프로덕션멀티 플랫폼 CI, 오버레이 공유, Docker, 업데이트 전략

구현 체크리스트

  • Manifest 모드 + vcpkg.json
  • builtin-baseline 고정
  • vcpkg.lock Git 커밋
  • vcpkg 서브모듈
  • CMAKE_TOOLCHAIN_FILE 지정
  • CI에서 vcpkg 캐시
  • 필요 시 오버레이·커스텀 triplet

자주 묻는 질문 (FAQ)

Q. vcpkg Classic 모드와 Manifest 모드 차이는?

A. Classic 모드는 vcpkg install로 전역 설치. Manifest 모드는 프로젝트 vcpkg.json에 의존성을 선언하고 CMake 설정 시 자동 설치. 재현 가능한 빌드를 위해 Manifest 모드를 권장합니다.

Q. 사내 라이브러리를 vcpkg로 쓰려면?

A. 오버레이 포트를 만듭니다. my-ports/내라이브러리/vcpkg.jsonportfile.cmake를 두고, -DVCPKG_OVERLAY_PORTS로 경로를 지정합니다.

Q. CI 빌드가 너무 느려요.

A. actions/cache로 vcpkg의 buildtrees, packages, downloads를 캐시하세요. hashFiles('vcpkg.json', 'vcpkg.lock')를 key에 넣으면 의존성 변경 시에만 캐시가 갱신됩니다.

Q. builtin-baseline을 언제 업데이트하나요?

A. 보안 패치·버그 수정이 필요할 때. 별도 브랜치에서 업데이트 후 전체 테스트를 돌리고, 통과하면 main에 반영합니다.

한 줄 요약: vcpkg Manifest·Triplet·오버레이·바이너리 캐시를 활용하면 멀티 플랫폼·재현 가능·빠른 CI 빌드를 구축할 수 있습니다.

다음 글: [C++ #53-4] Conan 레시피 작성 | 패키지 배포·의존성 관리

이전 글: [C++ #53-2] Visual Studio C++ 완벽 가이드


관련 글

  • C++ vcpkg 기초 완벽 가이드 | 설치·Manifest·Triplet·버전·커스텀 포트 [#53-3]
  • C++ vcpkg 패키지 만들기 | 포트 파일·빌드·배포 완벽 가이드 [#53-3]
  • C++ Conan 고급 완벽 가이드 | lockfile·크로스 빌드·사내 레포·프로덕션 패턴 [#53-4]
  • CMake 입문 | 수십 개 파일 컴파일할 때 필요한 빌드 자동화 (CMakeLists.txt 기초)
... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3