CMake

Definition : What is CMake

  • this is a tool or language (not compiler) that create commands of compiler based on what OS is and what kind of Generator (build system) we use.

Terms

Term Meaning
configure CmakeList.txt를 읽으며, 프로젝트 설정들을 확인하여, build 에 필요한 재료들을 만드는 과정 및 행동
build ..
target configure or build 대상들
linking target들을 연결하는 과정. 빌드를 한다고하면, 각 target들로부터 개별적인 object 파일들을 만들며, 이 object 파일들을 연결해줘야한다.
configurations First off Debug/Release are called configurations
.dll 동적 라이브러리 : 라이브러리 인데, 런타임에 포함되는 라이브러리임 + .lib 사용될때 같이 사용됨
.lib 정적 라이브러리 : 라이버리리 인데, 컴파일 때 포함되는 라이버리임 + 모든 코드가 다 들어있음

when to use dll / lib ?

빌드 방식 필요 파일 설명
정적 라이브러리 .lib 실행 파일에 라이브러리 코드가 포함. .dll 파일 불필요.
동적 라이브러리 .lib + .dll 컴파일 시 .lib, 실행 시 .dll 필요. 실행 파일 배포 시 .dll 포함.
  • 정적 라이브러리 (STATIC)

    • 확장자: .lib (Windows), .a (Linux/macOS)
    • 정의: 빌드 시점에 라이브러리 코드가 호출 대상 실행 파일에 그대로 포함되어 하나의 독립 실행 파일을 생성합니다.
  • 공유 라이브러리 (SHARED)

    • 확장자: .dll (Windows), .so (Linux), .dylib (macOS)
    • 정의: 실행 시점에 동적으로 라이브러리를 로딩하여 심볼(함수, 데이터 등)을 연결합니다.
  • 장단점 및 사용 적합 시기

구분 정적 라이브러리 (STATIC) 공유 라이브러리 (SHARED)
장점 - 실행 파일 하나만 배포하면 됨
- 런타임 의존성 문제 감소
- 실행 파일 크기 작음
- 라이브러리만 교체해도 기능/보안 업데이트 반영됨
- 여러 프로세스가 메모리 공유 가능
단점 - 실행 파일 크기 증가
- 라이브러리 수정 시 전체 재빌드 필요
- 런타임에 DLL/SO 위치 설정 필요
- 배포 시 .dll/.so 파일 포함 관리 필요
사용 적합 시기 - 소규모 툴, 단일 배포 바이너리 선호
- 특정 버전 고정 필요할 때
- 플러그인 시스템, 자주 업데이트되는 기능 모듈
- 메모리 최적화가 중요한 대규모 애플리케이션

CMAKE_PREFIX_PATH

  • 역할: find_package()가 검색할 설치 경로 목록을 지정하는 변수
  • 형식:

    # CMake 호출 시 옵션으로 설정
    cmake -DCMAKE_PREFIX_PATH="/opt/myLib;/usr/local/myOtherLib" ../src
    
  • 동작:

    1. CMAKE_PREFIX_PATH에 지정된 폴더를 먼저 뒤져 <prefix>/lib, <prefix>/share 등에서 <Package>Config.cmake 찾기
    2. 전역 설치 경로(/usr, /usr/local)를 뒤지기 전에 우선 탐색
  • 사용 예:

    cmake -DCMAKE_PREFIX_PATH="C:/MySdk;C:/AnotherLib" -B build
    

Install list of CMake dev env

Windows

  1. install several software
  2. install wsl : wsl --install
  3. install package on linux (ubuntu)
     sudo apt-get update
     sudo apt-get upgrade
        
     # Mandatory
     sudo apt-get install gcc g++ gdb
     sudo apt-get install make cmake
     sudo apt-get install git
     sudo apt-get install doxygen
     sudo apt-get install python3 python3-pip
        
     # Optional
     sudo apt-get install lcov gcovr
     sudo apt-get install ccache
     sudo apt-get install cppcheck
     sudo apt-get install llvm clang-format clang-tidy
     sudo apt-get install curl zip unzip tar
     sudo apt-get install graphviz
    
  4. install several extentions of vscode
    • C/C++ Extension Pack
    • Coding Tools extension Pack
    • WSL
  5. set global setting on VScode (User tab) :arrow_left: optional

Build after coding

```
0.) Create Source and CMakeFile
1.) mkdir build
2.) cd build
3.) cmake ..   -  Generting the Build Files / Configure the Project
4.) cmake --build .
5.) ./Executable
```


Methods

find_package( [version] [REQUIRED] [COMPONENTS ...])

  • 목적: CMake 모듈 또는 패키지 설정 파일을 통해 자동으로 의존성 경로를 설정
  • 인자:

    • <Package>: 찾을 패키지 이름
    • version: 최소/최대 버전 명시
    • REQUIRED: 없으면 에러, 있으면 경고 후 계속
    • COMPONENTS: 모듈별로 나눠 로드 가능 (예: usd, usdGeom)
  • 결과: <Package>_INCLUDE_DIRS, <Package>_LIBRARIES 변수 또는 <Package>::... 인터페이스 타겟 제공

include_directories(...) / target_include_directories( [SYSTEM] [AFTER|BEFORE] ...)

  • 목적: 컴파일러 헤더 검색 경로 추가
  • 차이:

    • 전역: include_directories()는 이후 모든 타겟에 적용
    • 타겟 한정: target_include_directories()는 특정 타겟에만 적용
  • 사용 예:
target_include_directories(myexe PRIVATE
  ${SomeLib_INCLUDE_DIRS}
)
  • 목적: 링커가 라이브러리(.lib/.a/.so) 파일을 찾을 수 있는 경로를 추가
  • 주의:

    • 가능하면 인터페이스 타겟 사용(find_package() 방식) 권장
    • 전역 설정이므로 의존성 충돌 우려
  • 목적: 특정 타겟에 라이브러리 링크를 지정
  • 키워드:

    • PRIVATE: 해당 타겟만 링크
    • PUBLIC: 해당 타겟 + 이를 링크하는 하위 타겟
    • INTERFACE: 링크 명세만 전파 (실체 없는 허브 타겟용)
  • 사용 예:

    target_link_libraries(myexe
      PRIVATE
        fnusd
        OpenUSD::usd
    )
    

add_library()

  • 자신이 작성한 C++ 소스(myCode.cpp)와 헤더(myCode.h)를 하나의 라이브러리로 만들고, 다른 타겟과 연동하는 방법입니다.

Create static library


  # myCode.cpp, myCode.h가 있는 디렉토리에서
  add_library(mycode_static STATIC
    myCode.cpp
    myCode.h       # 헤더를 명시해도 되고, 헤더는 include 디렉토리에만 두어도 됨
  )

  target_include_directories(mycode_static PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}  # 헤더 파일 위치
  )
  • STATIC: 정적(.lib/.a) 라이브러리를 생성
  • PUBLIC: 이 라이브러리를 링크하는 타겟에도 include 디렉토리를 전달

Create shared library

  add_library(mycode_shared SHARED
    myCode.cpp
  )

  target_include_directories(mycode_shared PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}
  )
  • SHARED: 공유(.dll/.so) 라이브러리를 생성
  • 헤더는 별도로 target_include_directories()로 설정

7.3 라이브러리 사용하기

# 라이브러리 생성 뒤, 실행 파일을 만들고 링크
add_executable(myApp main.cpp)

target_link_libraries(myApp PRIVATE
  mycode_static  # 또는 mycode_shared
)
  • myApp 타겟은 mycode_* 라이브러리의 심볼과 헤더를 사용 가능

Tip: ## 7.4 정적 라이브러리(Static) vs 공유 라이브러리(Shared)

CMake에서 add_library()로 생성할 때, STATICSHARED 두 가지 유형을 선택할 수 있습니다. 이하 정의와 적합한 사용 시기를 정리합니다.

[ Basic - (project / add_executable) ]

cmake_minimum_required(VERSION 3.22)

#       projectName         projectVersion  projectLanguage (CXX stands for C++)
#           v                   v               v
project(CppProjectTemplate  VERSION 1.0.0   LANGUAGES C CXX)

#          User defined name
#                  v
add_executable(Executable main.cc)

[ Add variable - set ]

  • set(변수명 변수값) or set(변수명 “변수값”) -> 선호에 따라서
set(LIBRARY_SOURCES
    my_lib.cc)
set(LIBRARY_HEADERS
    my_lib.h)

    or

set(LIBRARY_SOURCES
    "my_lib.cc")
set(LIBRARY_HEADERS
    "my_lib.h")

[ Use external os environment vairable ]

  • set(CMAKE변수명 $ENV{컴퓨터환경변수})
  • bring os env variable in cmake. and then use it as a local variable

[ Add local library ]

  • 자신이 작성한 C++ 소스(myCode.cpp)와 헤더(myCode.h)를 하나의 라이브러리로 만드는 방법으로,사용하게되면 target으로 지정하게 되는데, 다른 타겟과 연동하는 방법입니다.
set(EXECUTABLE_NAME Executable)
set(LIBRARY_NAME Library)

add_library(${LIBRARY_NAME} my_lib.cc)                      # library 파일들 리스트업
add_executable(${EXECUTABLE_NAME} main.cc)                  # execuatable 하게 만들 파일 targeting
target_link_libraries(${EXECUTABLE_NAME} ${LIBRARY_NAME})   # library하고 target파일을 연결관계 정의 

[ Add local library 2 ]

  • 폴더 구조를 만들고, library 를 위한 코드들이 다른 공간으로 분리되어있을 때,
  • header 파일을 추가하고싶을때, 사용

# - root
#     |-- app
#     |    |-- main.cc
#     |    |-- CMakeList.txt : 
#                   add_executable(${EXECUTABLE_NAME} "main.cc")
#                   target_link_libraries(${EXECUTABLE_NAME} PUBLIC ${LIBRARY_NAME})
#     |-- src
#          |-- CMakeList.txt : add_subdirectory(my_lib)
#          |-- my_lib
#                |-- CMakeList.txt : add_library / target_include_directories 사용 ----------
#     |-- CMakeList.txt                                                                     |
#                   cmake_minimum_required(VERSION 3.22)                                    |
#                   project(CppProjectTemplate VERSION 1.0.0 LANGUAGES C CXX)               |
#                   set(EXECUTABLE_NAME Executable)                                         |
#                   set(LIBRARY_NAME Library)                                               |
#                   add_subdirectory(src)                                                   |
#                   add_subdirectory(app)                                                   |
#                                   ---------------------------------------------------------
#                                   |
set(LIBRARY_SOURCES
    my_lib.cc)
set(LIBRARY_HEADERS
    my_lib.h)

add_library(${LIBRARY_NAME} STATIC
    ${LIBRARY_SOURCES}
    ${LIBRARY_HEADERS})
# Include dir to header files
# This does not have to be set, to be able to compile the program
# However, for MSVC builds this is needed, to have the headers listed in VS.
target_include_directories(${LIBRARY_NAME} PUBLIC 
    "./")

[ How to set Debug / release ]

  • First off Debug/Release are called configurations in cmake (nitpick). If you are using a single configuration generator (Ninja/Unix-Makefiles) you must specify the CMAKE_BUILD_TYPE.

  • Like this:

# Configure the build
cmake -S . -B build/ -D CMAKE_BUILD_TYPE=Debug

# Actually build the binaries
cmake --build build/

# Configure a release build
cmake -S . -B build/ -D CMAKE_BUILD_TYPE=Release

# Build release binaries
cmake --build build/
For multi-configuration generators it's slightly different (Ninja Multi-Config, Visual Studio)

# Configure the build
cmake -S . -B build

# Build debug binaries
cmake --build build --config Debug

# Build release binaries
cmake --build build --config Release
  • If you are wondering why this is necessary it’s because cmake isn’t a build system. It’s a meta-build system (IE a build system that build’s build systems). This is basically the result of handling build systems that support multiple-configurations in 1 build. If you’d like a deeper understanding I’d suggest reading a bit about cmake in Craig Scott’s book “Professional CMake: A Practical Guide

[ External library - Imath]

  1. Imath build 먼저
  2. CMakeList.txt 에 아래의 conditions 들 추가
    1. set Imath_DIR to ImathConfig.cmake directory.
    2. put include directory in target_include_directories() function
    3. put .lib file path in target_link_libraries() function to link in between source code and libraries.
    
     ...
    
     set(Imath_ROOT ...)
     set(Imath_LIB ${Imath_ROOT}/lib/Imath-3_1.lib)
     set(Imath_DIR ${Imath_ROOT}/lib/cmake/Imath)
     set(Imath_INCLUDE_DIR ${Imath_ROOT}/include/Imath)
        
     find_package(Katana PATHS "${KATANA_ROOT}/plugin_apis/cmake" REQUIRED)
     find_package(Imath REQUIRED)
        
     add_library(
                 ${LIBRARY_NAME}
                 MODULE
                 code.cpp
     )
        
     target_include_directories(
         ${LIBRARY_NAME}
         PUBLIC
         ${Imath_INCLUDE_DIR}
     )
        
     target_link_libraries(${LIBRARY_NAME}
         PRIVATE
         Katana::FnGeolibPluginApis::Shared
         ${Imath_LIB}
     )
     set_target_properties(${LIBRARY_NAME} PROPERTIES PREFIX "")
    

    [ How to set up external libraries ]

  • CMake 프로젝트에서 외부 라이브러리를 연동하는 방법은 크게 두 가지로 나뉩니다:
    1. 직접 지정(Manual Specification)
    2. find_package() 사용
    3. vcpkg 방식

Ways to set up based on form of library

라이브러리 형태 연동 방법 설명
헤더 + 바이너리(.lib/.dll/.so)
Katana FnUSD 등
직접 지정 CMake 설정 파일(Config/Find 모듈)이 없으므로 include/link 경로를 수동 등록
설치(in-stall) 형태, CMake Config 제공
OpenUSD, Qt, Boost 등
find_package() 사용 <Library>Config.cmake 또는 CMake 내장 Find<Library>.cmake를 통해 자동 경로 설정

1. Manual Specification (Direct)

  • When to use
    • CMake용 설정 파일을 제공하지 않는 서드파티 바이너리
    • 커스텀 빌드 환경, 내부 배포된 라이브러리 등
  • 기본 흐름
    1. include_directories() 또는 target_include_directories()로 헤더 경로 등록
    2. link_directories()로 라이브러리 검색 폴더 등록
    3. target_link_libraries()로 실제 라이브러리 링크
      set(KATANA_ROOT "C:/Program Files/Katana6.5v4" CACHE PATH "Katana install root")
    
      add_executable(MyUsdTool main.cpp)
    
      # 1) 헤더 경로
      target_include_directories(MyUsdTool PRIVATE
      "${KATANA_ROOT}/external/FnUSD/include"
      )
    
      # 2) 라이브러리 검색 경로 (Windows의 경우)
      link_directories(
      "${KATANA_ROOT}/bin"
      )
    
      # 3) 필요한 FnUSD 모듈 링크
      target_link_libraries(MyUsdTool PRIVATE
      fnusd
      fnUSDEngine
      fnusdGeom
      fnusdImaging
      )
    

2. By using find_package()

  • 동작 원리
    • Config 모드: <Package>Config.cmake를 찾아 설정 변수나 인터페이스 타겟을 가져옴
    • Module 모드: CMake 내장 Find<Package>.cmake를 찾아 *_INCLUDE_DIRS, *_LIBRARIES 등을 설정
  • 사용 시기

    • 공식 라이브러리(Boost, Qt, OpenCV 등)
    • 설치 형태로 CMake 설정 파일을 제공하는 오픈소스/사내 패키지
  • 예시

      # Config 모드 (OpenUSD가 제공하는 경우)
      find_package(OpenUSD 23.05 REQUIRED COMPONENTS usd usdGeom)
    
      add_executable(myexe main.cpp)
      # 자동으로 설정된 인터페이스 타겟 사용
      target_link_libraries(myexe PRIVATE OpenUSD::usd OpenUSD::usdGeom)
    
      # Module 모드 (CMake 내장 모듈 사용)
      find_package(ZLIB REQUIRED)
      include_directories(${ZLIB_INCLUDE_DIRS})
      target_link_libraries(myexe PRIVATE ${ZLIB_LIBRARIES})
    

3. Using vcpkg

(1) vcpkg 설치

git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh  # Windows: .\bootstrap-vcpkg.bat

(2) 라이브러리 설치

vcpkg install [패키지명]            # 예: vcpkg install fmt
vcpkg install [패키지명]:x64-windows  # 플랫폼 지정

(3) CMake에서 사용하기

  1. Toolchain 파일 지정

    cmake -B build -S . \
      -DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
    
  2. find_package() 또는 직접 링크

    • vcpkg가 CMake용 설정 파일을 제공하는 라이브러리라면 find_package() 사용 가능

      find_package(fmt CONFIG REQUIRED)
      target_link_libraries(myexe PRIVATE fmt::fmt)
      
    • 그렇지 않은 경우, vcpkg toolchain이 자동으로 include/library 디렉토리를 CMake에 추가하므로

      find_library(FOO_LIB foo)           # 또는 직접 경로 사용
      target_link_libraries(myexe PRIVATE ${FOO_LIB})
      
  3. CMAKE_TOOLCHAIN_FILE 변수

    • -DCMAKE_TOOLCHAIN_FILE 옵션을 통해 vcpkg가 설치된 라이브러리를 자동으로 검색 및 설정
    • CMAKE_PREFIX_PATH 대신 toolchain 파일을 사용하는 것이 권장됩니다.

results matching ""

    No results matching ""