ExternalProject 모듈
ExternalProject_Add()를 사용해서 SPDLOG를 다운받고, 그 과정에서 오류 해결을 하는 과정을 기록한다. 또한 CMake 3.11 이전 버전이라면 ExternalProject 모듈밖에 선택지가 없지만, 그 이후라면 FetchContent 모듈을 사용하는 방법도 존재한다. ExternalProject는 빌드 타임에 외부 파일들을 불러오며, FetchContent는 CMake를 실행하는 시점에 외부 파일들을 불러온다.
ExternalProject_Add()
공식 문서에서 ExternalProject_Add()의 옵션에 대해 확인할 수 있다. ExternalProject_Add 커맨드는 외부 프로젝트의 download, update, patch, configure, build, install 그리고 test를 구동하는 커스텀 타겟을 생성한다.
ExternalProject_Add(<name> [<option>...])
SPDLOG 다운 받기
1.4.2 구버전을 다운 받으면, MSVC 2022와 호환이 안되서 컴파일 에러가 많이 터지는 것 같길래, 해당 버전 설치는 포기하였다.
dependency.cmake
include(ExternalProject)
ExternalProject_Add(
dep_spdlog
GIT_REPOSITORY https://github.com/gabime/spdlog.git
GIT_TAG v1.x
)
이렇게 설치하려 하면, 바로 문제가 생긴다.
example.vcxproj -> C:\Users\ParkJunsu\Desktop\cmake-practice\build\dep_spdlog-prefix\src\dep_spdlog-build\example\Debug\example.exe
1>
-- Install configuration: "Debug"
-- Installing: C:/Program Files/spdlog/include
CMake Error at cmake_install.cmake:41 (file):
file INSTALL cannot make directory "C:/Program Files/spdlog/include": No
such file or directory.
이는 `CMAKE_INSTALL_PREFIX`의 기본 값이 "C:/Program Files"이기 때문에, 위 경로에서 디렉토리를 생성하려 했지만 실패한 것이다. CMAKE_ARGS를 통해 설치 경로를 전달해주자.
개선된 dependency.cmake
include(ExternalProject)
set(DEP_INSTALL_DIR ${PROJECT_BINARY_DIR}/install)
set(DEP_INCLUDE_DIR ${DEP_INSTALL_DIR}/include)
set(DEP_LIB_DIR ${DEP_INSTALL_DIR}/lib)
ExternalProject_Add(
dep_spdlog
GIT_REPOSITORY https://github.com/gabime/spdlog.git
GIT_TAG v1.x
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${DEP_INSTALL_DIR}
)
위 처럼 설정하면 configure와 build까지 제대로 수행되는 것을 확인할 수 있다.
빌드 후 지정한 install 경로에 spdlog이 잘 설치되었다.
그리고 build 폴더에 dep_spdlog-prefix라는 것이 생성되었는데, ExternalProject_Add() 커맨드는 "타겟이름-prefix"로 폴더를 생성한 뒤, 원본 소스코드를 내려받은 뒤 빌드가 수행되는 곳이다. 빌드가 정상적으로 수행되었다면 install() 커맨드가 동작하여 지정한 install 경로에 필요한 헤더파일을 include 경로에, 필요한 lib 파일을 lib 경로에 복사하게 된다.
SPDLOG 사용
빌드가 성공적으로 완수되었다고 바로 외부 라이브러리를 사용할 수 있는 것은 아니다. 아래처럼 설치된 라이브러리의 헤더 파일과 라이브러리 파일을 링크해주면 제대로 사용할 수 있게 된다.
CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(cmake-practice)
set(CMAKE_CXX_STANDARD 17)
add_executable(
${PROJECT_NAME} src/main.cpp
)
include(dependency.cmake)
target_include_directories(${PROJECT_NAME} PUBLIC ${DEP_INCLUDE_DIR})
target_link_directories(${PROJECT_NAME} PUBLIC ${DEP_LIB_DIR})
target_link_libraries(${PROJECT_NAME} PUBLIC ${DEP_LIBS})
dependency.cmake
include(ExternalProject)
set(DEP_INSTALL_DIR ${PROJECT_BINARY_DIR}/install)
set(DEP_INCLUDE_DIR ${DEP_INSTALL_DIR}/include)
set(DEP_LIB_DIR ${DEP_INSTALL_DIR}/lib)
ExternalProject_Add(
dep_spdlog
GIT_REPOSITORY https://github.com/gabime/spdlog.git
GIT_TAG v1.x
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${DEP_INSTALL_DIR}
)
set(DEP_LIST ${DEP_LIST} dep_spdlog)
set(DEP_LIBS ${DEP_LIBS} spdlog$<$<CONFIG:Debug>:d>)
그리고 CMakeLists.txt 마지막에 다음을 추가해준다,
add_dependencies(${PROJECT_NAME} ${DEP_LIST})
이는, 내가 작성한 코드보다 라이브러리의 코드가 먼저 빌드 되도록 만들 수 있다. DEP_LIST에 들어가있는 타겟들을 모두 컴파일 한 다음 내 프로젝트의 코드가 컴파일된다. CMake는 기본적으로 모든 타겟을 병렬로 빌드하기 때문에, add_dependencies() 커맨드를 통해 먼저 빌드가 필요한 디펜던시를 관리 및 빌드할 수 있게 된다.
참고 자료
- https://cmake.org/cmake/help/latest/module/ExternalProject.html
- https://discourse.cmake.org/t/cmake-command-mode-help-cmake-e-env-edit-fixed-error-on-concatenation/5798
- https://velog.io/@seongcheoljeon/CMake-Install-Command
- https://www.youtube.com/playlist?list=PLvNHCGtd4kh_cYLKMP_E-jwF3YKpDP4hf
- https://cmake.org/cmake/help/latest/command/add_dependencies.html
- https://modoocode.com/332
'CMake' 카테고리의 다른 글
[CMake] .cmake 파일의 사용 (0) | 2025.04.23 |
---|---|
[CMake] target_link_directories(), target_link_libraries() (0) | 2025.04.22 |
[CMake] CMAKE_PREFIX_PATH (0) | 2025.04.17 |
[CMake] find_package() (0) | 2025.04.16 |
[CMake] Microsft store에서 제공하는 powerhsell의 HRESULT: 0x80070005 오류 (0) | 2025.04.15 |