명령어
cmake_minimum_required
# 최소 호환 버전 지정
cmake_minimum_required(VERSION 3.22)
project
# 버전 번호와 설정 파일 추가
project(step_base VERSION 1.1)
project()명령어가 호출되면, CMake는 내부적으로step_base_VERSION_MAJOR와step_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에서 매크로는 함수와 유사하며, 여러 곳에서 호출할 수 있도록 재사용 가능한 코드 조각을 캡슐화하는 데 사용됩니다. 매크로는 인수를 받아들이고 일련의 명령어를 실행할 수 있습니다. 매크로는 macro와 endmacro 키워드를 사용하여 정의됩니다. 예:
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_ 매크로는 실패해도 테스트를 계속할 수 있습니다.