# 기본 명령어와 구조

CMakeLists.txt 파일은 CMake 빌드 시스템의 핵심 구성 요소로, 프로젝트의 빌드 과정을 제어하는 스크립트 파일이다. 이 파일은 프로젝트의 소스 파일, 헤더 파일, 라이브러리, 실행 파일, 의존성 등을 정의하고 관리한다. CMakeLists.txt 파일은 프로젝트의 최상위 디렉터리뿐만 아니라 서브 디렉터리에서도 사용할 수 있으며, 계층 구조를 통해 빌드 설정을 세분화할 수 있다.

#### 최소 요구 명령어

CMakeLists.txt 파일은 기본적으로 프로젝트를 정의하는 명령어들로 시작한다. 다음은 가장 기본적인 명령어들이다:

**cmake\_minimum\_required**

```cmake
cmake_minimum_required(VERSION <version>)
```

이 명령어는 CMakeLists.txt 파일을 처리하기 위해 필요한 최소 CMake 버전을 지정한다. `<version>`은 버전 번호를 의미하며, 예를 들어 `3.10`과 같은 형식을 갖는다. 이 명령어는 프로젝트 파일을 특정 버전의 CMake에서 작동하도록 강제하기 위해 필수적이다.

**project**

```cmake
project(<name> [LANGUAGES <languages>])
```

`project` 명령어는 프로젝트의 이름과 사용할 언어를 지정한다. `<name>`은 프로젝트 이름이며, `<languages>`는 C, C++, Fortran 등의 프로그래밍 언어를 지정한다. 언어를 지정하지 않으면 기본적으로 C와 C++이 설정된다.

#### 기본적인 빌드 타겟 정의

CMakeLists.txt는 빌드 타겟을 정의하는 데 사용된다. 빌드 타겟은 보통 실행 파일이나 라이브러리를 의미하며, 이를 위해 CMake는 몇 가지 중요한 명령어를 제공한다.

**add\_executable**

```cmake
add_executable(<name> [source1] [source2] ...)
```

`add_executable` 명령어는 실행 파일을 정의한다. `<name>`은 생성될 실행 파일의 이름이며, 그 뒤에 나오는 인자들은 실행 파일을 빌드하기 위해 필요한 소스 파일들이다. 예를 들어, `main.cpp`와 `utils.cpp`를 사용하여 `myApp`이라는 실행 파일을 생성하려면 다음과 같이 작성한다:

```cmake
add_executable(myApp main.cpp utils.cpp)
```

**add\_library**

```cmake
add_library(<name> [STATIC | SHARED | MODULE] [source1] [source2] ...)
```

`add_library` 명령어는 라이브러리를 정의한다. `<name>`은 라이브러리의 이름이고, `STATIC`, `SHARED`, `MODULE`은 라이브러리의 유형을 지정한다. `STATIC`은 정적 라이브러리, `SHARED`는 동적 라이브러리(또는 DLL), `MODULE`은 플러그인 라이브러리를 의미한다. 소스 파일들을 나열하여 라이브러리를 구성한다.

#### 빌드 디렉터리와 하위 디렉터리 관리

프로젝트가 복잡해지면 여러 개의 서브 디렉터리를 포함할 수 있다. CMake는 이러한 구조를 관리하기 위해 몇 가지 명령어를 제공한다.

**add\_subdirectory**

```cmake
add_subdirectory(<dir> [binary_dir] [EXCLUDE_FROM_ALL])
```

`add_subdirectory` 명령어는 특정 디렉터리의 CMakeLists.txt 파일을 현재 프로젝트에 포함시킨다. `<dir>`은 서브 디렉터리의 경로이고, `binary_dir`은 해당 서브 디렉터리에 대해 생성될 빌드 디렉터리를 지정한다. `EXCLUDE_FROM_ALL`을 사용하면 모든 빌드 타겟에서 이 서브 디렉터리를 제외할 수 있다.

**include\_directories**

```cmake
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
```

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

#### 의존성 관리

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

**find\_package**

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

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

**target\_link\_libraries**

```cmake
target_link_libraries(<target> [items...])
```

`target_link_libraries` 명령어는 특정 타겟에 대해 링크할 라이브러리들을 지정한다. `<target>`은 실행 파일이나 라이브러리 타겟의 이름이며, 뒤에 나오는 인자들은 링크할 라이브러리들이다. 이 명령어는 타겟이 올바르게 동작하도록 외부 라이브러리와 연결해주는 중요한 역할을 한다.

#### 조건부 설정

프로젝트의 요구 사항에 따라 특정 조건에 따라 빌드 설정을 다르게 해야 할 때가 있다. 이를 위해 CMake는 다양한 조건부 명령어를 제공한다.

**if/else/endif**

```cmake
if(<condition>)
  # 조건이 참일 때 실행할 내용
else()
  # 조건이 거짓일 때 실행할 내용
endif()
```

`if` 명령어는 조건에 따라 특정 명령어 블록을 실행하도록 한다. `<condition>`은 조건식이며, 참일 경우 `if` 블록 내의 명령어들이 실행되고, 거짓일 경우 `else` 블록의 명령어들이 실행된다. `endif`로 조건문을 종료한다.

**foreach**

```cmake
foreach(<var> <items>)
  # 반복할 내용
endforeach()
```

`foreach` 명령어는 주어진 리스트에서 각각의 항목에 대해 반복 작업을 수행할 때 사용된다. `<var>`는 반복 시 사용할 변수이고, `<items>`는 반복할 항목들의 리스트이다. `endforeach`로 반복 블록을 종료한다.

**set**

```cmake
set(<variable> <value>)
```

`set` 명령어는 CMake 변수에 값을 할당한다. `<variable>`은 변수 이름이고, `<value>`는 할당할 값이다. 이 변수는 이후 CMakeLists.txt 파일에서 참조할 수 있다.

#### 매크로 및 함수 정의

CMake에서는 반복되는 작업을 간단하게 처리하기 위해 매크로와 함수를 정의할 수 있다.

**macro**

```cmake
macro(<name> [arg1 [arg2 ...]])
  # 매크로 내용
endmacro()
```

`macro` 명령어는 반복적으로 사용할 명령어 블록을 정의한다. `<name>`은 매크로 이름이고, 뒤따르는 인자들은 매크로에서 사용할 변수들이다. `endmacro`로 매크로 정의를 종료한다.

**function**

```cmake
function(<name> [arg1 [arg2 ...]])
  # 함수 내용
endfunction()
```

`function` 명령어는 매크로와 유사하지만, 로컬 스코프를 갖는다. 이는 함수 내에서 선언된 변수들이 함수 외부에 영향을 미치지 않는다는 점에서 매크로와 차이가 있다.

#### 빌드 구성 옵션

CMakeLists.txt는 다양한 빌드 옵션을 설정할 수 있다. 이러한 옵션들은 빌드 과정을 유연하게 만들고, 다양한 환경에 맞춰 조정할 수 있도록 돕는다.

**option**

```cmake
option(<variable> "description" [value])
```

`option` 명령어는 사용자에게 선택할 수 있는 빌드 옵션을 제공한다. `<variable>`은 옵션 이름이며, "description"은 옵션에 대한 설명이다. `[value]`는 옵션의 기본값이다.

**configure\_file**

```cmake
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
