# 플래그에 따른 컴파일 설정

#### CMake 개요

CMakeLists.txt 파일에는 프로젝트의 소스 코드, 헤더 파일, 라이브러리, 외부 종속성 및 컴파일러 설정에 대한 정보가 포함된다. CMake는 이러한 정보를 기반으로 플랫폼 독립적인 빌드 스크립트를 생성한다.

#### 컴파일러 플래그 설정

컴파일러 플래그는 코드 최적화, 디버깅 정보 포함 여부, 경고 레벨 등을 결정하는 데 사용된다. CMake에서는 다양한 명령어와 변수를 통해 컴파일러 플래그를 설정할 수 있다.

* **add\_compile\_options()**: 이 명령어는 소스 파일에 적용될 컴파일러 플래그를 지정한다. 예를 들어, `add_compile_options(-Wall -O2)`와 같이 사용하여 모든 소스 파일에 `-Wall`과 `-O2` 플래그를 추가할 수 있다.
* **target\_compile\_options()**: 특정 타겟에 대해서만 컴파일러 플래그를 지정하고자 할 때 사용한다. `target_compile_options(MyTarget PRIVATE -Wall -O2)`와 같이 사용하여 `MyTarget`이라는 타겟에만 플래그를 적용할 수 있다. `PRIVATE`, `PUBLIC`, `INTERFACE`는 플래그의 가시성을 결정한다.
* **CMAKE\_CXX\_FLAGS, CMAKE\_C\_FLAGS**: CMake 프로젝트 전반에 걸쳐 기본 컴파일러 플래그를 설정할 때 사용한다. 예를 들어, `set(CMAKE_CXX_FLAGS "-Wall -O2")`로 C++ 컴파일러에 대한 플래그를 설정할 수 있다. C와 C++ 플래그는 각각 `CMAKE_C_FLAGS`와 `CMAKE_CXX_FLAGS`로 구분된다.

#### 빌드 타입에 따른 설정

CMake에서는 빌드 타입에 따라 컴파일러 플래그를 다르게 설정할 수 있다. 이는 코드 최적화, 디버깅, 테스트 등의 목적에 따라 빌드 설정을 다르게 할 수 있게 한다.

* **CMAKE\_BUILD\_TYPE**: 이 변수는 빌드 타입을 지정한다. `Debug`, `Release`, `RelWithDebInfo`, `MinSizeRel` 등이 일반적인 빌드 타입이다. 예를 들어, `set(CMAKE_BUILD_TYPE Debug)`로 설정하면 디버그 빌드에 적합한 플래그가 적용된다.
* **CMAKE\_CXX\_FLAGS\_DEBUG, CMAKE\_C\_FLAGS\_DEBUG**: 디버그 빌드에 사용되는 플래그를 설정한다. 디버그 빌드 시 `-g` 플래그를 추가하고자 한다면, `set(CMAKE_CXX_FLAGS_DEBUG "-g")`로 설정할 수 있다.
* **CMAKE\_CXX\_FLAGS\_RELEASE, CMAKE\_C\_FLAGS\_RELEASE**: 릴리즈 빌드에 사용되는 플래그를 설정한다. 릴리즈 빌드에서는 주로 최적화 플래그 `-O2`나 `-O3`를 사용한다. 예를 들어, `set(CMAKE_CXX_FLAGS_RELEASE "-O3")`와 같이 설정한다.

#### 조건부 컴파일 설정

플래그에 따라 특정 설정을 활성화하거나 비활성화할 수 있다. 조건부 컴파일 설정은 다양한 환경에서의 빌드 요구사항을 충족시킬 수 있다.

* **if() 조건문 사용**: CMakeLists.txt 내에서 `if()` 조건문을 사용하여 특정 플래그나 환경 변수에 따라 설정을 변경할 수 있다. 예를 들어, 특정 컴파일러에서만 플래그를 적용하려면 다음과 같이 설정할 수 있다:

  ```cmake
  if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
  endif()
  ```
* **option() 명령어**: 특정 기능을 활성화하거나 비활성화할 수 있는 옵션을 제공한다. 예를 들어, 디버그 로그 출력을 활성화할 옵션을 만들고 싶다면:

  ```cmake
  option(ENABLE_DEBUG_LOG "Enable debug logging" OFF)

  if(ENABLE_DEBUG_LOG)
      add_compile_options(-DENABLE_DEBUG_LOG)
  endif()
  ```

#### 타겟 기반 플래그 설정

CMake는 특정 타겟에 대해서만 플래그를 설정할 수 있다. 이를 통해 다양한 타겟이 서로 다른 설정으로 빌드될 수 있다.

* **target\_compile\_options()**: 특정 타겟에 대한 플래그를 설정할 수 있다. 예를 들어, 라이브러리 타겟에는 `-fPIC` 플래그를 추가하고 싶다면:

  ```cmake
  target_compile_options(MyLibrary PRIVATE -fPIC)
  ```
* **target\_compile\_definitions()**: 특정 타겟에 대한 매크로 정의를 설정할 수 있다. 다음 예제는 `DEBUG` 매크로를 `MyTarget`에 대해 정의한다:

  ```cmake
  target_compile_definitions(MyTarget PRIVATE DEBUG)
  ```
* **target\_link\_options()**: 특정 타겟에 대해 링크 옵션을 설정할 수 있다. 예를 들어, `MyExecutable` 타겟에 대해 링커 플래그를 추가하고 싶다면:

  ```cmake
  target_link_options(MyExecutable PRIVATE -Wl,-rpath,/custom/lib/path)
  ```

#### 외부 라이브러리 및 종속성 관리

CMake는 외부 라이브러리와 종속성을 관리할 수 있는 강력한 기능을 제공한다. 이는 종속성에 따라 플래그를 자동으로 설정할 수 있게 한다.

* **find\_package()**: 외부 라이브러리를 찾기 위해 사용된다. 예를 들어, `find_package(Boost REQUIRED)`는 Boost 라이브러리를 찾고, 이를 사용할 수 있도록 플래그를 설정한다.
* **target\_link\_libraries()**: 특정 타겟에 외부 라이브러리를 링크한다. 예를 들어, `MyTarget` 타겟에 Boost 라이브러리를 링크하고 싶다면:

  ```cmake
  target_link_libraries(MyTarget PRIVATE Boost::Boost)
  ```
* **ExternalProject\_Add()**: 외부 프로젝트를 빌드하고 연결할 수 있다. 이 기능은 종속성을 관리하는 데 유용하다.

***

관련 자료:

* CMake 공식 문서: <https://cmake.org/documentation/>
* Professional CMake: A Practical Guide by Craig Scott
* Mastering CMake by Ken Martin, Bill Hoffman
