C++ CMake Presets 완벽 가이드 | 멀티 플랫폼·vcpkg·Conan·CI/CD 통합

C++ CMake Presets 완벽 가이드 | 멀티 플랫폼·vcpkg·Conan·CI/CD 통합

이 글의 핵심

C++ CMake Presets 입니다. 멀티 플랫폼 빌드, vcpkg/Conan 통합, CI/CD 자동화를 위한 프리셋 설정 방법을 다룹니다. CMake로 빌드하다 보면 이런 상황을 자주 마주합니다: "로컬에서는 되는데 CI에서만 빌드가 실패해요." "Debug로 빌드하려면 -DCMAKEBUILDTYPE=Debug를 매번 치기 귀찮아요.

들어가며: “cmake 명령어가 팀원마다 달라요”

실제 겪는 문제 시나리오

CMake로 빌드하다 보면 이런 상황을 자주 마주합니다:

"로컬에서는 되는데 CI에서만 빌드가 실패해요."
"Debug로 빌드하려면 -DCMAKE_BUILD_TYPE=Debug를 매번 치기 귀찮아요."
"Windows는 MSVC, Linux는 GCC, macOS는 Clang인데 설정이 다 달라요."
"vcpkg 쓰는 사람은 CMAKE_TOOLCHAIN_FILE을, Conan 쓰는 사람은 다른 경로를 지정해요."
"팀원 A는 build/, B는 out/, C는 cmake-build-debug/를 쓰는데 정리가 안 돼요."
"IDE(CLion, VS Code)에서 preset을 선택하는 게 불편해요."
"Ninja vs Makefile vs Visual Studio 생성기가 섞여 있어요."

CMake Presets로 해결:

문제Presets 해결
팀마다 다른 cmake 옵션CMakePresets.json에 설정 통일, Git으로 공유
Debug/Release 전환configurePresets에 debug, release 분리
멀티 컴파일러gcc, clang, msvc preset 각각 정의
vcpkg/ConantoolchainFile로 자동 지정
CI 빌드cmake --preset ci-release 한 줄로 재현
IDE 연동CLion, VS Code, Visual Studio가 preset 자동 인식

팀 전체가 같은 configure/build 옵션을 쓰게 만든다는 점에서, Rust의 Cargo 워크플로·npm package.json·lock·Go 모듈·빌드 캐시·Python 가상환경·락과 같은 “재현 가능한 빌드” 문제를 나란히 떠올리면 설계 의도가 잘 맞습니다. 큰 그림은 CMake 가이드·빌드 시스템 비교와 함께 보세요.

요구 환경: CMake 3.19+ (configure), 3.20+ (build/test), 3.23+ 권장

이 글을 읽으면:

  • CMake Presets 기본 구조와 상속을 이해할 수 있습니다.
  • Debug/Release, GCC/Clang/MSVC, vcpkg, Conan을 preset으로 통합할 수 있습니다.
  • 자주 발생하는 에러와 해결법을 알 수 있습니다.
  • CI/CD, IDE 연동 등 프로덕션 패턴을 적용할 수 있습니다.

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

목차

  1. 문제 시나리오 상세
  2. CMake Presets 기본 구조
  3. 완전한 CMake Presets 예제
  4. vcpkg·Conan 연동
  5. 자주 발생하는 에러와 해결법
  6. 베스트 프랙티스
  7. 프로덕션 패턴
  8. 구현 체크리스트
  9. 정리

1. 문제 시나리오 상세

시나리오 1: 팀 빌드 설정 불일치

개발자 A: cmake -B build -DCMAKE_BUILD_TYPE=Release -G Ninja
개발자 B: cmake .. -DCMAKE_BUILD_TYPE=Debug
개발자 C: cmake -S . -B build -DCMAKE_CXX_COMPILER=clang++

결과: “내 로컬에서는 되는데요” — CI나 다른 환경에서 재현 불가.

해결: CMakePresets.jsondefault, debug, release preset을 정의하고, 모두 cmake --preset release로 통일.

시나리오 2: CI에서 빌드 실패

로컬: Ubuntu 22.04, GCC 12, Ninja → 성공
CI: Ubuntu 22.04, 기본 GCC, Makefile → "undefined reference"

원인: Generator, 컴파일러, 빌드 타입이 CI와 로컬에서 다름.

해결: ci-debug, ci-release preset을 만들어 CI 스크립트에서 cmake --preset ci-release 사용.

시나리오 3: vcpkg/Conan 사용자 혼재

vcpkg 사용자: -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
Conan 사용자: -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake

원인: 패키지 매니저마다 toolchain 경로가 다름.

해결: vcpkg-default, conan-default preset을 각각 정의. 사용자는 --preset vcpkg-default만 지정.

시나리오 4: 멀티 플랫폼 개발

Windows: Visual Studio 2022, x64
Linux: GCC 12, Ninja
macOS: Clang (Xcode), Ninja

해결: 플랫폼별 preset 또는 condition으로 OS에 따라 자동 선택.

시나리오 5: Sanitizer·코드 커버리지 빌드

"ASan 빌드하려면 -DUSE_ASAN=ON을 매번 넣어요."
"코드 커버리지 빌드 설정이 복잡해요."

해결: asan, tsan, coverage preset으로 한 번에 전환.

시나리오 6: 의존성 경로 변경

상황: vcpkg를 /opt/vcpkg에서 C:\vcpkg로 옮김
문제: 팀원마다 VCPKG_ROOT 경로가 다름
결과: "Could not find toolchain file" 에러, README에 경로 적어도 누락 발생

해결: CMakeUserPresets.json에 개인 경로만 두고, CMakePresets.json$env{VCPKG_ROOT}로 환경 변수에 위임. .env.exampleVCPKG_ROOT= 예시만 문서화.

시나리오 7: IDE 프로필 불일치

상황: CLion은 cmake-build-debug/, VS Code는 build/, Visual Studio는 out/ 사용
문제: Git에 build 결과가 실수로 커밋되거나, .gitignore가 복잡해짐
결과: 빌드 산출물 경로가 제각각이라 정리·배포 스크립트 작성 어려움

해결: Preset의 binaryDir${sourceDir}/build/${presetName}로 통일. 모든 IDE가 동일 preset을 쓰면 build/ 하위만 관리하면 됨.

flowchart TB
  subgraph Problems[문제]
    P1[팀 설정 불일치]
    P2[CI 빌드 실패]
    P3[vcpkg/Conan 혼재]
    P4[멀티 플랫폼]
  end

  subgraph Solutions[CMake Presets 해결]
    S1[CMakePresets.json]
    S2[ci-release preset]
    S3[toolchainFile preset]
    S4[플랫폼별 preset]
  end

  P1 --> S1
  P2 --> S2
  P3 --> S3
  P4 --> S4

2. CMake Presets 기본 구조

2.1 파일 위치와 역할

파일용도Git
CMakePresets.json프로젝트 공통 설정✅ 커밋
CMakeUserPresets.json개발자 개인 설정❌ .gitignore

CMakeUserPresets.json이 있으면 CMakePresets.json을 암시적으로 include합니다. 개인용 경로·컴파일러 등은 User 쪽에 두세요.

2.2 최소 구성 예제

{
  "version": 3,
  "configurePresets": [
    {
      "name": "default",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/default",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_CXX_STANDARD": "17"
      }
    }
  ],
  "buildPresets": [
    {
      "name": "default",
      "configurePreset": "default"
    }
  ]
}

사용:

cmake --preset default
cmake --build build/default

또는 build preset 사용:

cmake --preset default
cmake --build --preset default

2.3 상속 (inherits)

공통 설정을 base preset에 두고, 다른 preset이 상속합니다.

{
  "version": 3,
  "configurePresets": [
    {
      "name": "base",
      "hidden": true,
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/${presetName}",
      "cacheVariables": {
        "CMAKE_CXX_STANDARD": "17",
        "CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
      }
    },
    {
      "name": "debug",
      "inherits": "base",
      "displayName": "Debug",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug"
      }
    },
    {
      "name": "release",
      "inherits": "base",
      "displayName": "Release",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    }
  ],
  "buildPresets": [
    { "name": "debug", "configurePreset": "debug" },
    { "name": "release", "configurePreset": "release" }
  ]
}
  • hidden: true: 직접 사용 불가, 상속용 base만
  • inherits: 문자열 또는 배열 ["base", "other"]
  • $presetName: preset 이름 매크로 (binaryDir 등에서 사용)

2.4 매크로 확장

매크로설명
${sourceDir}CMakeLists.txt가 있는 디렉터리
${presetName}현재 preset 이름
${hostSystemName}Windows, Linux, Darwin 등
$env{VAR}환경 변수 VAR
$penv{VAR}부모 환경의 VAR (prepend/append용)

3. 완전한 CMake Presets 예제

3.1 Debug / Release / RelWithDebInfo

{
  "version": 3,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 20,
    "patch": 0
  },
  "configurePresets": [
    {
      "name": "base",
      "hidden": true,
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/${presetName}",
      "cacheVariables": {
        "CMAKE_CXX_STANDARD": "17",
        "CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
      }
    },
    {
      "name": "debug",
      "inherits": "base",
      "displayName": "Debug (디버그 심볼)",
      "description": "디버깅용 빌드",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug"
      }
    },
    {
      "name": "release",
      "inherits": "base",
      "displayName": "Release (최적화)",
      "description": "배포용 빌드",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    },
    {
      "name": "relwithdebinfo",
      "inherits": "base",
      "displayName": "RelWithDebInfo",
      "description": "최적화 + 디버그 심볼",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "RelWithDebInfo"
      }
    }
  ],
  "buildPresets": [
    { "name": "debug", "configurePreset": "debug" },
    { "name": "release", "configurePreset": "release" },
    { "name": "relwithdebinfo", "configurePreset": "relwithdebinfo" }
  ]
}

3.2 GCC / Clang / MSVC 멀티 컴파일러

{
  "version": 3,
  "configurePresets": [
    {
      "name": "base",
      "hidden": true,
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/${presetName}",
      "cacheVariables": {
        "CMAKE_CXX_STANDARD": "17",
        "CMAKE_BUILD_TYPE": "Release"
      }
    },
    {
      "name": "gcc",
      "inherits": "base",
      "displayName": "GCC",
      "cacheVariables": {
        "CMAKE_C_COMPILER": "gcc",
        "CMAKE_CXX_COMPILER": "g++"
      }
    },
    {
      "name": "clang",
      "inherits": "base",
      "displayName": "Clang",
      "cacheVariables": {
        "CMAKE_C_COMPILER": "clang",
        "CMAKE_CXX_COMPILER": "clang++"
      }
    },
    {
      "name": "msvc",
      "inherits": "base",
      "displayName": "MSVC",
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Windows"
      },
      "generator": "Ninja Multi-Config",
      "architecture": {
        "value": "x64",
        "strategy": "set"
      },
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    }
  ],
  "buildPresets": [
    { "name": "gcc", "configurePreset": "gcc" },
    { "name": "clang", "configurePreset": "clang" },
    { "name": "msvc", "configurePreset": "msvc" }
  ]
}

주의: Ninja Multi-Config는 MSVC 등 멀티 설정 생성기에서 사용. 단일 설정(Ninja)에서는 CMAKE_BUILD_TYPE이 configure 시점에 고정됩니다.

3.3 Sanitizer (ASan, TSan, UBSan)

{
  "version": 3,
  "configurePresets": [
    {
      "name": "base",
      "hidden": true,
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/${presetName}",
      "cacheVariables": {
        "CMAKE_CXX_STANDARD": "17",
        "CMAKE_BUILD_TYPE": "Debug"
      }
    },
    {
      "name": "asan",
      "inherits": "base",
      "displayName": "AddressSanitizer",
      "cacheVariables": {
        "USE_ASAN": "ON",
        "USE_UBSAN": "ON"
      }
    },
    {
      "name": "tsan",
      "inherits": "base",
      "displayName": "ThreadSanitizer",
      "cacheVariables": {
        "USE_TSAN": "ON"
      }
    }
  ],
  "buildPresets": [
    { "name": "asan", "configurePreset": "asan" },
    { "name": "tsan", "configurePreset": "tsan" }
  ]
}

CMakeLists.txt에서 USE_ASAN, USE_TSAN 등으로 플래그를 분기합니다.

3.4 코드 커버리지 (gcov/lcov)

{
  "name": "coverage",
  "inherits": "base",
  "displayName": "Coverage",
  "cacheVariables": {
    "CMAKE_BUILD_TYPE": "Debug",
    "CMAKE_CXX_FLAGS": "--coverage",
    "CMAKE_EXE_LINKER_FLAGS": "--coverage"
  }
}

3.5 condition 상세 (플랫폼·환경별 분기)

condition으로 preset을 특정 OS·환경에서만 활성화할 수 있습니다. CMake 3.21+에서 지원합니다.

type설명용도
equalslhs == rhsOS, 아키텍처 비교
notEqualslhs != rhs환경 변수 미설정 시 제외
inListstring이 list에 포함여러 OS 지원 (Linux, Darwin)
notInListstring이 list에 미포함특정 OS 제외
matchesstring이 regex와 매칭버전·경로 패턴
notMatchesstring이 regex와 불일치예외 패턴
allOf모든 하위 condition이 true복합 조건 (AND)
anyOf하나라도 true복합 조건 (OR)
not조건 반전부정

예시: equals (Windows 전용), inList (Linux·macOS), allOf (복합)

{
  "name": "msvc-release",
  "condition": { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" }
}
{
  "name": "unix-release",
  "condition": {
    "type": "inList",
    "string": "${hostSystemName}",
    "list": ["Linux", "Darwin"]
  }
}
{
  "name": "ci-release",
  "condition": {
    "type": "allOf",
    "conditions": [
      { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux" },
      { "type": "notEquals", "lhs": "$env{CI}", "rhs": "" }
    ]
  }
}

3.6 buildPresets 완전 예제 (targets, jobs, verbose)

{
  "buildPresets": [
    {
      "name": "release",
      "configurePreset": "release",
      "jobs": 8,
      "configuration": "Release"
    },
    {
      "name": "release-single",
      "configurePreset": "release",
      "targets": [myapp],
      "jobs": 1
    },
    {
      "name": "release-verbose",
      "configurePreset": "release",
      "verbose": true
    }
  ]
}
  • jobs(-j), targets(특정 타깃), configuration(멀티 설정), verbose(상세 로그).

3.7 testPresets 완전 예제 (filter, output, execution)

{
  "testPresets": [
    {
      "name": "default",
      "configurePreset": "release",
      "output": {
        "outputOnFailure": true,
        "verbosity": "verbose"
      },
      "execution": {
        "noTestsAction": "error",
        "stopOnFailure": true,
        "jobs": 4
      }
    },
    {
      "name": "unit-only",
      "configurePreset": "release",
      "filter": { "include": { "label": "unit" } },
      "output": { "outputOnFailure": true }
    },
    {
      "name": "ci-test",
      "configurePreset": "ci-release",
      "output": {
        "outputOnFailure": true,
        "outputJUnitFile": "${sourceDir}/test-results.xml"
      },
      "execution": { "noTestsAction": "error", "stopOnFailure": true }
    }
  ]
}
ctest --preset default
ctest --preset unit-only
ctest --preset ci-test
  • filter.include.label: set_tests_properties(..., LABELS "unit")와 매칭. output.outputJUnitFile: CI JUnit XML.

4. vcpkg·Conan 연동

4.1 vcpkg 연동

{
  "version": 3,
  "configurePresets": [
    {
      "name": "base",
      "hidden": true,
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/${presetName}",
      "cacheVariables": {
        "CMAKE_CXX_STANDARD": "17",
        "CMAKE_BUILD_TYPE": "Release"
      }
    },
    {
      "name": "vcpkg-default",
      "inherits": "base",
      "displayName": "vcpkg (Release)",
      "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
      "cacheVariables": {
        "VCPKG_TARGET_TRIPLET": "$env{VCPKG_DEFAULT_TRIPLET}"
      }
    },
    {
      "name": "vcpkg-debug",
      "inherits": "vcpkg-default",
      "displayName": "vcpkg (Debug)",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug",
        "VCPKG_TARGET_TRIPLET": "x64-windows-static"
      }
    }
  ],
  "buildPresets": [
    { "name": "vcpkg-default", "configurePreset": "vcpkg-default" },
    { "name": "vcpkg-debug", "configurePreset": "vcpkg-debug" }
  ]
}

사전 설정:

# 환경 변수 설정 (쉘 또는 .env)
export VCPKG_ROOT=/path/to/vcpkg
export VCPKG_DEFAULT_TRIPLET=x64-linux  # 또는 x64-windows, arm64-osx 등

4.2 Conan 연동

Conan은 conan installconan_toolchain.cmake가 생성됩니다. Preset에서 이 경로를 지정합니다.

{
  "name": "conan-release",
  "inherits": "base",
  "displayName": "Conan (Release)",
  "toolchainFile": "${sourceDir}/build/conan_toolchain.cmake",
  "cacheVariables": {
    "CMAKE_BUILD_TYPE": "Release"
  }
}

빌드 순서:

# 1. Conan install (preset보다 먼저)
conan install . --output-folder=build --build=missing

# 2. CMake configure (preset 사용)
cmake --preset conan-release

# 3. Build
cmake --build build

주의: Conan의 --output-folder와 preset의 binaryDir가 일치해야 합니다. 위 예에서는 둘 다 build입니다.

4.3 vcpkg + Conan 혼용 프로젝트 (팀 분리)

팀 내에서 vcpkg 사용자와 Conan 사용자가 공존할 때, 각자 자신의 preset만 사용하도록 분리합니다.

{
  "version": 3,
  "configurePresets": [
    {
      "name": "vcpkg-release",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/vcpkg-release",
      "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_CXX_STANDARD": "17"
      }
    },
    {
      "name": "conan-release",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/conan-release",
      "toolchainFile": "${sourceDir}/build/conan_toolchain.cmake",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_CXX_STANDARD": "17"
      }
    }
  ]
}

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

에러 1: “Could not find a preset named “default""

원인: CMakePresets.json에 해당 이름의 preset이 없거나, CMakeUserPresets.json만 있고 CMakePresets.json이 없음.

해결법:

# preset 목록 확인
cmake --list-presets

CMakePresets.json이 프로젝트 루트에 있는지, configurePresetsname: "default"가 있는지 확인하세요.

에러 2: “Preset inherits from “base” which is not defined”

원인: inherits로 참조한 preset이 같은 파일 또는 include된 파일에 없음. 또는 CMakeUserPresets.json의 preset이 CMakePresets.json의 preset을 상속할 때, User 파일이 Presets를 include하지 않음.

해결법: CMakeUserPresets.json에서 상속하려면 includeCMakePresets.json을 명시합니다 (버전 4+). 또는 User 파일이 있으면 Presets가 암시적으로 include되므로, Presets 파일에 base가 있는지 확인하세요.

에러 3: “CMAKE_TOOLCHAIN_FILE” or “toolchainFile” 경로 오류

증상: Could not find toolchain file 또는 vcpkg.cmake not found.

원인: $env{VCPKG_ROOT}가 설정되지 않았거나, 경로가 잘못됨.

해결법:

# VCPKG_ROOT 확인
echo $VCPKG_ROOT

# 설정
export VCPKG_ROOT=/opt/vcpkg   # 또는 Windows: set VCPKG_ROOT=C:\vcpkg

상대 경로 사용 시:

"toolchainFile": "${sourceDir}/cmake/toolchain.cmake"

에러 4: “binaryDir”가 매번 덮어씌워짐

증상: debug와 release 빌드가 같은 build/를 쓰면서 설정이 꼬임.

원인: binaryDir${sourceDir}/build로 고정해 둠.

해결법:

"binaryDir": "${sourceDir}/build/${presetName}"

각 preset마다 build/debug, build/release처럼 분리됩니다.

에러 5: Windows에서 “Ninja Multi-Config” 관련 에러

증상: Generator Ninja Multi-Config does not support single-configuration builds.

원인: Ninja(단일 설정)와 CMAKE_BUILD_TYPE을 같이 쓰면 되는데, Ninja Multi-Config에서는 CMAKE_BUILD_TYPE 대신 --config Release로 빌드 시점에 지정합니다.

해결법:

cmake --preset msvc
cmake --build build/msvc --config Release

또는 build preset에서 configuration 지정:

{
  "name": "msvc-release",
  "configurePreset": "msvc",
  "configuration": "Release"
}

에러 6: “condition”으로 숨긴 preset이 목록에 안 나옴

증상: cmake --list-presets에 Windows용 preset이 Linux에서 안 보임.

원인: conditionfalse이면 해당 preset은 사용 불가.

해결법: 정상 동작입니다. 플랫폼별 preset은 해당 OS에서만 보이도록 설계된 것입니다.

에러 7: cacheVariables가 적용 안 됨

증상: CMAKE_BUILD_TYPE=Release를 넣었는데 Debug로 빌드됨.

원인: 상속 순서. 자식 preset의 cacheVariables가 부모보다 우선합니다. 또는 Ninja Multi-Config에서는 CMAKE_BUILD_TYPE이 무시되고 --config가 우선합니다.

해결법: 단일 설정 생성기(Ninja, Makefile)에서는 CMAKE_BUILD_TYPE이 configure 시점에 적용됩니다. cmake --build--config Release를 붙이거나, build preset에 configuration을 넣으세요.

에러 8: Conan preset에서 “conan_toolchain.cmake not found”

원인: conan install을 하지 않았거나, --output-folder 경로가 preset의 binaryDir와 다름.

해결법:

# Conan install을 build 디렉터리에 출력
conan install . --output-folder=build --build=missing

# preset의 binaryDir가 build인지 확인
# toolchainFile: "${sourceDir}/build/conan_toolchain.cmake"

에러 9: JSON 문법 오류

증상: Expecting ',' delimiter 또는 Unexpected token.

원인: JSON에서 마지막 요소 뒤에 쉼표를 넣으면 안 됨. "name": "x" 뒤에 ,만 있고 다음 필드가 없으면 오류.

해결법:

❌ 잘못된 예: "name": "default", 뒤에 쉼표만 있고 다음 필드 없음
{
  "name": "default"
}
✅ 올바른 예: 마지막 필드 뒤에는 쉼표 없음

에러 10: “version” 필드 누락 또는 잘못된 버전

증상: Unsupported version 또는 schema 검증 실패.

해결법: version은 정수입니다. 3 또는 4 이상 사용. cmakeMinimumRequired는 선택 사항이지만, 팀 협업 시 명시하면 좋습니다.

{
  "version": 3,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 20,
    "patch": 0
  }
}

에러 11: inherits 순환 참조

증상: Preset "A" inherits from "B" which inherits from "A" 또는 비슷한 순환 에러.

원인: ABA처럼 상속 체인이 순환함.

해결법: 상속 구조를 트리 형태로 유지. basedebugdebug-asan처럼 단방향으로만 상속.

에러 12: condition에서 환경 변수 미설정

증상: $env{VCPKG_ROOT}를 condition에서 쓰는데, 변수가 없으면 preset이 비활성화되거나 에러.

원인: notEquals에서 $env{X}가 빈 문자열일 때 "rhs": ""와 비교하면, 변수 미설정 시 예상과 다르게 동작할 수 있음.

해결법: 환경 변수 의존 preset은 CMakeUserPresets.json에 두거나, CI에서 반드시 해당 변수를 export한 뒤 실행.


6. 베스트 프랙티스

6.1 base preset 분리

공통 설정은 hidden base에 두고, 나머지는 inherits로 상속합니다. 중복을 줄이고 수정 지점을 한 곳으로 모읍니다.

{
  "name": "base",
  "hidden": true,
  "generator": "Ninja",
  "binaryDir": "${sourceDir}/build/${presetName}",
  "cacheVariables": {
    "CMAKE_CXX_STANDARD": "17",
    "CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
  }
}

6.2 binaryDir를 preset별로 분리

build/${presetName} 패턴을 사용하면 Debug/Release, 컴파일러별로 디렉터리가 분리되어 설정이 섞이지 않습니다.

6.3 환경 변수는 User Presets에

VCPKG_ROOT, CONAN_HOME 등 개발자마다 다른 경로는 CMakeUserPresets.json에 두고 Git에 넣지 않습니다.

// CMakeUserPresets.json
{
  "version": 3,
  "configurePresets": [
    {
      "name": "my-vcpkg",
      "inherits": "vcpkg-default",
      "toolchainFile": "/home/me/vcpkg/scripts/buildsystems/vcpkg.cmake"
    }
  ]
}

6.4 cmakeMinimumRequired 명시

팀 전체가 동일한 CMake 버전 이상을 쓰도록 제한합니다.

"cmakeMinimumRequired": {
  "major": 3,
  "minor": 23,
  "patch": 0
}

6.5 displayName, description 활용

IDE에서 preset 목록을 볼 때 사람이 읽기 쉬운 이름을 표시합니다.

{
  "name": "vcpkg-release",
  "displayName": "vcpkg Release",
  "description": "vcpkg로 의존성 관리, Release 빌드"
}

6.6 condition으로 플랫폼 제한

Windows 전용 preset은 Windows에서만 보이게 합니다.

{
  "name": "msvc",
  "condition": {
    "type": "equals",
    "lhs": "${hostSystemName}",
    "rhs": "Windows"
  }
}

6.7 testPresets·buildPresets 쌍으로 정의

configure preset마다 대응하는 build·test preset을 두면 cmake --build --preset X, ctest --preset X로 일관되게 사용할 수 있습니다.

6.8 cacheVariables 타입 명시 (선택)

BOOL, PATH 등 타입을 명시하면 IDE에서 더 정확히 해석합니다: "BUILD_SHARED_LIBS": { "type": "BOOL", "value": "OFF" }.


7. 프로덕션 패턴

7.1 CI/CD 통합 (GitHub Actions)

name: Build

on: [push, pull_request]

jobs:
  build-linux:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4

      - name: Install CMake
        uses: jwlawson/actions-setup-cmake@v2
        with:
          cmake-version: '3.28'

      - name: Configure
        run: cmake --preset ci-release

      - name: Build
        run: cmake --build --preset ci-release

CMakePresets.jsonci-release preset 정의: "inherits": "base", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }

7.2 CI 캐시로 빌드 시간 단축

- uses: actions/cache@v4
  with:
    path: build
    key: ${{ runner.os }}-cmake-${{ hashFiles('CMakeLists.txt', 'CMakePresets.json', '**/CMakeLists.txt') }}

7.3 멀티 플랫폼 CI (Linux, macOS, Windows)

strategy:
  matrix:
    include:
      - { os: ubuntu-22.04, preset: linux-release }
      - { os: macos-14, preset: macos-release }
      - { os: windows-2022, preset: msvc-release }
runs-on: ${{ matrix.os }}
steps:
  - uses: actions/checkout@v4
  - run: cmake --preset ${{ matrix.preset }}
  - run: cmake --build --preset ${{ matrix.preset }}

7.4 testPresets 활용

CMake 3.20+에서 ctest --preset default로 테스트 실행. 상세 예제는 3.7절 참고.

7.5 workflowPresets (CMake 3.26+)

configure → build → test → package를 한 번에 실행: "steps": [{ "type": "configure", "name": "ci-release" }, { "type": "build", "name": "ci-release" }, { "type": "test", "name": "default" }]cmake --workflow --preset ci

7.6 include로 설정 분리

대형 프로젝트에서는 preset을 여러 파일로 나눌 수 있습니다 (버전 4+).

{
  "version": 4,
  "include": ["presets/linux.json", "presets/windows.json", "presets/ci.json"]
}

7.7 GitLab CI / Jenkins 연동

# .gitlab-ci.yml
build:
  script:
    - cmake --preset ci-release
    - cmake --build --preset ci-release
    - ctest --preset ci-test
// Jenkinsfile
sh 'cmake --preset ci-release && cmake --build --preset ci-release && ctest --preset ci-test'

7.8 packagePresets로 배포 패키지 생성 (CMake 3.26+)

{
  "packagePresets": [
    {
      "name": "release-tgz",
      "configurePreset": "release",
      "generators": [TGZ]
    }
  ]
}
cpack --preset release-tgz

8. 구현 체크리스트

CMake Presets: CMake 3.19+ (configure), 3.20+ (build/test) · CMakePresets.json 루트 · CMakeUserPresets.json .gitignore · base (hidden) · binaryDir: ${sourceDir}/build/${presetName} · Debug/Release 분리 · vcpkg/Conan 시 toolchainFile · cmakeMinimumRequired · displayName, description

CI/CD: cmake --preset, cmake --build --preset · build/캐시 캐싱 · 플랫폼별 preset · ctest --preset

팀 협업: cmake --list-presets 안내 · README 문서화 · VCPKG_ROOT 등 환경 변수 문서화


9. 정리

항목설명
CMakePresets.json프로젝트 공통, Git 커밋
CMakeUserPresets.json개인 설정, .gitignore
inheritsbase 상속으로 중복 제거
binaryDir${sourceDir}/build/${presetName}
toolchainFilevcpkg, Conan 연동
condition플랫폼별 preset 제한

핵심: 팀 전체 동일 preset · base로 공통 설정 통합 · binaryDir preset별 분리 · vcpkg/Conan은 toolchainFile


자주 묻는 질문 (FAQ)

  • CMake 3.19 미만? Configure 3.19+, Build/Test 3.20+ 필요.
  • IDE에서 preset 안 보임? CLion 2022.2+, VS 2022 17.5+, VS Code CMake Tools. 루트에 CMakePresets.json·JSON 문법 확인.
  • vcpkg+Conan 동시 사용? 권장하지 않음. 하나 선택 후 preset 분리.
  • CMakeUserPresets.json? Presets 복사 후 개인 경로 수정. inherits로 상속.
  • preset 목록? cmake --list-presets 또는 --all(hidden 포함).

참고 자료

한 줄 요약: CMake Presets로 팀 빌드 설정을 통일하고, vcpkg·Conan·CI/CD와 seamlessly 연동할 수 있습니다.


관련 글

  • CMake 입문 | 수십 개 파일 컴파일할 때 필요한 빌드 자동화 (CMakeLists.txt 기초)
  • C++ CI/CD GitHub Actions 완벽 가이드 | 워크플로·매트릭스·캐싱·아티팩트·배포
  • C++ CMake 완벽 가이드 | 크로스 플랫폼 빌드·최신 CMake 3.28+ 기능·프리셋·모듈
  • C++ CMake |
... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3