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/Conan | toolchainFile로 자동 지정 |
| 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++ 프로젝트에서 실제로 겪은 문제와 해결 과정을 바탕으로 작성되었습니다. 책이나 문서에서 다루지 않는 실전 함정과 디버깅 팁을 포함합니다.
목차
- 문제 시나리오 상세
- CMake Presets 기본 구조
- 완전한 CMake Presets 예제
- vcpkg·Conan 연동
- 자주 발생하는 에러와 해결법
- 베스트 프랙티스
- 프로덕션 패턴
- 구현 체크리스트
- 정리
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.json에 default, 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.example에 VCPKG_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 | 설명 | 용도 |
|---|---|---|
equals | lhs == rhs | OS, 아키텍처 비교 |
notEquals | lhs != rhs | 환경 변수 미설정 시 제외 |
inList | string이 list에 포함 | 여러 OS 지원 (Linux, Darwin) |
notInList | string이 list에 미포함 | 특정 OS 제외 |
matches | string이 regex와 매칭 | 버전·경로 패턴 |
notMatches | string이 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 install 후 conan_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이 프로젝트 루트에 있는지, configurePresets에 name: "default"가 있는지 확인하세요.
에러 2: “Preset inherits from “base” which is not defined”
원인: inherits로 참조한 preset이 같은 파일 또는 include된 파일에 없음. 또는 CMakeUserPresets.json의 preset이 CMakePresets.json의 preset을 상속할 때, User 파일이 Presets를 include하지 않음.
해결법: CMakeUserPresets.json에서 상속하려면 include로 CMakePresets.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에서 안 보임.
원인: condition이 false이면 해당 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" 또는 비슷한 순환 에러.
원인: A → B → A처럼 상속 체인이 순환함.
해결법: 상속 구조를 트리 형태로 유지. base → debug → debug-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.json에 ci-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 |
| inherits | base 상속으로 중복 제거 |
| binaryDir | ${sourceDir}/build/${presetName} |
| toolchainFile | vcpkg, 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 |