CMakeLists.txt 파일에서 조건부 컴파일은 특정 조건에 따라 소스 파일을 컴파일하거나 컴파일 옵션을 설정하는 방법을 제공한다. 조건부 컴파일은 코드의 유연성과 유지보수성을 높이는 데 필수적이다.
조건부 컴파일의 기본 개념
조건부 컴파일은 특정 조건이 충족될 때만 코드의 일부분이 컴파일되도록 하는 것이다. 이 개념은 다양한 플랫폼, 빌드 구성, 또는 사용자의 요구 사항에 따라 특정 코드가 컴파일되거나 제외되도록 조절하는 데 사용된다.
CMake에서는 if()
, elseif()
, else()
, endif()
명령어를 사용하여 조건부 컴파일을 구현할 수 있다. 이러한 조건문은 일반적으로 변수 값, 파일 존재 여부, 시스템 속성 등을 평가하여 특정 동작을 결정한다.
조건부 컴파일을 위한 CMake 변수
CMake 변수는 조건부 컴파일을 구현하는 데 중요한 역할을 한다. 일반적으로 다음과 같은 변수가 사용된다.
- CMake 전역 변수:
CMAKE_SYSTEM_NAME
,CMAKE_BUILD_TYPE
등은 빌드 환경에 따라 설정되는 전역 변수로, 플랫폼 또는 빌드 설정에 따라 다르게 설정될 수 있다. - 사용자 정의 변수:
option()
명령어를 사용하여 사용자가 정의할 수 있는 변수다. 예를 들어,option(USE_CUSTOM_LIB "Use custom library" OFF)
를 정의하여 특정 라이브러리 사용 여부를 결정할 수 있다. - 자동 설정 변수:
find_package()
와 같은 명령어는 특정 패키지의 존재 여부에 따라 변수를 자동으로 설정한다. 예를 들어,find_package(OpenSSL REQUIRED)
는 OpenSSL이 발견되면OpenSSL_FOUND
변수를TRUE
로 설정한다.
CMake 조건문
CMake의 조건문은 다양한 형태의 조건을 평가하여 코드의 일부를 선택적으로 실행할 수 있다. 주요 조건문 사용법은 다음과 같다.
-
기본 조건문 사용:
cmake if(USE_CUSTOM_LIB) add_definitions(-DUSE_CUSTOM_LIB) endif()
위의 예는USE_CUSTOM_LIB
변수가ON
으로 설정되었을 때만 특정 정의를 추가한다. -
AND, OR 연산자 사용:
cmake if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_BUILD_TYPE STREQUAL "Debug") message("Building on Linux in Debug mode") endif()
이 조건문은 빌드 시스템이 Linux이고, 빌드 타입이 Debug인 경우에만 메시지를 출력한다. -
elseif 및 else 사용:
cmake if(CMAKE_SYSTEM_NAME STREQUAL "Windows") message("Building on Windows") elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") message("Building on Linux") else() message("Building on an unknown platform") endif()
이 예시는 시스템에 따라 다른 메시지를 출력한다.
파일 및 디렉토리 존재 여부에 따른 조건부 컴파일
CMake는 파일이나 디렉토리의 존재 여부에 따라 조건부 컴파일을 수행할 수 있는 기능을 제공한다. 이는 프로젝트의 특정 파일 또는 디렉토리가 있는 경우에만 특정 코드나 라이브러리를 포함하고자 할 때 유용하다.
-
파일 존재 여부 체크:
cmake if(EXISTS "${PROJECT_SOURCE_DIR}/config.h") include_directories("${PROJECT_SOURCE_DIR}") endif()
위의 코드는config.h
파일이 존재할 경우에만 해당 디렉토리를 포함 디렉토리에 추가한다. -
디렉토리 존재 여부 체크:
cmake if(IS_DIRECTORY "${PROJECT_SOURCE_DIR}/libs") add_subdirectory("${PROJECT_SOURCE_DIR}/libs") endif()
이 예시는libs
디렉토리가 존재할 경우에만 서브디렉토리를 추가한다.
조건부 컴파일을 위한 함수 및 매크로
CMake에서 조건부 컴파일을 더 정교하게 제어하기 위해 함수와 매크로를 사용할 수 있다. 함수와 매크로는 코드의 중복을 줄이고, 복잡한 조건부 로직을 보다 깔끔하게 관리할 수 있게 해준다.
- 함수 사용 예: ```cmake function(enable_custom_feature) if(USE_CUSTOM_LIB) add_definitions(-DUSE_CUSTOM_LIB) message("Custom library enabled") endif() endfunction()
enable_custom_feature()
``
이 함수는
USE_CUSTOM_LIB` 변수가 설정되었을 때만 호출되며, 이로 인해 조건부 컴파일 논리를 재사용할 수 있다.
- 매크로 사용 예: ```cmake macro(setup_platform_specifics) if(CMAKE_SYSTEM_NAME STREQUAL "Windows") add_definitions(-DPLATFORM_WINDOWS) elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_definitions(-DPLATFORM_LINUX) endif() endmacro()
setup_platform_specifics() ``` 매크로는 여러 곳에서 반복되는 조건부 설정을 정의하는 데 유용하다.
조건부 컴파일을 이용한 목표 타겟 설정
CMake에서는 특정 조건에 따라 타겟을 설정하거나 타겟의 속성을 변경할 수 있다. 이는 다양한 빌드 환경에서 유연한 타겟 설정을 가능하게 한다.
- 타겟 속성 조건부 설정: ```cmake add_executable(myapp main.cpp)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(myapp PRIVATE DEBUG_MODE)
endif()
``
이 예제는 Debug 빌드 모드에서만
DEBUG_MODE`를 정의하여 컴파일하도록 한다.
- 타겟의 조건부 추가:
cmake if(USE_CUSTOM_LIB) add_library(custom_lib STATIC custom_lib.cpp) target_link_libraries(myapp PRIVATE custom_lib) endif()
조건에 따라 라이브러리를 추가하고, 이를 타겟과 링크할 수 있다.
관련 자료: - CMake 공식 문서: https://cmake.org/documentation/ - Mastering CMake by Ken Martin and Bill Hoffman