Build(빌드)/CMake
[CMake] target_include_directories와 target_link_libraries 개념
2026. 5. 11. 01:55반응형
target_include_directories vs target_link_libraries 키워드
두 명령어 모두 PUBLIC / PRIVATE / INTERFACE 키워드를 사용하지만, 전파되는 속성(property)이 다르기 때문에 의미와 효과가 다릅니다.
핵심 개념: 두 가지 관점
| 관점 | 속성 |
| 헤더(컴파일) | INCLUDE_DIRECTORIES, INTERFACE_INCLUDE_DIRECTORIES |
| 링크 | LINK_LIBRARIES, INTERFACE_LINK_LIBRARIES |
키워드는 "이 타겟 자신에게 적용되는가" 와 "이 타겟에 의존하는 타겟에게도 전파되는가" 를 동시에 제어합니다.
키워드 의미 (공통)
나 자신에게 적용? 의존자에게 전파?
PRIVATE ✅ ❌
INTERFACE ❌ ✅
PUBLIC ✅ ✅
target_include_directories
컴파일 시 헤더 탐색 경로(-I)를 제어합니다.
target_include_directories(<target>
PUBLIC <include_dir> # 나도 쓰고, 나를 쓰는 놈도 써야 함
PRIVATE <include_dir> # 나만 씀 (구현 내부 헤더)
INTERFACE <include_dir> # 나는 안 씀, 나를 쓰는 놈만 써야 함
)
실제 예시
project/
├── libfoo/
│ ├── include/foo/foo.h ← public API 헤더
│ ├── src/foo.cpp
│ └── src/internal/detail.h ← 내부 구현 헤더
└── app/
└── main.cpp ← #include <foo/foo.h> 사용
# libfoo/CMakeLists.txt
add_library(foo STATIC src/foo.cpp)
target_include_directories(foo
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include # foo.h → app도 필요
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/internal # detail.h → foo만 필요
)
# app/CMakeLists.txt
add_executable(app main.cpp)
target_link_libraries(app PRIVATE foo)
# → app은 자동으로 include/foo 경로를 얻음 (foo의 PUBLIC이 전파됨)
# → src/internal 경로는 전파 안 됨
전파되는 CMake 내부 속성
| 키워드 | 자신의 속성 | 전파되는 속성 |
| PRIVATE | INCLUDE_DIRECTORIES | — |
| INTERFACE | — | INTERFACE_INCLUDE_DIRECTORIES |
| PUBLIC | INCLUDE_DIRECTORIES | INTERFACE_INCLUDE_DIRECTORIES |
target_link_libraries
링크 시 의존 라이브러리(-l, -L)를 제어합니다. 단, 키워드가 없으면 헤더 경로까지 함께 전파됩니다 (transitive dependency).
target_link_libraries(<target>
PUBLIC <lib> # 나도 링크, 나를 쓰는 놈도 링크해야 함
PRIVATE <lib> # 나만 링크 (구현 내부에서만 사용)
INTERFACE <lib> # 나는 링크 안 함, 나를 쓰는 놈이 링크해야 함
)
실제 예시: 3계층 의존성
app → libbar → libfoo
# libfoo
add_library(foo STATIC foo.cpp)
target_include_directories(foo PUBLIC include)
# libbar: foo를 PUBLIC으로 링크 → bar의 헤더에서 foo 타입을 노출함
add_library(bar STATIC bar.cpp)
target_link_libraries(bar PUBLIC foo)
# bar.h 안에 foo::SomeType 사용 → app도 foo 헤더가 필요
# app
add_executable(app main.cpp)
target_link_libraries(app PRIVATE bar)
# → app은 bar도 링크, foo도 자동으로 링크됨 (bar의 PUBLIC 전파)
# → app은 foo의 include 경로도 자동으로 얻음
# 반대 케이스: foo가 bar 내부 구현에서만 쓰임
target_link_libraries(bar PRIVATE foo)
# → app은 foo를 링크 안 해도 됨
# → app은 foo 헤더 경로도 받지 않음
전파되는 CMake 내부 속성
| 키워드 | 자신의 속성 | 전파되는 속성 |
| PRIVATE | LINK_LIBRARIES | — |
| INTERFACE | — | INTERFACE_LINK_LIBRARIES |
| PUBLIC | LINK_LIBRARIES | INTERFACE_LINK_LIBRARIES |
두 명령어의 관계
target_link_libraries로 CMake 타겟을 연결하면, 링크뿐 아니라 그 타겟의 INTERFACE_INCLUDE_DIRECTORIES도 자동으로 전파됩니다.
target_link_libraries(app PRIVATE foo)
# 이 한 줄이 아래 두 줄을 암묵적으로 수행:
# - app이 foo를 링크 (-lfoo)
# - foo의 INTERFACE_INCLUDE_DIRECTORIES → app의 INCLUDE_DIRECTORIES로 추가
그래서 올바르게 구성된 라이브러리라면 target_link_libraries 하나만으로 충분하고, 별도의 target_include_directories를 소비자 쪽에서 쓸 필요가 없습니다.
판단 기준 요약
이 헤더/라이브러리가...
├── 내 .cpp 구현 파일에서만 쓰임? → PRIVATE
├── 내 공개 헤더(.h)에 노출됨? → PUBLIC
└── 내 헤더에만 노출, 내 .cpp엔 없음? → INTERFACE
(header-only 라이브러리가 대표적)반응형
'Build(빌드) > CMake' 카테고리의 다른 글
| [CMake] 플러그인 빌드 구조 만들기 - 예제 2. 정적라이브러리 심볼 활용 (0) | 2026.05.18 |
|---|---|
| [CMake] 플러그인 빌드 구조 만들기 (--export-dynamic 활용) (0) | 2026.05.14 |
| [CMake] CMake 명령어 순서에 대한 고찰 (0) | 2026.05.11 |
| [CMake] find_package와 pkg_check_modules(PkgConfig)의 차이에 대한 고찰 (0) | 2026.04.16 |
| [CMake] Module(모듈) (0) | 2025.12.03 |