
C나 C++ 프로젝트를 처음 시작하면 빌드 시스템 얘기가 빠지지 않습니다. 파일이 하나면 g++ main.cpp -o app으로 끝나는데, 파일이 여러 개로 늘어나고 외부 라이브러리가 붙기 시작하면 컴파일 명령어가 감당이 안 됩니다.
CMake는 그 빌드 과정을 기술하는 도구입니다. 정확히는 빌드 시스템을 생성하는 도구인데, CMakeLists.txt에 프로젝트 구조와 의존성을 정의해두면 플랫폼에 맞는 빌드 파일(Makefile, Ninja 파일, Visual Studio 솔루션 등)을 만들어줍니다.
1편에서는 CMake의 기본 개념, CMakeLists.txt 작성 방법, 빌드 타입과 옵션을 정리합니다.
빌드 흐름
CMake의 빌드는 두 단계로 나뉩니다.
Configure → Build
(cmake) (cmake --build)
Configure 단계에서 CMakeLists.txt를 읽고 플랫폼에 맞는 빌드 파일을 생성합니다. Build 단계에서 그 빌드 파일을 실행해서 실제로 컴파일합니다.
# 기본 흐름
mkdir build && cd build
cmake .. # configure (상위 디렉토리의 CMakeLists.txt 읽기)
cmake --build . # build
소스 디렉토리와 빌드 디렉토리를 분리하는 게 관례입니다. build/ 디렉토리에 생성된 파일들이 몰려서 소스가 깔끔하게 유지됩니다.
설치
# Ubuntu / Debian
sudo apt install cmake
# macOS
brew install cmake
# 버전 확인
cmake --version
CMake 버전에 따라 쓸 수 있는 기능이 달라집니다. 3.15 이상을 쓰는 게 권장됩니다. 최신 기능을 쓰려면 3.20 이상이 좋습니다.
CMakeLists.txt 기본 구조
모든 프로젝트는 루트에 CMakeLists.txt를 가집니다.
cmake_minimum_required(VERSION 3.20)
project(MyApp
VERSION 1.0.0
DESCRIPTION "내 첫 CMake 프로젝트"
LANGUAGES CXX
)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(myapp main.cpp)
cmake_minimum_required
이 프로젝트가 요구하는 최소 CMake 버전을 지정합니다. 항상 첫 줄에 씁니다.
cmake_minimum_required(VERSION 3.20)
project
프로젝트 이름, 버전, 언어를 정의합니다. LANGUAGES에 C, CXX, CUDA 등을 지정합니다. 생략하면 C와 CXX가 기본입니다.
project(MyProject VERSION 2.1.0 LANGUAGES CXX)
project() 호출 후 PROJECT_NAME, PROJECT_VERSION 같은 변수를 쓸 수 있습니다.
변수
set으로 변수 정의
set(변수명 값)
set(APP_NAME "myapp")
set(SRC_FILES main.cpp utils.cpp parser.cpp)
# 사용
message("앱 이름: ${APP_NAME}")
add_executable(${APP_NAME} ${SRC_FILES})
변수를 쓸 때는 ${변수명} 형태입니다.
자주 쓰는 내장 변수
CMAKE_SOURCE_DIR # 최상위 CMakeLists.txt 위치
CMAKE_BINARY_DIR # 빌드 디렉토리 (cmake를 실행한 위치)
CMAKE_CURRENT_SOURCE_DIR # 현재 처리 중인 CMakeLists.txt 위치
CMAKE_CURRENT_BINARY_DIR # 현재 빌드 디렉토리
PROJECT_NAME # project()에서 지정한 이름
PROJECT_VERSION # project()에서 지정한 버전
CMAKE_CXX_STANDARD # C++ 표준 버전
CMAKE_BUILD_TYPE # 빌드 타입 (Debug, Release 등)
CACHE 변수
cmake 실행 시 -D 옵션으로 외부에서 설정할 수 있는 변수입니다.
set(MY_OPTION OFF CACHE BOOL "옵션 설명")
set(INSTALL_DIR "/usr/local" CACHE PATH "설치 경로")
cmake -DMY_OPTION=ON -DINSTALL_DIR=/opt ..
option()
CACHE BOOL 변수의 축약 문법입니다. 기능 플래그에 자주 씁니다.
option(BUILD_TESTS "테스트 빌드 여부" ON)
option(ENABLE_LOGGING "로깅 활성화" OFF)
if(BUILD_TESTS)
add_subdirectory(tests)
endif()
타겟 정의
CMake에서 빌드의 단위는 타겟(target)입니다. 실행 파일, 라이브러리, 커스텀 명령 등이 타겟이 됩니다.
실행 파일
add_executable(타겟명 소스파일...)
add_executable(myapp main.cpp utils.cpp)
add_executable(myapp main.cpp) # 소스가 하나면 하나만
라이브러리
add_library(타겟명 타입 소스파일...)
add_library(mylib STATIC utils.cpp parser.cpp) # 정적 라이브러리 (.a)
add_library(mylib SHARED utils.cpp parser.cpp) # 동적 라이브러리 (.so / .dll)
add_library(mylib OBJECT utils.cpp parser.cpp) # 오브젝트 파일만
타입을 생략하면 BUILD_SHARED_LIBS 변수에 따라 결정됩니다.
소스 파일 묶기
파일이 많아지면 변수로 묶어서 관리합니다.
set(SOURCES
src/main.cpp
src/parser.cpp
src/utils.cpp
)
add_executable(myapp ${SOURCES})
file(GLOB ...)로 와일드카드로 모을 수도 있는데, 파일이 추가될 때 cmake를 다시 돌려야 인식한다는 단점이 있어서 명시적으로 나열하는 방식이 더 권장됩니다.
타겟 속성 설정
include 경로
target_include_directories(타겟명 접근제어 경로...)
target_include_directories(myapp PRIVATE include/)
target_include_directories(mylib PUBLIC include/)
접근 제어는 세 가지입니다.
PRIVATE: 이 타겟 컴파일에만 적용PUBLIC: 이 타겟 + 이 타겟에 링크하는 타겟에도 적용INTERFACE: 이 타겟에는 적용 안 하고, 링크하는 타겟에만 적용
라이브러리의 헤더 경로는 PUBLIC으로 두면, 그 라이브러리를 쓰는 쪽에서 따로 경로를 지정하지 않아도 됩니다.
컴파일 옵션
target_compile_options(myapp PRIVATE
-Wall
-Wextra
-O2
)
컴파일 정의 (매크로)
target_compile_definitions(myapp PRIVATE
APP_VERSION="1.0.0"
DEBUG_MODE
)
코드 안에서 #ifdef DEBUG_MODE처럼 쓸 수 있습니다.
링크
target_link_libraries(타겟명 접근제어 라이브러리...)
target_link_libraries(myapp PRIVATE mylib)
target_link_libraries(myapp PRIVATE pthread dl)
빌드 타입
cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
cmake -DCMAKE_BUILD_TYPE=MinSizeRel ..
Debug: 최적화 없음, 디버그 심볼 포함 (-g)Release: 최적화 적용 (-O3), 디버그 심볼 없음RelWithDebInfo: 최적화 + 디버그 심볼MinSizeRel: 크기 최소화 최적화
빌드 타입을 지정 안 하면 최적화도 디버그 심볼도 없는 상태입니다. 개발 중엔 Debug, 배포 시엔 Release를 씁니다.
CMakeLists.txt 안에서 기본값을 지정하려면 이렇게 씁니다.
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "빌드 타입" FORCE)
endif()
cmake 명령어 정리
# Configure
cmake -S 소스디렉토리 -B 빌드디렉토리
cmake -S . -B build
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
# Build
cmake --build 빌드디렉토리
cmake --build build
cmake --build build --config Release # 멀티 config 생성기용
cmake --build build --parallel 4 # 병렬 빌드 (코어 수 지정)
cmake --build build --target myapp # 특정 타겟만 빌드
cmake --build build --clean-first # 클린 후 빌드
# Install
cmake --install build
cmake --install build --prefix /usr/local
# 캐시 변수 확인
cmake -S . -B build -L # 캐시 변수 목록
cmake -S . -B build -LA # 상세 목록
cmake -LH build # 도움말 포함
# 클린
cmake --build build --target clean
Ninja 사용
기본 생성기 대신 Ninja를 쓰면 빌드가 빠릅니다.
cmake -S . -B build -G Ninja
cmake --build build
# 설치
sudo apt install ninja-build # Linux
brew install ninja # macOS
조건문과 메시지
if(조건)
...
elseif(조건)
...
else()
...
endif()
# 조건 예시
if(WIN32) # Windows
if(UNIX) # Unix 계열
if(APPLE) # macOS
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
if(MY_OPTION) # 변수가 TRUE, ON, YES, 1 등이면 참
if(NOT MY_OPTION)
if(EXISTS "${파일경로}")
# 메시지 출력
message("일반 메시지")
message(STATUS "-- 상태 메시지")
message(WARNING "경고")
message(FATAL_ERROR "에러 — cmake 중단")
정리 표
| 명령어 | 용도 |
|---|---|
cmake_minimum_required(VERSION x.y) |
최소 버전 지정 |
project(이름 VERSION x LANGUAGES CXX) |
프로젝트 정의 |
set(변수 값) |
변수 설정 |
option(변수 설명 기본값) |
옵션 플래그 |
add_executable(타겟 소스...) |
실행 파일 타겟 |
add_library(타겟 타입 소스...) |
라이브러리 타겟 |
target_include_directories(타겟 접근제어 경로) |
include 경로 |
target_compile_options(타겟 접근제어 옵션) |
컴파일 옵션 |
target_compile_definitions(타겟 접근제어 매크로) |
매크로 정의 |
target_link_libraries(타겟 접근제어 라이브러리) |
링크 |
message(STATUS "...") |
메시지 출력 |
cmake 빌드 명령어
| 명령어 | 동작 |
|---|---|
cmake -S . -B build |
configure |
cmake -S . -B build -G Ninja |
Ninja로 configure |
cmake --build build |
전체 빌드 |
cmake --build build --parallel |
병렬 빌드 |
cmake --build build --target 타겟 |
특정 타겟만 |
cmake --install build |
설치 |
2편에서는 서브디렉토리 구조, find_package로 외부 라이브러리 찾기, CPM / FetchContent로 의존성 관리, 그리고 실용 패턴들을 정리합니다.
'블로그, 컴퓨터 > Cheatsheets' 카테고리의 다른 글
| GitHub Actions 정리 (1편) — 개념, 워크플로우 구조, 트리거 (0) | 2026.05.31 |
|---|---|
| CMake 정리 (2편) — 서브디렉토리, 외부 라이브러리, 실용 패턴 (0) | 2026.05.30 |
| tmux 정리 (2편) — 설정, 플러그인, 실용 커스터마이징 (0) | 2026.05.29 |
| tmux 정리 (1편) — 세션, 윈도우, 패널 (0) | 2026.05.29 |
| Shell Script 정리 (2편) — 에러 처리, 문자열, 실용 패턴 (0) | 2026.05.28 |