CMakeLists.txt 파일은 CMake 빌드 시스템의 핵심 구성 요소로, 프로젝트의 빌드 과정을 제어하는 스크립트 파일이다. 이 파일은 프로젝트의 소스 파일, 헤더 파일, 라이브러리, 실행 파일, 의존성 등을 정의하고 관리한다. CMakeLists.txt 파일은 프로젝트의 최상위 디렉터리뿐만 아니라 서브 디렉터리에서도 사용할 수 있으며, 계층 구조를 통해 빌드 설정을 세분화할 수 있다.
최소 요구 명령어
CMakeLists.txt 파일은 기본적으로 프로젝트를 정의하는 명령어들로 시작한다. 다음은 가장 기본적인 명령어들이다:
cmake_minimum_required
cmake_minimum_required(VERSION <version>)
이 명령어는 CMakeLists.txt 파일을 처리하기 위해 필요한 최소 CMake 버전을 지정한다. <version>
은 버전 번호를 의미하며, 예를 들어 3.10
과 같은 형식을 갖는다. 이 명령어는 프로젝트 파일을 특정 버전의 CMake에서 작동하도록 강제하기 위해 필수적이다.
project
project(<name> [LANGUAGES <languages>])
project
명령어는 프로젝트의 이름과 사용할 언어를 지정한다. <name>
은 프로젝트 이름이며, <languages>
는 C, C++, Fortran 등의 프로그래밍 언어를 지정한다. 언어를 지정하지 않으면 기본적으로 C와 C++이 설정된다.
기본적인 빌드 타겟 정의
CMakeLists.txt는 빌드 타겟을 정의하는 데 사용된다. 빌드 타겟은 보통 실행 파일이나 라이브러리를 의미하며, 이를 위해 CMake는 몇 가지 중요한 명령어를 제공한다.
add_executable
add_executable(<name> [source1] [source2] ...)
add_executable
명령어는 실행 파일을 정의한다. <name>
은 생성될 실행 파일의 이름이며, 그 뒤에 나오는 인자들은 실행 파일을 빌드하기 위해 필요한 소스 파일들이다. 예를 들어, main.cpp
와 utils.cpp
를 사용하여 myApp
이라는 실행 파일을 생성하려면 다음과 같이 작성한다:
add_executable(myApp main.cpp utils.cpp)
add_library
add_library(<name> [STATIC | SHARED | MODULE] [source1] [source2] ...)
add_library
명령어는 라이브러리를 정의한다. <name>
은 라이브러리의 이름이고, STATIC
, SHARED
, MODULE
은 라이브러리의 유형을 지정한다. STATIC
은 정적 라이브러리, SHARED
는 동적 라이브러리(또는 DLL), MODULE
은 플러그인 라이브러리를 의미한다. 소스 파일들을 나열하여 라이브러리를 구성한다.
빌드 디렉터리와 하위 디렉터리 관리
프로젝트가 복잡해지면 여러 개의 서브 디렉터리를 포함할 수 있다. CMake는 이러한 구조를 관리하기 위해 몇 가지 명령어를 제공한다.
add_subdirectory
add_subdirectory(<dir> [binary_dir] [EXCLUDE_FROM_ALL])
add_subdirectory
명령어는 특정 디렉터리의 CMakeLists.txt 파일을 현재 프로젝트에 포함시킨다. <dir>
은 서브 디렉터리의 경로이고, binary_dir
은 해당 서브 디렉터리에 대해 생성될 빌드 디렉터리를 지정한다. EXCLUDE_FROM_ALL
을 사용하면 모든 빌드 타겟에서 이 서브 디렉터리를 제외할 수 있다.
include_directories
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
include_directories
명령어는 빌드 과정에서 사용할 헤더 파일의 경로를 지정한다. 이 경로들은 프로젝트 내 모든 소스 파일에 적용되며, AFTER
나 BEFORE
키워드를 사용하여 경로의 우선순위를 지정할 수 있다. SYSTEM
을 사용하면 시스템 경로로 간주되어 경고 메시지가 억제될 수 있다.
의존성 관리
CMake는 프로젝트가 외부 라이브러리나 다른 프로젝트에 의존할 때 이를 관리하기 위한 기능을 제공한다.
find_package
find_package(<package> [version] [REQUIRED] [COMPONENTS components...])
find_package
명령어는 외부 라이브러리나 패키지를 찾고 이를 프로젝트에 포함시킨다. <package>
는 패키지의 이름이고, version
은 원하는 최소 버전, REQUIRED
는 필수 의존성임을 의미한다. COMPONENTS
는 패키지의 특정 구성 요소들을 지정할 수 있다.
target_link_libraries
target_link_libraries(<target> [items...])
target_link_libraries
명령어는 특정 타겟에 대해 링크할 라이브러리들을 지정한다. <target>
은 실행 파일이나 라이브러리 타겟의 이름이며, 뒤에 나오는 인자들은 링크할 라이브러리들이다. 이 명령어는 타겟이 올바르게 동작하도록 외부 라이브러리와 연결해주는 중요한 역할을 한다.
조건부 설정
프로젝트의 요구 사항에 따라 특정 조건에 따라 빌드 설정을 다르게 해야 할 때가 있다. 이를 위해 CMake는 다양한 조건부 명령어를 제공한다.
if/else/endif
if(<condition>)
# 조건이 참일 때 실행할 내용
else()
# 조건이 거짓일 때 실행할 내용
endif()
if
명령어는 조건에 따라 특정 명령어 블록을 실행하도록 한다. <condition>
은 조건식이며, 참일 경우 if
블록 내의 명령어들이 실행되고, 거짓일 경우 else
블록의 명령어들이 실행된다. endif
로 조건문을 종료한다.
foreach
foreach(<var> <items>)
# 반복할 내용
endforeach()
foreach
명령어는 주어진 리스트에서 각각의 항목에 대해 반복 작업을 수행할 때 사용된다. <var>
는 반복 시 사용할 변수이고, <items>
는 반복할 항목들의 리스트이다. endforeach
로 반복 블록을 종료한다.
set
set(<variable> <value>)
set
명령어는 CMake 변수에 값을 할당한다. <variable>
은 변수 이름이고, <value>
는 할당할 값이다. 이 변수는 이후 CMakeLists.txt 파일에서 참조할 수 있다.
매크로 및 함수 정의
CMake에서는 반복되는 작업을 간단하게 처리하기 위해 매크로와 함수를 정의할 수 있다.
macro
macro(<name> [arg1 [arg2 ...]])
# 매크로 내용
endmacro()
macro
명령어는 반복적으로 사용할 명령어 블록을 정의한다. <name>
은 매크로 이름이고, 뒤따르는 인자들은 매크로에서 사용할 변수들이다. endmacro
로 매크로 정의를 종료한다.
function
function(<name> [arg1 [arg2 ...]])
# 함수 내용
endfunction()
function
명령어는 매크로와 유사하지만, 로컬 스코프를 갖는다. 이는 함수 내에서 선언된 변수들이 함수 외부에 영향을 미치지 않는다는 점에서 매크로와 차이가 있다.
빌드 구성 옵션
CMakeLists.txt는 다양한 빌드 옵션을 설정할 수 있다. 이러한 옵션들은 빌드 과정을 유연하게 만들고, 다양한 환경에 맞춰 조정할 수 있도록 돕는다.
option
option(<variable> "description" [value])
option
명령어는 사용자에게 선택할 수 있는 빌드 옵션을 제공한다. <variable>
은 옵션 이름이며, "description"은 옵션에 대한 설명이다. [value]
는 옵션의 기본값이다.
configure_file
configure_file(<input> <output> [COPYONLY] [ESCAPE_QUOTES])
configure_file
명령어는 입력 파일을 출력 파일로 변환한다. 주로 소스 코드 파일에 대한 설정 값을 삽입하기 위해 사용된다. COPYONLY
를 지정하면 파일 내용이 변환되지 않고 그대로 복사되며, ESCAPE_QUOTES
를 사용하면 따옴표가 이스케이프 처리된다.
관련 자료: - CMake 공식 문서 (https://cmake.org/documentation) - Modern CMake by Henry Schreiner (https://cliutils.gitlab.io/modern-cmake/) - Professional CMake by Craig Scott