CMake 주요 명령어 정리

명령어

cmake_minimum_required

# 최소 호환 버전 지정
cmake_minimum_required(VERSION 3.22)

project

# 버전 번호와 설정 파일 추가
project(step_base VERSION 1.1) 

project() 명령어가 호출되면, CMake는 내부적으로 step_base_VERSION_MAJORstep_base_VERSION_MINOR 변수를 정의합니다.

add_executable

# 소스 코드 파일을 지정하여 실행 파일 생성
add_executable(exe_file_name xx.c)

set

# C++ 표준을 C11로 지정
set(CMAKE_CXX_STANDARD  11)
set(CMAKE_CXX_STANDARD_REQUIRED  True)

set 명령어를 사용한 사용자 정의 변수

set(MY_VAR "xxxx")

configure_file

configure_file 명령어는 설정 파일을 생성하거나 업데이트합니다.

  • xx.h.in 템플릿 파일을 생성합니다. configure_file()로 전달된 변수는 입력 파일 내용의 @VAR@ 형태의 변수 값을 대체하고 config.h 파일을 출력합니다.
  • configure_file에서 변수는 ${} 문법을 사용하여 참조해야 합니다.
  • @ONLY 인자는 @VAR@ 형태의 변수만 대체하고, $VAR 형태(유닉스 셸 스타일)의 변수는 대체하지 않도록 지정합니다.
// config.h.in
#define MY_VAR @MY_VAR@
set(MY_VAR "Hello, World!") # 사용자 정의 변수
configure_file(config.h.in config.h @ONLY)

target_**

target_* 명령어는 라이브러리나 실행 파일과 같은 대상의 속성과 의존성을 정의하고 관리하는 데 사용됩니다. PRIVATE, INTERFACE, PUBLIC 키워드는 대상 속성의 가시성과 전파 방식을 지정합니다.

  • PRIVATE: 속성(디렉터리 또는 라이브러리)은 대상 자체에만 적용되며, 의존성에 전달되지 않습니다.
  • INTERFACE: 속성은 의존성에만 사용되며, 대상 자체에는 적용되지 않습니다.
  • PUBLIC: 속성은 대상 자체와 의존성 모두에 적용됩니다.

예를 들어, 프로젝트의 하위 디렉터리 라이브러리가 자체적으로는 해당 하위 디렉터리의 헤더 파일을 필요로 하지 않지만, 프로젝트에서 이 라이브러리에 의존하는 대상은 필요로 하는 경우, 하위 디렉터리의 CMakeLists.txt에서 경로를 추가할 때 INTERFACE로 지정할 수 있습니다.

# 헤더 파일 디렉터리를 프로젝트에 추가합니다. project_name 자체만 이 디렉터리를 알아야 합니다.
target_include_directories(project_name PRIVATE ${PROJECT_BINARY_DIR}) 

# 프로젝트에 라이브러리를 링크합니다. project_name 자체와 project_name에 의존하는 대상 모두 mylib 라이브러리에 의존합니다.
target_link_libraries(project_name PUBLIC mylib) 

# MyFunc에 의존하는 대상은 이 하위 디렉터리의 헤더 파일을 사용해야 하지만, MyFunc 자체는 필요하지 않습니다.
add_library(MyFunc func.cc)
target_include_directories(MyFunc INTERFACE $(CMAKE_CURRENT_SOURCE_DIR))
# 컴파일 정의를 추가합니다. 컴파일 시 조건을 제어합니다. 예를 들어 디버그 모드를 활성화하거나, 특정 기능 옵션을 활성화하거나, 다른 플랫폼 호환성 문제를 처리합니다.
target_compile_definitions(target_name
    PUBLIC | PRIVATE | INTERFACE
    definition1 [definition2 ...]
)

option

# 설정 옵션을 추가합니다. 기본값은 ON입니다.
option(OPTION_1 "설명" ON) 
if (OPTION_1)
    # ...
endif()

message

message("경로: ${CMAKE_INSTALL_PREFIX}")  # 정보 출력

add_library

# 사용자 정의 라이브러리 추가
add_library(MyFunc func.cc) 

add_subdirectory

# 컴파일할 하위 디렉터리를 추가합니다. 하위 디렉터리에는 자체 CMakeLists.txt가 있어야 합니다.
add_subdirectory(xx/src) 

add_definitions

# 전처리기 매크로를 추가합니다. CMake 프로젝트의 모든 대상에 영향을 줍니다. target_compile_definitions 사용을 권장합니다.
add_definitions(-DDEFINE_NAME)

install

cmake install은 생성된 대상 파일(실행 파일, 라이브러리 파일, 헤더 파일 등)을 지정된 디렉터리에 설치하는 방법을 지정합니다.

install(TARGETS <target> 
        [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|EXPORTED_TARGETS]
            [DESTINATION <dir>]
            [PERMISSIONS permissions...]
            [CONFIGURATIONS [Debug|Release|...]]
            [COMPONENT <component>]
            [OPTIONAL]
            [EXCLUDE_FROM_ALL]])
  • TARGETS: 설치할 대상을 지정합니다. 실행 파일, 라이브러리 파일 또는 CMake에서 지원하는 다른 대상 유형이 될 수 있습니다.
  • ARCHIVE|LIBRARY|RUNTIME|OBJECTS|EXPORTED_TARGETS: 선택 사항으로, 정적 라이브러리(ARCHIVE), 공유 라이브러리(LIBRARY), 실행 파일(RUNTIME), 오브젝트 파일(OBJECTS) 또는 내보낸 대상(EXPORTED_TARGETS)과 같이 설치할 대상의 유형을 지정합니다.
  • DESTINATION <dir>: 설치 대상 디렉터리를 지정합니다. 절대 경로이거나 CMAKE_INSTALL_PREFIX에 대한 상대 경로일 수 있습니다.
  • PERMISSIONS permissions...: 선택 사항으로, 설치 파일의 권한을 지정합니다.
  • CONFIGURATIONS [Debug|Release|...]: 선택 사항으로, 특정 빌드 구성에서만 설치하도록 제한합니다.
  • COMPONENT <component>: 선택 사항으로, 설치할 구성 요소를 지정합니다. 설치 패키지 내의 논리적 구성을 관리하는 데 사용됩니다.
  • OPTIONAL: 선택 사항으로, 설치 대상이 필수가 아님을 나타냅니다.
  • EXCLUDE_FROM_ALL: 선택 사항으로, 설치 대상을 make all 또는 build 대상에서 제외합니다.
# my_executable이라는 실행 파일을 bin 디렉터리에 설치합니다.
install(TARGETS my_executable
        RUNTIME DESTINATION bin)

# 정적 라이브러리와 헤더 파일을 설치합니다. my_library라는 정적 라이브러리를 lib 디렉터리에 설치하고, my_header.h 헤더 파일을 include 디렉터리에 설치합니다.
install(TARGETS my_library
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin)
install(FILES my_header.h DESTINATION include)

# 공유 라이브러리를 설치하고 권한을 지정합니다. my_shared_library라는 공유 라이브러리를 lib 디렉터리에 설치하고 파일 권한을 읽기 권한으로 설정합니다.
install(TARGETS my_shared_library
        LIBRARY DESTINATION lib
        PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)

# 특정 빌드 구성으로 설치합니다. Release 빌드 구성에서만 my_executable을 설치합니다.
# cmake --install . --config Release
install(TARGETS my_executable
        RUNTIME DESTINATION bin
        CONFIGURATIONS Release)

# 구성 요소 설치: my_library를 lib 및 bin 디렉터리에 설치하고 libraries 구성 요소로 분류합니다.
install(TARGETS my_library
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin
        COMPONENT libraries)
  • CMake는 CMAKE_INSTALL_PREFIX 변수를 사용하여 설치 디렉터리의 루트 경로를 결정합니다. 기본적으로 /usr/local로 설정됩니다.
  • -DCMAKE_INSTALL_PREFIX=/path/to/install을 사용하여 설치 경로를 사용자 정의할 수 있습니다.
  • cmake --install 명령어를 사용하는 경우, --prefix 인수를 통해 설치 접두사를 재정의할 수 있습니다. cmake --install . --prefix "/home/myuser/installdir"
  • 설치를 실행하려면, install() 명령어 구성을 완료한 후 프로젝트의 루트 디렉터리에서 다음 명령어를 실행합니다.
cmake --install .
cmake --install . --config Release
cmake --build . --target install --config Debug
cmake --install . --prefix "/home/myuser/installdir"

cpack

cpack 패키징. 빌드 후 프로그램을 NSIS, ZIP, RPM, TGZ(tar.gz), DEB 등 형식의 설치 패키지로 패키징할 수 있습니다.

include(CPack) # 패키징 활성화

set(CPACK_PACKAGE_NAME "pack_test")
set(CPACK_PACKAGE_VERSION "1.0.0")
set(CPACK_PACKAGE_VENDOR "MyCompany")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyAwesomeSoftware 설명")

 # 다른 생성기에 따라 다른 형식의 설치 패키지 생성
set(CPACK_GENERATOR "ZIP;TGZ") 

set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "sshpass, can-utils") # 의존성 설정
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "관리자 이름 <maintainer@example.com>")

install(TARGETS MyExecutable
        DESTINATION bin)

install(FILES README.md
        DESTINATION doc)

# cpack 명령어를 실행하여 패키징 시작
cpack

macro

CMake에서 매크로는 함수와 유사하며, 여러 곳에서 호출할 수 있도록 재사용 가능한 코드 조각을 캡슐화하는 데 사용됩니다. 매크로는 인수를 받아들이고 일련의 명령어를 실행할 수 있습니다. 매크로는 macroendmacro 키워드를 사용하여 정의됩니다. 예:

macro(print_message message)
    message(STATUS "메시지: ${message}")
endmacro()

# 매크로 사용
print_message("Hello, world!")

string

string은 변수 내의 텍스트를 처리하기 위한 몇 가지 기본적인 문자열 조작 기능을 제공합니다. 일반적인 문자열 조작에는 문자열 연결, 추출, 대체 등이 포함됩니다. 다음은 몇 가지 일반적인 문자열 조작 함수입니다:

  • string(CONCAT varName string1 string2 ...): 여러 문자열을 연결합니다.
  • string(SUBSTRING <string> <begin> <length> <output_variable>): 부분 문자열을 가져옵니다.
  • string(REPLACE <match_string> <replace_string> <input_string> <output_variable>): 문자열에서 일치하는 항목을 대체합니다.
set(myString "Hello, World!")
string(SUBSTRING ${myString} 0 5 mySubString)
message(STATUS "부분 문자열: ${mySubString}")

file

file은 파일 생성, 복사, 삭제, 읽기 등 다양한 파일 작업을 허용합니다. 일반적인 파일 작업 함수는 다음과 같습니다:

  • file(WRITE <filename> <content>...): 내용을 파일에 씁니다.
  • file(READ <filename> <variable> [OFFSET <offset>] [LIMIT <max-in>] [HEX]): 파일 내용을 변수로 읽습니다.
  • file(COPY <files...> DESTINATION <dir> [FILE_PERMISSIONS <permissions...>]): 파일을 지정된 디렉터리로 복사합니다.
  • file(REMOVE <files...>): 파일을 삭제합니다.
file(WRITE myfile.txt "Hello, World!")
file(READ myfile.txt content)
message(STATUS "파일 내용: ${content}")

DEFINED

DEFINED는 변수가 정의되었는지 확인하는 조건 판단 키워드입니다. 일반적으로 if 문의 조건 판단에 사용됩니다. 예:

if(DEFINED myVar)
    message(STATUS "myVar가 정의되었습니다.")
else()
    message(STATUS "myVar가 정의되지 않았습니다.")
endif()

list

list는 CMake에서 목록(배열)을 처리하는 데 사용되는 키워드입니다. CMake에서 목록은 세미콜론으로 구분된 문자열입니다. 일반적인 list 작업은 다음과 같습니다:

  • list(LENGTH <list> <output_variable>): 목록에 있는 요소의 개수를 가져옵니다.
  • list(GET <list> <element_index> [<element_index>...] <output_variable>): 목록에서 지정된 인덱스 위치의 요소를 가져옵니다.
  • list(APPEND <list> [<element>...]): 요소를 목록 끝에 추가합니다.
  • list(REMOVE_ITEM <list> [<value>...]): 목록에서 지정된 요소를 제거합니다.
set(myList "apple;banana;cherry")
list(LENGTH myList len)
message(STATUS "myList 길이: ${len}")

list(GET myList 1 secondElement)
message(STATUS "두 번째 요소: ${secondElement}")

list(APPEND myList "orange")
message(STATUS "업데이트된 목록: ${myList}")

list(REMOVE_ITEM myList "banana")
message(STATUS "제거 후 목록: ${myList}")

find_package

find_package 명령어는 CMake에서 프로젝트에 필요한 외부 종속성을 찾고 구성하는 데 사용됩니다.

  • 형식: find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE] [REQUIRED] [[COMPONENTS] [components...]])
  • <PackageName>: 찾을 패키지의 이름입니다. CMake는 해당 패키지의 Config.cmake 파일을 검색합니다.
  • version: 선택 사항입니다. 필요한 패키지 버전을 지정합니다.
  • EXACT: 선택 사항입니다. 정확한 버전 일치를 요구합니다.
  • QUIET: 선택 사항입니다. 패키지를 찾을 수 없는 경우 경고를 표시하지 않습니다.
  • MODULE: 선택 사항입니다. CMake 모듈 경로에서 .cmake 파일을 강제로 검색합니다.
  • REQUIRED: 선택 사항입니다. 이 패키지가 필수임을 지정합니다. 찾을 수 없으면 CMake는 오류를 발생시키고 구성을 중지합니다.
  • COMPONENTS: 선택 사항입니다. 사용할 패키지의 구성 요소를 지정합니다.
find_package(Boost 1.70 REQUIRED COMPONENTS filesystem system)
if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS})
    add_executable(my_program main.cpp)
    target_link_libraries(my_program ${Boost_LIBRARIES})
endif()

# find_package(Boost 1.70 REQUIRED COMPONENTS filesystem system)는 Boost 버전 1.70 이상을 찾고 filesystem 및 system 구성 요소가 필요함을 나타냅니다.
# Boost를 찾은 경우(Boost_FOUND가 참), Boost 포함 디렉터리(${Boost_INCLUDE_DIRS})를 프로젝트에 추가하고, my_program이라는 실행 파일을 생성한 다음 Boost 라이브러리(${Boost_LIBRARIES})를 링크합니다.

특정 패키지의 찾기 모듈: 일부 패키지는 Config.cmake 파일을 제공하지 않고 CMake의 찾기 모듈(예: FindBoost.cmake)에 의존할 수 있습니다. CMAKE_MODULE_PATH 변수를 설정하여 이러한 모듈을 사용할 수 있습니다:

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
find_package(Boost REQUIRED COMPONENTS filesystem system)
# 여기서 CMAKE_MODULE_PATH를 사용자 정의 찾기 모듈이 포함된 디렉터리로 설정합니다.

시스템의 모든 CMake 모듈 찾기

cmake --help-module-list |grep -E ^Find #

ctest

ctest는 CMake의 테스트 드라이버 도구로, CMake에서 생성된 테스트를 실행하고 관리하는 데 사용됩니다. 테스트를 자동으로 실행하고 테스트 결과에 대한 보고서를 생성할 수 있습니다.

일반적인 옵션 및 인수

  • -R <regex>: 정규식 과 일치하는 테스트만 실행합니다.
  • -E <regex>: 정규식 과 일치하는 테스트를 제외합니다.
  • -j <num>: 테스트를 병렬로 실행할 개수를 지정합니다.
  • -V: 자세한 테스트 출력 정보를 표시합니다.
  • -C <cfg>: 테스트를 실행할 구성(예: Debug 또는 Release)을 지정합니다.
# 모든 테스트 실행:
cd build_directory
ctest
# 이 명령어는 CMake에 의해 생성된 모든 테스트를 실행하고 테스트 실행 결과를 표시합니다.

# 특정 테스트 실행: -R 옵션을 사용하여 특정 정규식과 일치하는 테스트 이름을 지정할 수 있습니다. 예를 들어, 이름에 "test_"가 포함된 테스트를 실행하려면:
ctest -R test_

# 더 많은 정보 표시: -V 옵션을 사용하면 각 테스트의 출력 및 세부 결과를 포함한 자세한 테스트 출력 정보를 표시할 수 있습니다:
ctest -V

# 병렬 테스트 실행: 시스템이 테스트 병렬 실행을 지원하는 경우 -j 옵션을 사용하여 병렬 테스트 수를 지정할 수 있습니다:
ctest -j 4  # 4개 스레드를 사용하여 테스트 병렬 실행
find_package(GTest REQUIRED)

enable_testing()  # 테스트 활성화
add_executable(my_gtest ctest/gtest.cc)
target_link_libraries(my_gtest PRIVATE MyFunc GTest::Main)

# 테스트 등록
add_test(NAME MyGTests COMMAND my_gtest)

ctest  # 테스트 시작

빌드 유형

  • Release:
    • 최적화 컴파일: 일반적으로 프로그램 실행 효율성과 속도를 향상시키기 위해 다양한 컴파일러 최적화 옵션을 활성화합니다.
    • 디버그 정보 제거: 생성된 실행 파일은 파일 크기를 줄이기 위해 디버그 정보를 줄입니다.
    • 어설션 미포함: 일부 라이브러리와 코드는 Debug 모드에서 어설션(assertions)을 포함할 수 있지만, Release 모드에서는 일반적으로 런타임 성능 저하를 방지하기 위해 비활성화됩니다.
  • Debug: 개발 단계에서 사용됩니다. 디버그 정보를 포함하고 최적화를 비활성화하여 디버깅 및 문제 추적을 용이하게 합니다.
  • RelWithDebInfo: Release와 Debug 특성을 결합하여 디버깅 및 개발을 위해 디버그 정보가 포함된 최적화된 코드를 생성합니다.
  • MinSizeRel: 실행 파일의 크기를 최소화하여 산출물의 크기를 최적화합니다.
# 기본 빌드 유형을 Release로 설정
set(CMAKE_BUILD_TYPE "Release")

확장

gtest

Google Test는 테스트 케이스를 정의하고 실행하기 위한 몇 가지 주요 테스트 매크로를 제공합니다.

// test_case_name은 테스트 케이스의 이름이고, test_name은 구체적인 테스트 케이스 이름인 테스트 케이스를 정의합니다.
TEST(test_case_name, test_name):

TEST(MathTest, Addition) {
    // Test body
}
// 테스트 픽스처(Fixture)를 기반으로 하는 테스트 케이스를 정의합니다. 테스트 픽스처를 사용하면 여러 테스트 케이스 간에 초기화 및 정리 코드를 공유할 수 있습니다. test_fixture_name은 테스트 픽스처 클래스의 이름이고, test_name은 구체적인 테스트 케이스 이름입니다.
TEST_F(test_fixture_name, test_name):

class MathTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 초기화 코드
    }

    void TearDown() override {
        // 정리 코드
    }
};

TEST_F(MathTest, Addition) {
    // Test body
}
// 템플릿 유형을 테스트하기 위한 테스트 매크로입니다. test_case_name은 테스트 케이스 이름이고, test_name은 구체적인 테스트 케이스 이름입니다.
TYPED_TEST(test_case_name, test_name) :

template<typename T>
class MathTest : public ::testing::Test {
    // Test body
};

using MyTypes = ::testing::Types<int, float>;
TYPED_TEST_SUITE(MathTest, MyTypes);

TYPED_TEST(MathTest, Addition) {
    // Test body
}
// TYPED_TEST_P(test_case_name, test_name):
// 매개변수화된 테스트 픽스처(Parameterized Fixture)를 테스트하는 데 사용됩니다.
// test_case_name은 테스트 케이스 이름이고, test_name은 구체적인 테스트 케이스 이름입니다. 예:

class MathTest : public ::testing::TestWithParam<int> {
    // Test body
};

INSTANTIATE_TEST_SUITE_P(SimpleValues, MathTest, ::testing::Values(1, 2, 3));

TEST_P(MathTest, Addition) {
    // Test body
}
// 테스트에서 조건을 확인하기 위한 매크로입니다. 예: ASSERT_TRUE, ASSERT_FALSE, EXPECT_EQ, EXPECT_NE, ASSERT_GT, EXPECT_LT 등. 이러한 매크로는 테스트에서 실제 값이 예상 값과 일치하는지 확인하는 데 사용됩니다.

ASSERT_TRUE(expression); // expression이 참이어야 하며, 그렇지 않으면 테스트 실패
ASSERT_FALSE(expression); // expression이 거짓이어야 하며, 그렇지 않으면 테스트 실패
ASSERT_GT(val1, val2); // val1이 val2보다 커야 하며, 그렇지 않으면 테스트 실패
ASSERT_LT(val1, val2); // val1이 val2보다 작아야 하며, 그렇지 않으면 테스트 실패
...

EXPECT_EQ(expected, actual); // 두 값이 같은지 비교
EXPECT_NE(expected, actual); // 두 값이 다른지 비교
EXPECT_LT(val1, val2); // val1이 val2보다 작은지 비교

// ASSERT_ 매크로는 실패 시 테스트를 계속하지 않지만, EXPECT_ 매크로는 실패해도 테스트를 계속할 수 있습니다.

태그: cmake 빌드 컴파일 의존성 관리 CTest

6월 12일 21:28에 게시됨