# 소스 파일 추가

CMake는 크로스 플랫폼 빌드 시스템을 지원하는 도구로, CMakeLists.txt 파일은 프로젝트의 빌드 설정을 정의하는 데 사용된다. 이 파일 내에서 소스 파일을 추가하는 방법은 CMake의 중요한 부분 중 하나이다. 소스 파일을 추가하는 방식은 프로젝트의 구조와 요구 사항에 따라 달라질 수 있다. 아래에서 CMakeLists.txt에서 소스 파일을 추가하는 방법을 계층적으로 자세히 설명하겠다.

#### 프로젝트 구조 이해

CMakeLists.txt에서 소스 파일을 추가하기 전에 프로젝트의 디렉토리 구조를 이해하는 것이 중요하다. 프로젝트는 다음과 같은 구조를 가질 수 있다:

```
/ProjectRoot
├── CMakeLists.txt
├── src
│   ├── main.cpp
│   ├── utils.cpp
│   └── utils.h
└── include
    └── utils.h
```

이 구조에서 `src` 디렉토리에 소스 파일이 있고, `include` 디렉토리에 헤더 파일이 있다.

#### CMakeLists.txt 파일에서의 기본적인 소스 파일 추가

CMakeLists.txt에서 소스 파일을 추가하는 가장 기본적인 방법은 `add_executable` 또는 `add_library` 명령어를 사용하는 것이다. 예를 들어, 다음과 같은 CMakeLists.txt 파일이 있을 수 있다:

```cmake
cmake_minimum_required(VERSION 3.10)
project(MyProject)

add_executable(MyExecutable src/main.cpp src/utils.cpp)
```

이 예에서는 `add_executable` 명령어를 통해 `main.cpp`와 `utils.cpp` 파일이 `MyExecutable`이라는 실행 파일에 포함되도록 지정하고 있다.

#### 변수 사용을 통한 소스 파일 관리

소스 파일이 많아지면, 이를 직접 나열하는 것이 비효율적일 수 있다. 이럴 때 변수에 소스 파일을 저장하여 관리할 수 있다:

```cmake
cmake_minimum_required(VERSION 3.10)
project(MyProject)

set(SOURCES
    src/main.cpp
    src/utils.cpp
)

add_executable(MyExecutable ${SOURCES})
```

`set` 명령어를 사용하여 소스 파일 목록을 `SOURCES` 변수에 저장하고, `add_executable` 명령어에서 이를 참조한다. 이 방법은 파일을 추가하거나 제거할 때 수정할 부분이 줄어들어 편리한다.

#### 서브디렉토리와 파일 추가

프로젝트가 커지면 여러 서브디렉토리로 나뉠 수 있다. 이 경우 `add_subdirectory` 명령어를 사용하여 각 서브디렉토리의 CMakeLists.txt 파일에서 소스 파일을 관리할 수 있다:

```cmake
cmake_minimum_required(VERSION 3.10)
project(MyProject)

add_subdirectory(src)
```

`src` 디렉토리 내에 별도의 CMakeLists.txt 파일이 존재하고, 이 파일에서 소스 파일을 추가하도록 할 수 있다:

```cmake

set(SOURCES
    main.cpp
    utils.cpp
)

add_executable(MyExecutable ${SOURCES})
```

이렇게 하면 프로젝트의 구조를 더 체계적으로 관리할 수 있다.

#### globbing을 통한 파일 자동 추가

CMake는 globbing을 사용하여 특정 패턴에 맞는 모든 파일을 자동으로 추가할 수 있다. 하지만 이는 파일 추가/삭제 시 CMake를 다시 실행해야 하는 문제점이 있으므로 신중하게 사용해야 한다:

```cmake
file(GLOB SOURCES "src/*.cpp")

add_executable(MyExecutable ${SOURCES})
```

위의 예에서는 `src` 디렉토리 내의 모든 `.cpp` 파일을 `SOURCES` 변수에 포함시킨다.

#### 인터페이스 라이브러리 사용

CMake에서 인터페이스 라이브러리는 링크 시에만 포함될 수 있는 타겟을 정의할 때 사용된다. 인터페이스 라이브러리를 정의하고, 이를 다른 타겟에서 사용할 수 있다:

```cmake
add_library(MyLibrary INTERFACE)
target_sources(MyLibrary INTERFACE src/utils.cpp)
target_include_directories(MyLibrary INTERFACE include/)

add_executable(MyExecutable src/main.cpp)
target_link_libraries(MyExecutable MyLibrary)
```

이 예제에서는 `MyLibrary`라는 인터페이스 라이브러리를 정의하고, 이를 `MyExecutable`에서 링크하도록 했다.

#### 소스 파일의 조건부 추가

프로젝트가 특정 조건에 따라 소스 파일을 다르게 포함해야 하는 경우가 있다. 이럴 때 `if` 명령어를 사용하여 조건부로 소스 파일을 추가할 수 있다:

```cmake
cmake_minimum_required(VERSION 3.10)
project(MyProject)

set(SOURCES src/main.cpp)

if(WIN32)
    list(APPEND SOURCES src/windows_specific.cpp)
elseif(UNIX)
    list(APPEND SOURCES src/unix_specific.cpp)
endif()

add_executable(MyExecutable ${SOURCES})
```

이 코드에서는 빌드 환경에 따라 추가되는 소스 파일이 달라진다.

***

관련 자료:

* [CMake Documentation](https://cmake.org/cmake/help/latest/)
* [CMake Tutorial by Kitware](https://cmake.org/cmake/help/latest/guide/tutorial/index.html)
* [Modern CMake by Henry Schreiner](https://cliutils.gitlab.io/modern-cmake/)
