CMake find_package로 외부 라이브러리 연결하기: Config vs Module 모드와 커스텀 Find 모듈
이 글의 핵심
find_package가 라이브러리를 찾는 방식, Config 모드와 Module 모드의 차이, Boost·OpenSSL 등 주요 라이브러리 연결 예제, 커스텀 Find 모듈 작성법을 다룹니다.
find_package가 대신해 주는 일
헤더·라이브러리 경로를 손으로 적을 때의 문제
Boost를 쓰는 프로젝트를 생각해 봅시다. Linux에서는 헤더가 /usr/include/boost, 라이브러리가 /usr/lib/libboost_filesystem.so에 있지만, macOS에서 Homebrew로 설치하면 /opt/homebrew/include 아래에, Windows에서는 C:\boost 같은 임의의 위치에 있습니다. 이 경로들을 CMakeLists.txt에 플랫폼별로 하드코딩하면 개발자마다, CI 이미지마다 수정이 필요해집니다.
find_package는 이 탐색을 CMake에 맡기는 명령입니다. 정해진 규칙에 따라 설치 위치를 찾아 헤더 경로, 라이브러리 경로, 버전 정보를 알려 줍니다. 예를 들어 find_package(Boost REQUIRED COMPONENTS filesystem)을 호출하면 Boost::filesystem 같은 타겟이 만들어지고, 이후에는 이 이름만 링크하면 됩니다.
의존성을 끌어오는 층에서는 vcpkg·Conan이 자주 함께 사용되며, 다른 언어로 치면 npm의 node_modules 해석·Go 모듈·go.sum·Python 패키지 매니저와 역할을 대응시켜 이해하면 편합니다. Rust는 Cargo가 빌드와 크레이트를 통합합니다.
flowchart LR
subgraph find["find_package(Boost)"]
search["시스템 경로 탐색"]
end
subgraph system[시스템]
linux["/usr/lib/libboost*.so"]
mac["/opt/homebrew/lib"]
win["C:/boost/lib"]
end
subgraph result[결과]
target["Boost filesystem 타겟 생성"]
vars["Boost_FOUND, Boost_VERSION 변수"]
end
search --> linux
search --> mac
search --> win
linux --> target
mac --> target
win --> target
search --> vars
REQUIRED·버전·COMPONENTS 지정하기
REQUIRED로 필수 패키지 찾기
find_package(Boost REQUIRED)
# REQUIRED이면 못 찾았을 때 여기서 구성이 중단되므로 별도의 FATAL_ERROR 분기는 필요 없습니다.
message(STATUS "Boost found: ${Boost_VERSION}")
없어도 되는 선택적 패키지
find_package(SomeLib)
if(SomeLib_FOUND)
target_link_libraries(myapp PRIVATE SomeLib::SomeLib)
else()
message(WARNING "SomeLib not found, using fallback")
endif()
최소 버전과 EXACT 지정
# 최소 버전
find_package(Boost 1.70 REQUIRED)
# 정확한 버전
find_package(Boost 1.75 EXACT REQUIRED)
# 버전 범위 (CMake 3.19+)
find_package(Boost 1.70...1.80 REQUIRED)
find_package의 결과는 두 가지 형태로 돌아옵니다. Boost_FOUND, Boost_INCLUDE_DIRS 같은 변수와, Boost::filesystem 같은 IMPORTED 타겟입니다. 이 글의 예제가 가능하면 타겟을 쓰는 이유는 타겟이 include 경로, 링크할 라이브러리 파일, 필요한 컴파일 정의, 그리고 그 라이브러리가 다시 의존하는 다른 라이브러리까지 한 묶음으로 전달하기 때문입니다. 변수 방식은 이 중 하나라도 빠뜨리면 컴파일은 되는데 링크에서 undefined reference가 나는 식으로 늦게 드러납니다. 또 ::가 들어간 이름은 CMake가 반드시 타겟으로 해석하므로, 오타가 나면 생성 단계에서 바로 “target was not found” 에러가 납니다. 변수 오타는 빈 문자열로 조용히 확장된다는 점과 대조적입니다.
EXACT나 버전 범위를 쓸 때는 버전 비교를 패키지가 제공하는 버전 파일(<Name>ConfigVersion.cmake)이 한다는 점을 알아 두면 좋습니다. 많은 라이브러리가 SameMajorVersion 호환성으로 버전 파일을 만들기 때문에, find_package(fmt 9.0)을 요청하면 fmt 10은 “호환되지 않음”으로 거절될 수 있습니다. 더 높은 버전이 설치되어 있는데도 버전 불일치 에러가 난다면 이 호환성 규칙 때문인 경우가 많고, 이때는 9.0...10.99 같은 범위 지정(CMake 3.19+)으로 허용 범위를 명시합니다.
COMPONENTS로 필요한 부분만 찾기
find_package(Boost REQUIRED COMPONENTS
filesystem
system
thread
)
target_link_libraries(myapp PRIVATE
Boost::filesystem
Boost::system
Boost::thread
)
Boost·OpenSSL·Qt·GTest·OpenCV 연결 예제
Boost
find_package(Boost 1.70 REQUIRED COMPONENTS filesystem system)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE
Boost::filesystem
Boost::system
)
OpenSSL
find_package(OpenSSL REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE
OpenSSL::SSL
OpenSSL::Crypto
)
Boost는 특별히 주의할 점이 있습니다. 오랫동안 CMake에 내장된 FindBoost.cmake(Module 모드)가 Boost를 찾아 왔지만, Boost 1.70부터는 Boost 자체가 BoostConfig.cmake를 설치하고, CMake 3.30에서는 내장 FindBoost가 폐기 예정(정책 CMP0167)이 되었습니다. 그래서 같은 find_package(Boost ...)라도 CMake 버전과 정책 설정에 따라 다른 파일이 쓰이고, 에러 메시지 형태도 달라집니다. 새 프로젝트라면 find_package(Boost 1.80 CONFIG REQUIRED COMPONENTS filesystem)처럼 CONFIG를 명시하는 편이 동작이 예측 가능합니다. 헤더 전용 라이브러리만 쓴다면 Boost::headers 타겟을 링크하면 됩니다.
Qt5
find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE
Qt5::Core
Qt5::Widgets
)
# Qt MOC 자동 실행
set_target_properties(myapp PROPERTIES
AUTOMOC ON
AUTOUIC ON
AUTORCC ON
)
Qt 6에서는 find_package(Qt6 REQUIRED COMPONENTS Core Widgets)와 Qt6::Widgets로 이름만 바뀌고 방식은 같습니다. Qt5와 Qt6를 모두 지원해야 한다면 find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) 다음에 find_package(Qt${QT_VERSION_MAJOR} ...)로 실제 버전을 찾는 패턴이 Qt 공식 문서에 소개되어 있습니다.
Google Test
find_package(GTest REQUIRED)
add_executable(tests test.cpp)
target_link_libraries(tests PRIVATE
GTest::gtest
GTest::gtest_main
)
OpenCV
find_package(OpenCV REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE ${OpenCV_LIBS})
target_include_directories(myapp PRIVATE ${OpenCV_INCLUDE_DIRS})
OpenCV처럼 오래된 라이브러리는 Config 모드를 제공하면서도 문서와 예제가 여전히 ${OpenCV_LIBS} 변수 방식이라 위와 같이 쓰는 경우가 많습니다. 이 변수에는 사실 opencv_core, opencv_imgproc 같은 IMPORTED 타겟 이름이 들어 있어서 target_include_directories를 따로 쓰지 않아도 include 경로가 전달되는 경우가 대부분입니다. find_package(OpenCV REQUIRED COMPONENTS core imgproc)로 필요한 모듈만 지정하면 쓰지 않는 모듈까지 링크하지 않아도 됩니다.
find_package가 없는 라이브러리는 pkg-config로
find_package(PkgConfig REQUIRED)
pkg_check_modules(CURL REQUIRED libcurl)
pkg_check_modules(SQLITE REQUIRED sqlite3)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE
${CURL_LIBRARIES}
${SQLITE_LIBRARIES}
)
target_include_directories(myapp PRIVATE
${CURL_INCLUDE_DIRS}
${SQLITE_INCLUDE_DIRS}
)
pkg-config는 CMake 설정 파일을 제공하지 않는 라이브러리(특히 Linux의 C 라이브러리)에 유용합니다. pkg_check_modules(CURL REQUIRED IMPORTED_TARGET libcurl)처럼 IMPORTED_TARGET을 붙이면 변수 대신 PkgConfig::CURL 타겟이 만들어져 다른 find_package 결과와 같은 방식으로 링크할 수 있습니다. 다만 pkg-config는 Windows에서는 기본으로 없고, .pc 파일은 설치 경로를 절대 경로로 담는 경우가 많아 크로스 컴파일에서는 PKG_CONFIG_SYSROOT_DIR 같은 추가 설정이 필요합니다.
Config 모드와 Module 모드의 차이
Config 모드: 라이브러리가 제공하는 Config.cmake
라이브러리가 SomeLibConfig.cmake 또는 somelib-config.cmake 파일을 제공하는 경우입니다. 최신 라이브러리들은 대부분 Config 파일을 제공합니다.
find_package(fmt REQUIRED)
# fmt가 fmtConfig.cmake를 제공하면 자동으로 찾음
target_link_libraries(myapp PRIVATE fmt::fmt)
Config 파일은 각 탐색 접두사(CMAKE_PREFIX_PATH에 준 경로, 시스템 접두사 등) 아래의 <prefix>/lib/cmake/<name>/, <prefix>/share/<name>/ 같은 정해진 하위 디렉터리에서 찾습니다.
Module 모드: CMake의 Find 모듈
CMake가 제공하는 Find<Name>.cmake 모듈을 사용하는 경우입니다.
find_package(CURL REQUIRED)
# CMake의 FindCURL.cmake 모듈 사용
target_link_libraries(myapp PRIVATE CURL::libcurl)
Find<Name>.cmake는 CMAKE_MODULE_PATH에 등록한 디렉터리를 먼저 보고, 그다음 CMake에 내장된 모듈 디렉터리에서 찾습니다. 참고로 FindCURL은 CMake 3.12부터 CURL::libcurl 타겟도 만들어 주지만, 오래된 Find 모듈 중에는 변수만 설정하는 것도 있습니다.
모드 미지정 시 탐색 순서
모드를 지정하지 않은 find_package(Foo)는 Module 모드를 먼저 시도합니다. CMAKE_MODULE_PATH와 CMake 내장 모듈에서 FindFoo.cmake를 찾고, 없을 때만 Config 모드로 넘어가 FooConfig.cmake/foo-config.cmake를 찾습니다. 그래서 라이브러리가 좋은 Config 파일을 설치해 두었는데도 CMake에 오래된 Find 모듈이 있으면 그쪽이 먼저 쓰여, 기대한 타겟 이름이 없거나 버전이 다르게 잡힐 수 있습니다. CMake 3.15부터는 CMAKE_FIND_PACKAGE_PREFER_CONFIG=ON으로 이 순서를 뒤집을 수 있습니다.
Config 모드에서 무엇을 먼저 보는지도 알아 두면 “왜 다른 버전이 잡히는가”를 설명할 수 있습니다. <Name>_DIR 캐시 변수가 이미 설정돼 있으면 그 위치를 그대로 쓰고, 없으면 <Name>_ROOT(CMake 3.12+), CMAKE_PREFIX_PATH, 환경 변수, 시스템 경로 순으로 찾습니다. 한 번 찾은 위치는 Foo_DIR로 캐시되므로, 나중에 다른 버전을 설치하거나 CMAKE_PREFIX_PATH를 바꿔도 기존 빌드 디렉터리에서는 예전 위치가 계속 쓰입니다. 경로를 바꿨는데 결과가 그대로라면 cmake -U Foo_DIR 또는 빌드 디렉터리 삭제가 먼저입니다.
CONFIG·MODULE 키워드로 강제하기
# Config 모드만
find_package(SomeLib CONFIG REQUIRED)
# Module 모드만
find_package(SomeLib MODULE REQUIRED)
# 지정 안 함: Module 먼저, FindSomeLib.cmake가 없으면 Config
# (CMAKE_FIND_PACKAGE_PREFER_CONFIG=ON이면 순서가 반대)
find_package(SomeLib REQUIRED)
FindMyLib.cmake 직접 작성하기
find_path·find_library로 모듈 만들기
# cmake/FindMyLib.cmake
# 헤더 찾기
find_path(MyLib_INCLUDE_DIR
NAMES mylib/mylib.h
PATHS /usr/include /usr/local/include
)
# 라이브러리 찾기
find_library(MyLib_LIBRARY
NAMES mylib
PATHS /usr/lib /usr/local/lib
)
# 버전 확인 (선택)
if(MyLib_INCLUDE_DIR)
file(READ "${MyLib_INCLUDE_DIR}/mylib/version.h" VERSION_CONTENT)
string(REGEX MATCH "MYLIB_VERSION \"([0-9.]+)\"" _ "${VERSION_CONTENT}")
set(MyLib_VERSION ${CMAKE_MATCH_1})
endif()
# 결과 처리
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MyLib
REQUIRED_VARS MyLib_LIBRARY MyLib_INCLUDE_DIR
VERSION_VAR MyLib_VERSION
)
# 타겟 생성
if(MyLib_FOUND AND NOT TARGET MyLib::MyLib)
add_library(MyLib::MyLib UNKNOWN IMPORTED)
set_target_properties(MyLib::MyLib PROPERTIES
IMPORTED_LOCATION "${MyLib_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${MyLib_INCLUDE_DIR}"
)
endif()
Find 모듈을 직접 쓸 때 핵심은 find_package_handle_standard_args와 IMPORTED 타겟 생성입니다. 전자는 REQUIRED·QUIET·버전 인자를 표준 방식으로 처리하고 “Could NOT find MyLib (missing: MyLib_INCLUDE_DIR)” 형태의 일관된 메시지를 만들어 주므로, 직접 message(FATAL_ERROR ...)를 쓰는 것보다 낫습니다. 후자는 if(NOT TARGET MyLib::MyLib)로 감싸 두어야 여러 하위 디렉터리에서 find_package(MyLib)를 호출해도 “target already exists” 에러가 나지 않습니다. 그리고 커스텀 Find 모듈은 어디까지나 라이브러리가 Config 파일을 제공하지 않을 때의 대안입니다. 라이브러리를 직접 관리한다면 install(EXPORT ...)와 configure_package_config_file()로 Config 파일을 설치하는 쪽이 사용자 모두에게 이득입니다.
CMAKE_MODULE_PATH에 등록해 사용하기
# CMakeLists.txt
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
find_package(MyLib REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE MyLib::MyLib)
find_package 실패 메시지별 원인과 해결
그림: 실제 실행 결과 — 설치된 fmt는 12.2.0이라 99.0 요구는 거절되고, 검토한 설정 파일 경로와 그 버전이 메시지에 함께 나온다. 요구 버전을 낮추면 통과한다. 글의 Boost 1.80 예와 같은 종류의 오류를 fmt로 재현했다. (환경: macOS 27.0.1 · cmake version 3.30.3)
Could not find a package configuration file
구성 단계에서 Could not find a package configuration file provided by "SomeLib"가 나오면, 라이브러리가 설치되지 않았거나 CMake가 탐색하지 않는 위치에 설치된 것입니다.
이 메시지는 에러 중 가장 친절한 편입니다. 바로 아래에 찾으려던 파일 이름(SomeLibConfig.cmake, somelib-config.cmake)과 해결 방법(“Add the installation prefix of “SomeLib” to CMAKE_PREFIX_PATH or set “SomeLib_DIR” to a directory containing one of the above files”)이 함께 나옵니다. 여기서 두 변수가 받는 경로가 다르다는 점이 자주 헷갈립니다. CMAKE_PREFIX_PATH에는 설치 접두사(/opt/somelib)를, SomeLib_DIR에는 Config 파일이 실제로 있는 디렉터리(/opt/somelib/lib/cmake/SomeLib)를 줘야 합니다. Linux에서는 런타임 패키지(libfoo)만 있고 개발 패키지(libfoo-dev)가 없어 헤더와 Config 파일이 없는 경우도 흔합니다. 어디를 뒤졌는지 알고 싶다면 cmake --debug-find(CMake 3.17+)로 탐색한 경로 목록을 출력해 실제 파일 위치와 비교하는 것이 가장 빠릅니다.
# 해결법 1: 패키지 설치
sudo apt install libboost-dev # Linux
brew install boost # macOS
vcpkg install boost # vcpkg
# 해결법 2: CMAKE_PREFIX_PATH 지정
cmake -DCMAKE_PREFIX_PATH=/custom/install/path ..
# 해결법 3: 환경 변수
export CMAKE_PREFIX_PATH=/usr/local:$CMAKE_PREFIX_PATH
cmake ..
# 해결법 4: 패키지별 힌트 변수
cmake -DBoost_ROOT=/usr/local/boost ..
요청한 버전과 호환되는 설정 파일이 없음
Could not find a configuration file for package "Boost" that is compatible with requested version "1.80"은 Config 파일은 찾았지만 그 버전 파일이 요청한 버전을 받아들이지 않았다는 뜻입니다. 설치된 버전이 더 낮은 경우가 대부분이고, 앞에서 설명한 것처럼 메이저 버전이 더 높아서 거절되는 경우도 있습니다. 메시지 아래에 검토한 파일과 그 버전이 함께 출력되므로 어느 쪽인지 바로 알 수 있습니다.
# 해결법 1: 버전 요구 완화
find_package(Boost 1.70 REQUIRED) # 1.80 → 1.70
# 해결법 2: 버전 확인 후 조건부
find_package(Boost 1.70)
if(Boost_VERSION VERSION_LESS 1.80)
message(WARNING "Boost 1.80+ recommended, found ${Boost_VERSION}")
endif()
Boost 컴포넌트를 찾지 못함
Unable to find the requested Boost libraries(FindBoost 모듈) 또는 Could not find a package configuration file provided by "boost_filesystem"(BoostConfig.cmake가 컴포넌트마다 다시 find_package를 호출할 때) 같은 메시지는 Boost 본체는 찾았지만 요청한 컴포넌트의 라이브러리가 설치되지 않았다는 뜻입니다. 배포판 패키지는 컴포넌트별로 나뉘어 있는 경우가 많습니다.
# Linux
sudo apt install libboost-filesystem-dev
# macOS
brew install boost
# Windows (vcpkg)
vcpkg install boost-filesystem
찾았는데 타겟이 만들어지지 않음
find_package는 성공했는데 target_link_libraries에서 “target was not found”가 난다면, 실제로 쓰인 것이 문서에서 본 것과 다른 모드나 다른 버전의 파일인 경우가 많습니다. 오래된 Find 모듈은 변수만 설정하고 타겟을 만들지 않으며, 타겟 이름도 버전에 따라 바뀌었습니다(예: FindCURL은 CMake 3.12부터 CURL::libcurl을 제공하고, FindGTest의 GTest::gtest는 CMake 3.20부터입니다). 프로젝트가 요구하는 최소 CMake 버전에서 해당 Find 모듈 문서를 확인하거나, 변수 방식으로 대체합니다.
# 타겟을 제공하지 않는 오래된 환경에서의 변수 방식
find_package(CURL REQUIRED)
target_include_directories(myapp PRIVATE ${CURL_INCLUDE_DIRS})
target_link_libraries(myapp PRIVATE ${CURL_LIBRARIES})
# 타겟을 제공하는 환경 (FindCURL 3.12+ 또는 curl이 설치한 CURLConfig.cmake)
find_package(CURL REQUIRED)
target_link_libraries(myapp PRIVATE CURL::libcurl)
여러 버전 중 엉뚱한 것이 선택됨
같은 패키지가 여러 위치에 설치돼 있으면 아래처럼 원하는 쪽의 경로를 지정합니다. 경로를 지정해도 결과가 바뀌지 않는다면 대부분 캐시 때문입니다. 첫 구성 때 찾은 Boost_DIR(또는 Module 모드의 Boost_INCLUDE_DIR 등)이 CMakeCache.txt에 남아 있으면 CMake는 다시 찾지 않습니다. 새 빌드 디렉터리에서 구성하거나 cmake --fresh(CMake 3.24+)로 캐시를 비운 뒤 다시 확인하세요. 구성 로그에 Found Boost: /usr/lib/x86_64-linux-gnu/cmake/Boost-1.74.0/BoostConfig.cmake (found suitable version "1.74.0", minimum required is "1.70")처럼 실제 사용한 파일 경로가 찍히므로 그 줄을 먼저 확인하는 습관이 좋습니다.
# 특정 버전 경로 지정
cmake -DBoost_ROOT=/usr/local/boost-1.80 ..
# 또는 CMAKE_PREFIX_PATH에 우선순위 경로 추가
cmake -DCMAKE_PREFIX_PATH="/usr/local/boost-1.80;/usr/local" ..
설치했는데도 못 찾는 흔한 세 가지
첫째는 패키지 이름의 대소문자입니다. Config 모드는 <이름>Config.cmake나 <소문자 이름>-config.cmake를 찾으므로, find_package(boost)라고 쓰면 boostConfig.cmake/boost-config.cmake를 찾다가 실제 파일인 BoostConfig.cmake를 놓칩니다. Windows처럼 대소문자를 구분하지 않는 파일 시스템에서는 통과하다가 Linux CI에서만 실패하는 원인이 되므로, 패키지 문서에 적힌 이름을 그대로 씁니다.
둘째는 vcpkg toolchain 파일 누락입니다. vcpkg install로 설치만 하고 -DCMAKE_TOOLCHAIN_FILE=<vcpkg>/scripts/buildsystems/vcpkg.cmake 없이 구성하면 CMake는 vcpkg 설치 디렉터리를 전혀 보지 않습니다. 이 값은 첫 구성 때 캐시에 고정되므로, 이미 만든 빌드 디렉터리에 나중에 추가해도 반영되지 않고 새 빌드 디렉터리(또는 cmake --fresh)가 필요합니다. CMake 3.21 이상에서는 CMAKE_TOOLCHAIN_FILE 환경 변수로 지정해 둘 수도 있습니다.
셋째는 Homebrew 접두사입니다. Apple Silicon Mac의 Homebrew는 /opt/homebrew에 설치하므로 /usr/local만 보던 오래된 설정이나 스크립트는 패키지를 찾지 못합니다. cmake -DCMAKE_PREFIX_PATH="$(brew --prefix)" ..처럼 접두사를 넘기거나, 특정 패키지만이라면 brew --prefix boost가 돌려주는 경로를 씁니다.
선택적 의존성과 버전 분기 패턴
찾으면 기능을 켜는 선택적 의존성
option(USE_OPENSSL "Use OpenSSL for encryption" ON)
if(USE_OPENSSL)
find_package(OpenSSL)
if(OpenSSL_FOUND)
target_link_libraries(myapp PRIVATE OpenSSL::SSL)
target_compile_definitions(myapp PRIVATE USE_OPENSSL)
else()
message(WARNING "OpenSSL not found, using fallback")
endif()
endif()
버전에 따라 기능 분기
find_package(Boost 1.70 REQUIRED COMPONENTS filesystem)
if(Boost_VERSION VERSION_GREATER_EQUAL 1.75)
message(STATUS "Using Boost 1.75+ features")
target_compile_definitions(myapp PRIVATE BOOST_NEW_API)
endif()
여러 후보 패키지 중 하나 선택
# OpenSSL 우선, 없으면 mbedTLS
find_package(OpenSSL)
if(OpenSSL_FOUND)
target_link_libraries(myapp PRIVATE OpenSSL::SSL)
target_compile_definitions(myapp PRIVATE USE_OPENSSL)
else()
# Mbed TLS 3.x가 설치하는 MbedTLSConfig.cmake (이름 대소문자 주의)
find_package(MbedTLS REQUIRED)
target_link_libraries(myapp PRIVATE MbedTLS::mbedtls)
target_compile_definitions(myapp PRIVATE USE_MBEDTLS)
endif()
찾은 패키지 정보 출력
find_package(Boost REQUIRED COMPONENTS filesystem)
message(STATUS "Boost version: ${Boost_VERSION}")
message(STATUS "Boost include: ${Boost_INCLUDE_DIRS}")
message(STATUS "Boost libraries: ${Boost_LIBRARIES}")
비표준 위치를 탐색 경로에 추가
# 프로젝트 로컬 FindModule 경로 추가
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# 커스텀 prefix 경로
list(APPEND CMAKE_PREFIX_PATH "/opt/mylibs")
find_package(MyLib REQUIRED)
Boost·OpenSSL·spdlog를 함께 쓰는 HTTP 서버 구성
CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(HttpServer VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 필수 패키지
find_package(Boost 1.70 REQUIRED COMPONENTS
system
thread
filesystem
)
find_package(OpenSSL REQUIRED)
# 선택적 패키지
find_package(spdlog)
# 실행 파일
add_executable(http_server
src/main.cpp
src/server.cpp
src/request_handler.cpp
)
# 링크
target_link_libraries(http_server PRIVATE
Boost::system
Boost::thread
Boost::filesystem
OpenSSL::SSL
OpenSSL::Crypto
)
# spdlog가 있으면 사용
if(spdlog_FOUND)
target_link_libraries(http_server PRIVATE spdlog::spdlog)
target_compile_definitions(http_server PRIVATE USE_SPDLOG)
else()
message(WARNING "spdlog not found, using std::cout")
endif()
# 헤더 경로
target_include_directories(http_server PRIVATE
${CMAKE_SOURCE_DIR}/include
)
main.cpp
#include <boost/asio.hpp>
#include <openssl/ssl.h>
#ifdef USE_SPDLOG
#include <spdlog/spdlog.h>
#define LOG(msg) spdlog::info(msg)
#else
#include <iostream>
#define LOG(msg) std::cout << msg << '\n'
#endif
int main() {
LOG("HTTP Server starting...");
boost::asio::io_context io;
// 서버 로직...
return 0;
}
패키지별 변수 이름
| 패키지 | 타겟 | 변수 (Module 모드) |
|---|---|---|
| Boost | Boost::filesystem | Boost_FOUND, Boost_INCLUDE_DIRS, Boost_LIBRARIES |
| OpenSSL | OpenSSL::SSL, OpenSSL::Crypto | OPENSSL_FOUND, OPENSSL_INCLUDE_DIR, OPENSSL_LIBRARIES |
| CURL | CURL::libcurl | CURL_FOUND, CURL_INCLUDE_DIRS, CURL_LIBRARIES |
| ZLIB | ZLIB::ZLIB | ZLIB_FOUND, ZLIB_INCLUDE_DIRS, ZLIB_LIBRARIES |
| GTest | GTest::gtest, GTest::gtest_main | GTEST_FOUND, GTEST_INCLUDE_DIRS, GTEST_LIBRARIES |
가능하면 Boost::filesystem 같은 타겟을 사용하세요. 오타가 구성 단계에서 에러로 드러나고, include 경로와 전이 의존성이 PUBLIC/PRIVATE 규칙에 따라 자동으로 전파됩니다. 표의 변수 이름은 모듈마다 대소문자 규칙이 달라서(OPENSSL_FOUND와 OpenSSL_FOUND) 헷갈리기 쉬운데, CMake 3.3 이후로는 find_package에 넘긴 이름 그대로의 <Name>_FOUND도 함께 설정되므로 if(OpenSSL_FOUND)처럼 호출한 이름으로 검사하는 편이 일관적입니다.