CMake 정리 (2편) — 서브디렉토리, 외부 라이브러리, 실용 패턴

2026. 5. 30. 15:51·블로그, 컴퓨터/Cheatsheets

cmake cheatsheet

1편에서 CMakeLists.txt 기본 구조, 타겟 정의, 빌드 타입을 다뤘습니다. 2편에서는 프로젝트가 커졌을 때 쓰는 서브디렉토리 구조, 외부 라이브러리를 끌어오는 방법, 그리고 현장에서 자주 쓰는 패턴들을 정리합니다.


서브디렉토리 구조

프로젝트가 커지면 디렉토리를 나눠서 관리합니다. 각 디렉토리마다 CMakeLists.txt를 두고, 루트에서 add_subdirectory()로 불러오는 방식입니다.

디렉토리 구조 예시

MyProject/
├── CMakeLists.txt          # 루트
├── src/
│   ├── CMakeLists.txt
│   ├── main.cpp
│   └── parser.cpp
├── lib/
│   ├── CMakeLists.txt
│   └── utils.cpp
└── tests/
    ├── CMakeLists.txt
    └── test_parser.cpp

루트 CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(MyProject VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

option(BUILD_TESTS "테스트 빌드" ON)

add_subdirectory(lib)
add_subdirectory(src)

if(BUILD_TESTS)
  enable_testing()
  add_subdirectory(tests)
endif()

lib/CMakeLists.txt

add_library(utils STATIC utils.cpp)

target_include_directories(utils PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}
)

src/CMakeLists.txt

add_executable(myapp main.cpp parser.cpp)

target_link_libraries(myapp PRIVATE utils)

lib에서 PUBLIC으로 include 경로를 열어뒀기 때문에, myapp이 utils에 링크하면 자동으로 include 경로도 따라옵니다.


find_package — 시스템 라이브러리 찾기

설치된 라이브러리를 CMake가 찾아서 연결합니다.

find_package(패키지명 버전 REQUIRED)
# OpenSSL
find_package(OpenSSL REQUIRED)
target_link_libraries(myapp PRIVATE OpenSSL::SSL OpenSSL::Crypto)

# Threads (pthread)
find_package(Threads REQUIRED)
target_link_libraries(myapp PRIVATE Threads::Threads)

# Boost
find_package(Boost 1.70 REQUIRED COMPONENTS filesystem system)
target_link_libraries(myapp PRIVATE Boost::filesystem Boost::system)

# zlib
find_package(ZLIB REQUIRED)
target_link_libraries(myapp PRIVATE ZLIB::ZLIB)

REQUIRED를 붙이면 못 찾을 때 에러로 멈춥니다. 선택적으로 쓰려면 빼고 if(패키지_FOUND)로 분기합니다.

find_package(OpenSSL)
if(OpenSSL_FOUND)
  target_link_libraries(myapp PRIVATE OpenSSL::SSL)
  target_compile_definitions(myapp PRIVATE HAS_OPENSSL)
endif()

pkg-config 방식

find_package 모듈이 없는 라이브러리는 pkg-config로 찾습니다.

find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBFOO REQUIRED libfoo)

target_include_directories(myapp PRIVATE ${LIBFOO_INCLUDE_DIRS})
target_link_libraries(myapp PRIVATE ${LIBFOO_LIBRARIES})

FetchContent — 의존성 자동 다운로드

외부 라이브러리를 git에서 직접 받아서 빌드에 포함시킵니다. 별도 설치 없이 cmake configure 시점에 자동으로 받아옵니다.

include(FetchContent)

FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        v1.14.0
)
FetchContent_MakeAvailable(googletest)

FetchContent_MakeAvailable()이 다운로드 + add_subdirectory를 한 번에 처리합니다.

자주 쓰는 라이브러리 예시

include(FetchContent)

# Google Test
FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        v1.14.0
)

# nlohmann/json
FetchContent_Declare(
  nlohmann_json
  GIT_REPOSITORY https://github.com/nlohmann/json.git
  GIT_TAG        v3.11.3
)

# spdlog
FetchContent_Declare(
  spdlog
  GIT_REPOSITORY https://github.com/gabime/spdlog.git
  GIT_TAG        v1.13.0
)

# fmt
FetchContent_Declare(
  fmt
  GIT_REPOSITORY https://github.com/fmtlib/fmt.git
  GIT_TAG        10.2.1
)

FetchContent_MakeAvailable(googletest nlohmann_json spdlog fmt)

target_link_libraries(myapp PRIVATE
  nlohmann_json::nlohmann_json
  spdlog::spdlog
  fmt::fmt
)

여러 개를 FetchContent_MakeAvailable()에 한 번에 넘길 수 있습니다.

다운로드 속도 개선

매번 git clone을 하면 느릴 수 있습니다. 아래 설정으로 zip 아카이브를 받으면 빠릅니다.

FetchContent_Declare(
  nlohmann_json
  URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz
  URL_HASH SHA256=d6c65aca6b1ed68e7a182f4757257b107ae403032760ed6ef121c9d55e81757d
)

테스트 — CTest

CMake에 내장된 테스트 프레임워크입니다. Google Test와 같이 쓰는 패턴이 가장 많습니다.

# 루트 CMakeLists.txt
enable_testing()

# tests/CMakeLists.txt
add_executable(test_parser test_parser.cpp)
target_link_libraries(test_parser PRIVATE
  GTest::gtest_main
  mylib
)

include(GoogleTest)
gtest_discover_tests(test_parser)
# 빌드 후 테스트 실행
cd build
ctest
ctest --output-on-failure    # 실패한 테스트 상세 출력
ctest -R test_parser         # 특정 테스트만
ctest --parallel 4           # 병렬 실행

설치 규칙

install(TARGETS myapp
  RUNTIME DESTINATION bin         # 실행 파일
  LIBRARY DESTINATION lib         # 동적 라이브러리
  ARCHIVE DESTINATION lib         # 정적 라이브러리
)

install(DIRECTORY include/
  DESTINATION include
)

install(FILES config.yaml
  DESTINATION etc/myapp
)
cmake --install build --prefix /usr/local

생성된 파일에 변수 삽입 — configure_file

소스 파일이나 설정 파일에 CMake 변수를 주입할 때 씁니다.

configure_file(
  ${CMAKE_SOURCE_DIR}/src/version.h.in
  ${CMAKE_BINARY_DIR}/version.h
)
// version.h.in
#pragma once
#define APP_VERSION "@PROJECT_VERSION@"
#define APP_NAME    "@PROJECT_NAME@"

빌드 후 version.h에 실제 값이 들어간 파일이 생성됩니다.


컴파일러 확인과 플랫폼 분기

# 컴파일러별 옵션
if(MSVC)
  target_compile_options(myapp PRIVATE /W4 /WX)
else()
  target_compile_options(myapp PRIVATE -Wall -Wextra -Werror)
endif()

# 플랫폼별 분기
if(WIN32)
  target_compile_definitions(myapp PRIVATE PLATFORM_WINDOWS)
elseif(APPLE)
  target_compile_definitions(myapp PRIVATE PLATFORM_MACOS)
elseif(UNIX)
  target_compile_definitions(myapp PRIVATE PLATFORM_LINUX)
endif()

# 컴파일러 식별
message(STATUS "컴파일러: ${CMAKE_CXX_COMPILER_ID}")  # GNU, Clang, MSVC
message(STATUS "컴파일러 버전: ${CMAKE_CXX_COMPILER_VERSION}")

실용 패턴 모음

compile_commands.json 생성

LSP(clangd)나 IDE에서 사용합니다. Neovim LSP 설정에서 clangd를 쓴다면 이 파일이 있어야 정확히 동작합니다.

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

또는 configure 시 옵션으로 줍니다.

cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

build/compile_commands.json이 생성됩니다. 루트에 심볼릭 링크를 만들어두면 clangd가 자동으로 찾습니다.

ln -s build/compile_commands.json compile_commands.json

디버그 / 릴리즈 공통 설정

# 빌드 타입에 따른 정의
target_compile_definitions(myapp PRIVATE
  $<$<CONFIG:Debug>:DEBUG_MODE>
  $<$<CONFIG:Release>:NDEBUG>
)

# 제너레이터 표현식으로 조건부 옵션
target_compile_options(myapp PRIVATE
  $<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra>
  $<$<CXX_COMPILER_ID:Clang>:-Wall -Wextra -Wno-unused-parameter>
)

$<조건:값> 형태는 제너레이터 표현식이라고 부릅니다. configure 시점이 아니라 빌드 시점에 평가됩니다.

자주 쓰는 전체 CMakeLists.txt 템플릿

cmake_minimum_required(VERSION 3.20)
project(MyProject VERSION 1.0.0 LANGUAGES CXX)

# ── 기본 설정 ─────────────────────────────────
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Debug CACHE STRING "빌드 타입" FORCE)
endif()

# ── 옵션 ──────────────────────────────────────
option(BUILD_TESTS "테스트 빌드" ON)

# ── 외부 의존성 ───────────────────────────────
include(FetchContent)

FetchContent_Declare(
  spdlog
  GIT_REPOSITORY https://github.com/gabime/spdlog.git
  GIT_TAG        v1.13.0
)
FetchContent_MakeAvailable(spdlog)

# ── 타겟 ──────────────────────────────────────
add_executable(myapp
  src/main.cpp
  src/parser.cpp
)

target_include_directories(myapp PRIVATE
  ${CMAKE_SOURCE_DIR}/include
)

target_link_libraries(myapp PRIVATE
  spdlog::spdlog
)

target_compile_options(myapp PRIVATE
  $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra>
)

# ── 테스트 ────────────────────────────────────
if(BUILD_TESTS)
  enable_testing()
  add_subdirectory(tests)
endif()

정리 표

명령어 용도
add_subdirectory(경로) 서브 CMakeLists.txt 포함
find_package(이름 REQUIRED) 시스템 라이브러리 탐색
include(FetchContent) FetchContent 모듈 로드
FetchContent_Declare(이름 ...) 외부 의존성 선언
FetchContent_MakeAvailable(이름) 다운로드 + 빌드 포함
enable_testing() CTest 활성화
gtest_discover_tests(타겟) Google Test 자동 등록
install(TARGETS ...) 설치 규칙 정의
configure_file(in out) 변수 주입 파일 생성
CMAKE_EXPORT_COMPILE_COMMANDS clangd용 JSON 생성

접근 제어 요약

키워드 현재 타겟 링크하는 타겟
PRIVATE ✓ ✗
PUBLIC ✓ ✓
INTERFACE ✗ ✓
반응형
저작자표시 비영리 변경금지 (새창열림)

'블로그, 컴퓨터 > Cheatsheets' 카테고리의 다른 글

GitHub Actions 정리 (2편) — 캐싱, Matrix, 재사용, 실전 패턴  (0) 2026.05.31
GitHub Actions 정리 (1편) — 개념, 워크플로우 구조, 트리거  (0) 2026.05.31
CMake 정리 (1편) — 개념, CMakeLists.txt, 기본 빌드  (0) 2026.05.30
tmux 정리 (2편) — 설정, 플러그인, 실용 커스터마이징  (0) 2026.05.29
tmux 정리 (1편) — 세션, 윈도우, 패널  (0) 2026.05.29
'블로그, 컴퓨터/Cheatsheets' 카테고리의 다른 글
  • GitHub Actions 정리 (2편) — 캐싱, Matrix, 재사용, 실전 패턴
  • GitHub Actions 정리 (1편) — 개념, 워크플로우 구조, 트리거
  • CMake 정리 (1편) — 개념, CMakeLists.txt, 기본 빌드
  • tmux 정리 (2편) — 설정, 플러그인, 실용 커스터마이징
생각사람
생각사람
지극히 사적인 연구실
  • 생각사람
    생각사람의 별장
    생각사람
  • 전체
    오늘
    어제
    • 분류 전체보기 (207)
      • 금융 (57)
        • 주식 공부 (11)
        • 파생상품 입문 (17)
        • 파생상품 기초 (15)
        • 파생상품 실전 (14)
      • 블로그, 컴퓨터 (83)
        • 프로그래밍 (16)
        • DevOps (8)
        • AI, RL, ML, ... (5)
        • 애드센스, SEO (23)
        • 임베디드 (3)
        • 컴퓨터 관련 (7)
        • Cheatsheets (21)
      • 다른 공부들 (67)
        • 읽고 쓰기 (18)
        • 수학 (15)
        • 물리 (9)
        • 사진 공부 (25)
  • 인기 글

  • 최근 글

  • 최근 댓글

  • 태그

    Kreyszig
    GIT
    벡터
    독후감
    version control
    슈뢰딩거 방정식
    github
    CheatSheet
    소니 a6000
    옵션
    깃허브
    공업수학
    파생상품
    웹크롤러
    행렬
    프로그래밍
    선물 옵션
    코딩
    선형대수학
    스트랭글
    양자역학
    AI
    c
    cmake
    스트래들
    옵션 투자
    c++
    깃
    오펜하이머
    구글 애드센스
  • hELLO· Designed By정상우.v4.10.6
생각사람
CMake 정리 (2편) — 서브디렉토리, 외부 라이브러리, 실용 패턴
상단으로

티스토리툴바