CMakeLists.txt 파일은 프로젝트의 빌드 시스템을 정의하는 핵심 요소이다. 이 파일을 잘 작성하면 유지보수성이 높아지고, 여러 플랫폼에서 일관된 빌드가 가능해진다. 다음은 CMakeLists.txt 파일을 작성할 때 따라야 할 모범 사례들이다.

프로젝트 초기 설정

프로젝트 이름과 버전 명시

프로젝트의 이름과 버전을 명시하는 것은 기본적인 시작점이다. 이를 통해 프로젝트의 정보를 명확히 전달할 수 있다.

cmake_minimum_required(VERSION 3.14)
project(MyProject VERSION 1.0 LANGUAGES CXX)

cmake_minimum_required는 CMake의 최소 버전을 지정하며, 호환성 문제를 방지하는 데 유용하다. project 명령어는 프로젝트 이름과 지원 언어(C, CXX, 등)를 설정한다.

표준 C++ 버전 설정

특정 C++ 표준을 사용해야 하는 경우, CMake를 통해 이를 명확히 설정할 수 있다.

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS OFF)

이 설정은 C++ 17 표준을 강제하며, 컴파일러 확장을 사용하지 않도록 한다.

파일 및 디렉토리 구조 관리

소스 및 헤더 파일 정리

프로젝트가 커질수록 소스 파일과 헤더 파일을 명확하게 구분하고 관리하는 것이 중요하다. 일반적으로, 소스 파일과 헤더 파일을 각각 srcinclude 디렉토리에 배치한다.

include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB_RECURSE SOURCES ${PROJECT_SOURCE_DIR}/src/*.cpp)

include_directories 명령어를 사용해 헤더 파일의 경로를 지정하고, file(GLOB_RECURSE ...)을 사용해 소스 파일을 자동으로 검색할 수 있다.

출력 디렉토리 지정

빌드 결과물을 별도의 디렉토리에 저장하도록 설정하면, 소스 디렉토리가 더 깔끔하게 유지된다.

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)

이 설정은 실행 파일과 라이브러리가 각각 binlib 디렉토리에 저장되도록 한다.

빌드 설정

빌드 유형 정의

디버그와 릴리즈 빌드의 차이를 명확히 하기 위해 빌드 유형을 명시적으로 정의하는 것이 좋다.

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

CMAKE_BUILD_TYPE을 통해 기본 빌드 유형을 설정하고, 각 빌드 유형에 맞는 컴파일러 플래그를 지정한다.

외부 라이브러리 사용

외부 라이브러리와의 종속성을 관리하는 방법도 중요하다. find_package 명령을 사용해 외부 라이브러리를 찾아 링크하는 방식이 권장된다.

find_package(Boost 1.65 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(MyExecutable ${Boost_LIBRARIES})

이 설정은 Boost 라이브러리를 찾고, 이를 프로젝트에 포함시킨다.

모듈화와 재사용성

타겟 사용

CMake에서 target을 사용하면 모듈화와 재사용성을 높일 수 있다. 타겟을 정의하고, 해당 타겟에 필요한 설정을 추가하는 것이 좋다.

add_executable(MyExecutable ${SOURCES})
target_include_directories(MyExecutable PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_compile_options(MyExecutable PRIVATE -Wall -Wextra)

이렇게 하면 특정 타겟에만 필요한 설정을 추가할 수 있어 관리가 용이해진다.

CMake 모듈 분리

CMakeLists.txt 파일이 복잡해질 경우, 이를 여러 파일로 나누어 관리하는 것이 바람직한다. include 명령을 사용해 다른 CMake 파일을 불러올 수 있다.

include(cmake/AdditionalConfig.cmake)

이 방식은 CMake 설정을 모듈화하고, 특정 기능이나 설정을 별도의 파일로 분리하여 관리할 수 있게 한다.

문서화

CMakeLists.txt 파일에 주석 추가

CMakeLists.txt 파일에 주석을 추가하여 설정의 의도와 목적을 설명하는 것이 중요하다. 이는 향후 유지보수 시 이해도를 높이고, 다른 개발자들과의 협업에 도움이 된다.

add_executable(MyExecutable ${SOURCES})

주석은 간결하고 명확하게 작성하는 것이 좋다.

예외 처리와 오류 검증

필수 요소 검증

필수 요소들이 설정되었는지 확인하고, 오류 메시지를 제공하여 빌드 실패 시 문제를 쉽게 파악할 수 있도록 한다.

if(NOT DEFINED REQUIRED_VARIABLE)
  message(FATAL_ERROR "REQUIRED_VARIABLE is not set")
endif()

message(FATAL_ERROR ...)를 통해 필수 설정이 누락된 경우 빌드를 중단하고 명확한 오류 메시지를 출력하도록 한다.


관련 자료: