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.cpputils.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 명령어는 빌드 과정에서 사용할 헤더 파일의 경로를 지정한다. 이 경로들은 프로젝트 내 모든 소스 파일에 적용되며, AFTERBEFORE 키워드를 사용하여 경로의 우선순위를 지정할 수 있다. SYSTEM을 사용하면 시스템 경로로 간주되어 경고 메시지가 억제될 수 있다.

의존성 관리

CMake는 프로젝트가 외부 라이브러리나 다른 프로젝트에 의존할 때 이를 관리하기 위한 기능을 제공한다.

find_package

find_package(<package> [version] [REQUIRED] [COMPONENTS components...])

find_package 명령어는 외부 라이브러리나 패키지를 찾고 이를 프로젝트에 포함시킨다. <package>는 패키지의 이름이고, version은 원하는 최소 버전, REQUIRED는 필수 의존성임을 의미한다. COMPONENTS는 패키지의 특정 구성 요소들을 지정할 수 있다.

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