모던 CMake를 활용하여 효율적인 C++ 프로젝트 빌드 시스템을 구축하는 방법을 계속해서 알아보겠습니다. 이번 글에서는 타겟 기반 구성의 심화 내용과 라이브러리의 의존성 관리 방법에 대해 다루겠습니다.
타겟 기반 구성의 중요성
모던 CMake에서는 타겟(target)을 중심으로 빌드 설정을 관리합니다. 이는 빌드 대상(executable, library 등)에 직접 속성을 부여함으로써, 설정의 명확성과 재사용성을 높입니다.
타겟 프로퍼티 설정
타겟에 속성을 부여할 때는 다음과 같은 명령어를 사용합니다:
- target_include_directories()
- target_compile_definitions()
- target_compile_options()
- target_link_libraries()
각 명령어는 타겟에 특정 속성을 추가하며, 범위 지정 키워드를 통해 속성의 전파 범위를 제어합니다.
범위 지정 키워드
- PRIVATE: 타겟 내에서만 속성이 적용됩니다.
- PUBLIC: 타겟과 타겟을 의존하는 대상 모두에 속성이 적용됩니다.
- INTERFACE: 타겟을 의존하는 대상에만 속성이 적용됩니다.
예제: 라이브러리와 실행 파일 구성
디렉토리 구조
my_project/
├── CMakeLists.txt
├── src/
│ ├── main.cpp
│ └── lib/
│ ├── CMakeLists.txt
│ ├── mylib.cpp
│ └── mylib.h
src/lib/CMakeLists.txt
add_library(MyLib STATIC mylib.cpp)
target_include_directories(MyLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(MyProject)
add_subdirectory(src/lib)
add_executable(MyApp src/main.cpp)
target_link_libraries(MyApp PRIVATE MyLib)
설명
- MyLib 라이브러리는 PUBLIC 범위로 인클루드 디렉토리를 설정하였기 때문에, MyLib를 링크하는 MyApp에서도 해당 인클루드 디렉토리를 사용할 수 있습니다.
- MyApp은 PRIVATE 범위로 MyLib를 링크하였으므로, MyApp을 의존하는 다른 타겟에는 MyLib의 링크 정보가 전파되지 않습니다.
의존성 관리
모던 CMake에서는 target_link_libraries()를 활용하여 타겟 간 의존성을 명확하게 정의합니다. 이를 통해 빌드 시스템은 필요한 설정을 자동으로 전파합니다.
의존성 전파 예제
추가 라이브러리 UtilsLib 생성
my_project/
├── src/
│ ├── lib/
│ │ ├── mylib.cpp
│ │ ├── mylib.h
│ │ └── CMakeLists.txt
│ └── utils/
│ ├── util.cpp
│ ├── util.h
│ └── CMakeLists.txt
src/utils/CMakeLists.txt
add_library(UtilsLib STATIC util.cpp)
target_include_directories(UtilsLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
src/lib/CMakeLists.txt 수정
add_library(MyLib STATIC mylib.cpp)
target_include_directories(MyLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(MyLib PUBLIC UtilsLib)
최상위 CMakeLists.txt 수정
cmake_minimum_required(VERSION 3.15)
project(MyProject)
add_subdirectory(src/utils)
add_subdirectory(src/lib)
add_executable(MyApp src/main.cpp)
target_link_libraries(MyApp PRIVATE MyLib)
설명
- MyLib는 PUBLIC 범위로 UtilsLib를 링크하였기 때문에, MyLib를 링크하는 MyApp은 자동으로 UtilsLib에도 접근할 수 있습니다.
- 의존성 전파를 통해 복잡한 라이브러리 의존성을 간단하게 관리할 수 있습니다.
인터페이스 라이브러리
인터페이스 라이브러리는 소스 파일 없이 빌드 설정만을 전파하는 용도로 사용됩니다.
인터페이스 라이브러리 생성
add_library(ConfigLib INTERFACE)
target_compile_definitions(ConfigLib INTERFACE ENABLE_FEATURE_X)
- ConfigLib를 링크하는 타겟들은 ENABLE_FEATURE_X 매크로를 사용할 수 있습니다.
생성기 표현식
생성기 표현식은 조건부 설정을 가능하게 하여, 빌드 구성에 유연성을 제공합니다.
예제: 디버그 모드에서만 특정 정의 추가
target_compile_definitions(MyApp PRIVATE
$<$<CONFIG:Debug>:ENABLE_DEBUG_MODE>
)
- 빌드 타입이 Debug일 때만 ENABLE_DEBUG_MODE 매크로가 정의됩니다.
결론
이번 글에서는 모던 CMake의 타겟 기반 구성과 의존성 관리에 대해 심도 있게 살펴보았습니다. 다음 글에서는 외부 라이브러리의 포함, 패키지 관리, 그리고 CMake를 활용한 테스트 설정 등에 대해 알아보겠습니다. 함께 성장해 나가길 바랍니다. 감사합니다!
반응형
'개발 이야기 > CMake' 카테고리의 다른 글
[모던 CMake] 테스트 설정과 CI/CD 파이프라인 연동 (31) | 2024.12.02 |
---|---|
[모던 CMake] 외부 라이브러리와 패키지 관리 (0) | 2024.12.01 |
[모던 CMake] C++ 표준 버전 설정 방법 비교 (16) | 2024.11.30 |
[모던 CMake] 기초와 소개 (0) | 2024.11.28 |
[CMake] Google Test (구글테스트) 종속성 추가하기 (0) | 2024.03.31 |