기술 노트

CMake 입문: 빌드 자동화 기초와 실전 예제

anothel 2022. 1. 29. 01:09

1. CMake 소개

CMake는 소프트웨어 개발에서 프로젝트를 빌드하고 의존성을 관리하는 데 도움을 주는 툴이다. 크로스 플랫폼 지원과 자동 의존성 관리를 통해 복잡한 프로젝트에서도 일관된 빌드 환경을 유지할 수 있다. 프로젝트 빌드 규칙은 CMakeLists.txt 파일에 정의되며, 플랫폼에 맞는 빌드 시스템(Ninja, Make, Visual Studio 등)으로 변환된다.

  • 주요 장점
    • 여러 플랫폼에서 동일한 빌드 스크립트를 사용 가능, 자동 의존성 관리
  • 주요 사용 사례
    • 대규모 프로젝트의 멀티 플랫폼 빌드, 라이브러리 의존성 관리

2. CMake 설치 및 환경 설정

CMake는 Windows, Linux, Docker 등 다양한 플랫폼에서 설치할 수 있으며, 설치 후 PATH 설정을 통해 명령어를 사용할 수 있게 한다.

설치 방법

  • Windows
    • CMake 공식 웹사이트에서 설치 파일을 다운로드하여 설치한다. 설치 중 Add CMake to the system PATH 옵션을 체크하는 것이 편리하다.
  • Linux
    • sudo apt install cmake 명령어로 설치할 수 있으며, Red Hat이나 CentOS에서는 yum을 통해 설치 가능하다. 예를 들어, 최신 버전을 설치하려면 공식 사이트에서 소스 파일을 다운로드하여 빌드할 수 있다.
    • # ./bootstrap && make && sudo make install
  • Docker
    • Docker 이미지를 사용해 격리된 환경에서 CMake를 실행할 수 있다.
    • docker pull kitware/cmake docker run --rm -it kitware/cmake cmake --version

설치 확인

설치가 완료되면 cmake --version을 통해 설치가 정상적으로 완료되었는지 확인한다.


3. CMakeLists.txt 기본 구조와 주요 명령어

CMake의 모든 프로젝트는 CMakeLists.txt 파일을 통해 빌드 설정을 정의한다. 주요 명령어는 아래와 같다.

  • cmake_minimum_required(VERSION 3.10)
    • 프로젝트에 필요한 최소 CMake 버전을 지정한다.
  • project(MyProject)
    • 프로젝트의 이름과 사용 언어를 지정한다.
  • add_executable(MyApp main.cpp)
    • main.cpp 파일로부터 실행 파일 MyApp을 생성한다.
  • target_link_libraries(MyApp MyLibrary)
    • 생성된 타겟 MyApp에 MyLibrary를 연결한다.

기본 예제

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 실행 파일 생성
add_executable(MyApp main.cpp)

# 라이브러리 연결
target_link_libraries(MyApp MyLibrary)

추가 명령어

  • add_library
    • 정적 또는 동적 라이브러리를 생성한다.
  • include_directories
    • 특정 디렉토리를 포함 디렉토리로 추가한다.
  • set

변수를 설정하여 전역이나 로컬 스코프에서 사용할 수 있게 한다.


4. 외부 라이브러리 연결 및 의존성 관리

CMake는 외부 라이브러리를 자동으로 검색하고 추가할 수 있는 find_package, include_directories, target_link_libraries와 같은 명령어를 제공한다. 이를 통해 프로젝트의 의존성을 간편하게 설정하고 관리할 수 있다.

  • find_package(MyLibrary REQUIRED)
    • MyLibrary 라이브러리를 프로젝트에 추가한다.
  • include_directories(${MyLibrary_INCLUDE_DIRS})
    • MyLibrary의 헤더 파일 경로를 추가한다.
  • target_link_libraries(MyApp ${MyLibrary_LIBRARIES})
    • MyLibrary를 MyApp 타겟에 연결한다.

예제

find_package(MyLibrary REQUIRED)
include_directories(${MyLibrary_INCLUDE_DIRS})
target_link_libraries(MyApp ${MyLibrary_LIBRARIES})
이 예제는 CMake가 MyLibrary를 프로젝트 내에서 자동으로 검색하고 필요한 경로를 설정하여 사용할 수 있게 한다.

5. 빌드 시스템 설정 및 하위 프로젝트 관리

대규모 프로젝트에서는 여러 모듈을 하위 디렉토리로 나누어 관리하는 것이 유용하다. add_subdirectory와 aux_source_directory 같은 명령어를 활용해 프로젝트 내 여러 디렉토리를 포함시키고, 빌드 시 자동으로 관리할 수 있다.

  • add_subdirectory(src): src 디렉토리를 하위 디렉토리로 추가하고 해당 디렉토리의 CMakeLists.txt 파일을 빌드에 포함시킨다.
  • aux_source_directory(<dir> <variable>): 지정된 디렉토리의 모든 소스 파일을 변수에 저장한다.

예제

add_subdirectory(src)
add_subdirectory(lib)

# src와 lib 디렉토리 각각에 있는 CMakeLists.txt 파일을 통해 빌드를 수행

6. 고급 기능: 정적 분석, 단위 테스트, 패키지 관리

CMake는 빌드 시스템뿐 아니라 코드 품질 관리, 패키지 관리까지 통합하여 지원한다.

정적 분석

target_compile_options를 사용하여 코드의 정적 분석 옵션을 추가할 수 있다. 예를 들어, 컴파일러 경고를 강화하거나 특정 정적 분석 옵션을 추가하여 코드 품질을 높일 수 있다.

target_compile_options(MyApp PRIVATE -Wall -Wextra -Werror)

단위 테스트

CMake는 Google Test와 같은 단위 테스트 프레임워크와 함께 사용할 수 있다. 테스트 타겟을 정의하고 add_test 명령으로 자동 테스트를 설정할 수 있다.

add_executable(MyTests test.cpp)
target_link_libraries(MyTests gtest gtest_main)
add_test(NAME RunTests COMMAND MyTests)

패키지 관리

패키지 관리에 유용한 find_package와 install 명령어를 사용해 의존성 패키지를 자동으로 설치하고, 컴파일 환경을 구성할 수 있다.

install(TARGETS MyApp DESTINATION bin)
install(FILES config.h DESTINATION include)

7. CMake 활용 예제

CMake 예제를 통해 실전에서 사용법을 익힐 수 있다. 예제는 간단한 C/C++ 프로젝트 설정부터 시작해 Docker와 같은 컨테이너 환경에서 빌드 환경을 테스트하거나, 여러 라이브러리와 실행 파일을 관리하는 대규모 프로젝트를 설정하는 방법까지 포함한다.

기본 프로젝트 설정 예제

  1. 프로젝트 초기화
    • CMakeLists.txt 파일을 생성하고 프로젝트를 정의한다.
  2. 라이브러리 연결
    • 외부 라이브러리를 찾고 빌드에 포함시킨다.
  3. 빌드 및 실행
    • cmake 명령어를 사용해 빌드를 수행하고, 실행 파일을 실행한다.

Docker를 이용한 CMake 빌드 예제

Docker에서 CMake 환경을 설정하면 빌드를 격리하여 실행할 수 있다. Dockerfile을 사용하여 빌드 환경을 설정하고, CMake를 이용해 프로젝트를 빌드하는 예제는 다음과 같다.

FROM ubuntu:latest
RUN apt-get update && apt-get install -y cmake g++
COPY . /project
WORKDIR /project
RUN cmake . && make

참조URL

https://sonseungha.tistory.com/372?category=710904
https://www.tuwlab.com/index.php?mid=ece&page=2&document_srl=27193
https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/How-To-Find-Libraries
https://gist.github.com/luncliff/6e2d4eb7ca29a0afd5b592f72b80cb5c#cmake-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC-lv1
https://github.com/ttroy50/cmake-examples

728x90