C++ 개발자라면 CMake로 프로젝트를 빌드하는 경우가 많을 것이다. 아마 대부분 cmake .나 cmake --build . 같은 기본적인 명령어는 익숙하리라 생각한다. 그런데 혹시 이런 경험이 있지 않은가?
cmake -S . -B build_debug -DCMAKE_BUILD_TYPE=Debug -G "Ninja"처럼 길고 복잡한 옵션들을 매번 입력하게 된다.- 디버그(
Debug) 빌드와 릴리즈(Release) 빌드를 왔다 갔다 할 때마다 명령줄을 일일이 수정하는 게 귀찮다. - "이상하다, 내 컴퓨터에서는 빌드가 잘 되는데 왜 네 컴퓨터에서는 안 되지?" 팀원들마다 빌드 설정이 미묘하게 달라 겪는 문제가 빈번하다.
- CI/CD 파이프라인에서 일관되고 재현 가능한 빌드 환경을 구축하는 데 어려움을 느낀다.
만약 이런 문제들로 고민하고 있다면, 오늘 소개할 CMake의 --preset 기능이 빌드 워크플로우를 훨씬 간결하고 효율적으로 바꿔줄 것이다.
--preset, 도대체 무엇인가
--preset은 CMake 프로젝트의 설정(Configuration), 빌드(Build), 테스트(Test) 과정을 미리 정의하고 재사용할 수 있도록 돕는 기능이다. 쉽게 말해, 복잡한 CMake 명령줄 옵션들을 .json 파일(주로 CMakePresets.json) 안에 저장해두고, 필요할 때마다 그 이름을 불러서 사용하는 방식인 것이다.
프로젝트의 package.json 파일에 scripts를 정의해서 긴 npm 명령어를 짧게 줄여 쓰거나, Makefile에 여러 타겟을 정의해 두고 필요한 타겟만 실행하는 것과 비슷하다고 생각할 수 있다. 다만 --preset은 CMake 빌드 시스템 자체에 통합되어 있어 훨씬 더 강력하고 유연하다.
왜 지금 --preset을 사용해야 할까
기존 CMake 사용법에 익숙한 개발자라면 --preset이 왜 필요한지 궁금할 수 있다. 다음 세 가지 핵심적인 이유가 --preset의 도입을 강력하게 추천하는 근거이다.
1. 지겨운 반복 작업에서 해방! 명령줄 간소화
매일 이런 명령어를 입력하는 데 지쳤을 수 있다.
cmake -S . -B build_debug -DCMAKE_BUILD_TYPE=Debug -G "Ninja" -DBUILD_TESTS=ON
하지만 --preset을 사용하면 이렇게 간단해진다.
cmake --preset debug
훨씬 깔끔하고, 오타를 낼 확률도 줄어든다. 매번 복잡한 옵션들을 외우거나 찾아볼 필요 없이, 설정해 둔 프리셋 이름만 기억하면 되기 때문이다.
2. 빌드 일관성 및 재현 가능성 확보
팀 프로젝트에서 가장 중요한 것 중 하나가 바로 "내 컴퓨터에서는 잘 되는데..." 문제를 없애는 것이다.
- 팀 협업:
CMakePresets.json파일은 프로젝트 저장소에 함께 커밋되어 모든 팀원이 동일한 빌드 환경 설정을 공유할 수 있다. 이는 빌드 환경 불일치로 인한 시간을 낭비하는 일을 현저히 줄여준다. - CI/CD 통합: CI/CD 파이프라인에서 빌드 명령을 표준화하고 자동화하는 데 최적이다. 특정 프리셋 이름만 지정하면 되므로, 스크립트가 훨씬 간결해지고 안정적인 빌드 환경을 보장한다.
3. 다양한 환경 전환의 용이성 및 IDE 연동
디버그 빌드로 개발하다가 성능 측정을 위해 릴리즈 빌드로 바꿔야 할 때, 혹은 특정 컴파일러나 플랫폼에서 빌드해야 할 때가 있다. --preset은 이 모든 것을 손쉽게 전환할 수 있게 해준다.
또한, Visual Studio, VS Code, CLion 등 최신 IDE들은 CMakePresets.json 파일을 자동으로 인식하고 지원한다. 덕분에 IDE 내에서 클릭 몇 번만으로 원하는 빌드 프리셋을 선택하고 빌드할 수 있다.
CMakePresets.json 파헤치기
--preset의 모든 마법은 프로젝트 루트 디렉토리에 위치하는 CMakePresets.json 파일에 담겨 있다. (개인적인 설정은 버전 관리에 포함시키지 않는 CMakeUserPresets.json 파일을 사용할 수도 있다.)
기본적인 구조는 다음과 같습니다.
{
"version": 6, // 현재 프리셋 파일의 스키마 버전 (최신 버전 사용 권장)
"configurePresets": [], // 프로젝트 설정(Configuration) 관련 프리셋 정의
"buildPresets": [], // 프로젝트 빌드(Build) 관련 프리셋 정의
"testPresets": [] // 프로젝트 테스트(Test) 관련 프리셋 정의
}
각 섹션이 어떤 역할을 하는지 좀 더 자세히 알아보자.
1. configurePresets: cmake 명령어의 옵션들을 정의
이 섹션은 cmake 명령줄에서 -G, -B, -D 등으로 지정하던 모든 설정들을 정의한다.
{
"name": "debug",
"displayName": "Debug Build (Ninja)",
"description": "Ninja 제너레이터를 사용한 디버그 빌드 설정",
"generator": "Ninja", // -G 옵션: 사용할 빌드 시스템 제너레이터
"binaryDir": "${sourceDir}/build/debug", // -B 옵션: 빌드 파일이 생성될 디렉토리
"cacheVariables": { // -D 옵션: CMake 캐시 변수 설정
"CMAKE_BUILD_TYPE": "Debug",
"BUILD_SHARED_LIBS": "ON" // 사용자 정의 옵션
},
"inherits": ["common_options"] // 다른 프리셋을 상속받을 수 있다.
}
name: 이 프리셋을 호출할 때 사용할 고유한 이름이다. (cmake --preset debug의debug)generator: 빌드 시스템 제너레이터(예:"Ninja","Visual Studio 17 2022","Unix Makefiles")를 지정한다.binaryDir: 빌드 파일이 생성될 디렉토리를 지정한다.${sourceDir}는 CMakeLists.txt가 있는 프로젝트 루트 디렉토리를 의미한다.cacheVariables:CMAKE_BUILD_TYPE과 같은 표준 CMake 변수나, 프로젝트에서 정의한 커스텀 옵션(예:BUILD_SHARED_LIBS)을 설정할 수 있다.
2. buildPresets: cmake --build 명령어의 옵션들을 정의
설정된 프로젝트를 실제로 빌드할 때 사용한다. 중요한 것은 이 프리셋이 어떤 configurePreset을 기반으로 빌드할지 명시해야 한다는 점이다.
{
"name": "debug",
"displayName": "디버그 빌드 실행",
"configurePreset": "debug", // 이 빌드는 'debug' configurePreset을 사용한다.
"targets": ["all"], // --target 옵션: 빌드할 타겟 (예: "all", "install", 특정 라이브러리/실행 파일)
"cleanFirst": true // 빌드 전 깨끗하게 클린 (선택 사항)
}
name: 빌드 프리셋의 이름이다.configurePreset: 가장 중요하다. 이 빌드 프리셋이 어떤 설정 프리셋을 참조할지 지정한다. 먼저configurePreset으로 프로젝트 설정이 완료되어 있어야 이 빌드 프리셋을 사용할 수 있다.
3. testPresets: cmake --test 명령어의 옵션들을 정의
빌드된 프로젝트의 테스트를 실행할 때 사용한다.
{
"name": "default",
"displayName": "기본 테스트 실행",
"configurePreset": "debug", // 이 테스트는 'debug' configurePreset으로 설정된 빌드를 기반으로 한다.
"output": {"outputOnFailure": true} // 테스트 실패 시에만 결과 출력
}
실전 적용: 단계별 --preset 활용법
이제 직접 CMakePresets.json을 만들고 사용해 보자.
간단한 CMakeLists.txt에서 시작한다.
# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject LANGUAGES CXX)
add_executable(my_app main.cpp)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
if(BUILD_SHARED_LIBS)
add_library(my_lib SHARED my_lib.cpp)
else()
add_library(my_lib STATIC my_lib.cpp)
endif()
단계 1: CMakePresets.json 파일 생성 및 기본 설정
프로젝트 루트 디렉토리에 CMakePresets.json 파일을 생성하고 다음 내용을 추가한다.
// CMakePresets.json
{
"version": 6,
"configurePresets": [
{
"name": "debug",
"displayName": "Debug (Ninja)",
"description": "디버그 빌드를 위한 Ninja 제너레이터 설정",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BUILD_SHARED_LIBS": "OFF"
}
},
{
"name": "release",
"displayName": "Release (Ninja)",
"description": "릴리즈 빌드를 위한 Ninja 제너레이터 설정",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"BUILD_SHARED_LIBS": "ON"
}
}
],
"buildPresets": [
{
"name": "debug",
"displayName": "Debug 빌드",
"configurePreset": "debug",
"targets": ["all"]
},
{
"name": "release",
"displayName": "Release 빌드",
"configurePreset": "release",
"targets": ["all"]
}
],
"testPresets": [
{
"name": "default_test",
"displayName": "기본 테스트 실행",
"configurePreset": "debug"
}
]
}
이 설정은 debug와 release 두 가지 환경을 정의한다. 디버그는 정적 라이브러리 빌드를, 릴리즈는 공유 라이브러리 빌드를 하도록 설정했다.
단계 2: 프로젝트 설정 (Configure)
이제 터미널을 열고 프로젝트 루트 디렉토리에서 다음 명령어를 실행한다.
cmake --preset debug
이 명령어는 CMakePresets.json에 정의된 debug configurePreset을 사용하여 프로젝트를 설정한다. build/debug 디렉토리가 생성되고, 그 안에 build.ninja 등의 빌드 파일이 만들어지는 것을 확인할 수 있다.
단계 3: 프로젝트 빌드 (Build)
설정이 완료되었다면, 이제 빌드할 차례이다.
cmake --build --preset debug
이 명령어는 debug buildPreset을 사용하여 프로젝트를 빌드한다. my_app 실행 파일과 my_lib.a (정적 라이브러리)가 build/debug 디렉토리에 생성될 것이다.
릴리즈 빌드를 하고 싶다면 간단히 release 프리셋을 사용하면 된다.
cmake --preset release # 릴리즈 설정
cmake --build --preset release # 릴리즈 빌드
이 경우 build/release 디렉토리에 my_app 실행 파일과 my_lib.so (공유 라이브러리, 리눅스 기준)가 생성될 것이다.
단계 4: 사용 가능한 프리셋 확인
어떤 프리셋이 정의되어 있는지 잊었을 때는 다음 명령어로 확인할 수 있다.
cmake --list-presets
또는 특정 타입만 보고 싶다면:
cmake --list-configure-presets
cmake --list-build-presets
cmake --list-test-presets
IDE 연동 맛보기
대부분의 최신 IDE(Visual Studio, VS Code with CMake Tools, CLion)는 CMakePresets.json 파일을 자동으로 인식한다. IDE의 빌드 설정 메뉴나 상태 표시줄에서 정의된 프리셋 목록을 선택하여 빌드 환경을 손쉽게 전환할 수 있다. 이를 통해 개발 생산성을 향상시킬 수 있을 것이다.
--preset 더 깊이 파고들기
--preset은 여기에 소개된 것 외에도 더 많은 기능을 제공한다.
CMakeUserPresets.json: 로컬 환경 설정이나 개인적인 테스트 용도로 사용할 수 있다. 이 파일은.gitignore에 추가하여 버전 관리에 포함되지 않도록 하는 것이 일반적이다.inherits: 여러 프리셋 간에 공통된 설정을 공유할 때 사용한다. 코드 중복을 줄이고 관리하기 쉽게 해준다.condition: 운영체제나 아키텍처에 따라 특정 프리셋을 활성화/비활성화하거나 다르게 설정할 수 있다.
결론: 이제 더 이상 힘들게 명령어를 입력하지 말자.
CMake --preset은 단순히 명령줄을 줄여주는 것을 넘어, 빌드 환경의 일관성, 재현 가능성, 그리고 관리 용이성을 개선해 주는 강력한 도구이다. 복잡한 빌드 스크립트에 시간을 낭비하는 대신, --preset을 활용하여 효율적인 개발 워크플로우를 구축하자.
'잡(job)기술' 카테고리의 다른 글
| C++20 코루틴과 awaitable task (0) | 2025.09.03 |
|---|---|
| C++20 코루틴으로 직접 구현하는 Generator (0) | 2025.09.03 |
| Node.js child_process의 exec와 spawn 차이 정리 (0) | 2025.06.20 |
| pickle 모듈을 이용한 캐싱 관리 기법 (2) | 2025.06.18 |
| TypeORM 마이그레이션 사용하기: 안전한 데이터베이스 관리를 위한 단계별 가이드 (0) | 2025.05.30 |