CMake - 3 (Variable, Option)
1. CMakeLists 작성때 변수를 추가하고, 다양한 옵션을 적용할 수 있다.
본 페이지에서는 CMakeLists에서 사용하는 변수 작성 방법과 옵션 적용 방법에 대해서 알아보자.
1.1 예제 1) Variable 및 Option 적용
CMake - 1 (Basic) 에 사용했던 예제 2.3 코드를 기반으로 작성하였다.
main.cpp
1 2 3 4 5 6 #include <iostream> #include "header1.h" void main(int argc, char* argv[]) { std::cout << "Hello World" << std::endl; source1_function(); }
source1.cpp에 source1_function()
을 작성하였다.
source1.cpp
1 2 3 void source1_function() { std::cout << "source1 function call" << std::endl; }
header1.h에 source1_function()
을 선언하였다.
header1.h
1 void source1_function();
전체 코드 트리는 아래와 같다.
code tree
1 2 3 4 5 6 7 my_project/ ├── CMakeLists.txt │── include/header.h ├── src/ │ ├── source1.cpp │ ├── main.cpp └── build/
CMakeLists는 다음과 같은 형태로 작성할 수 있다.
CMakeLists
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 # Required CMake version cmake_minimum_required(VERSION 3.0.0) # Project name # Language C CXX to support both C and C++ files project(hello_world VERSION 3.0.0 LANGUAGES C CXX) ########################################################### # Set the CMake build type set(EXECUTABLE_NAME Executable) # Executable name set(LIBRARY_NAME Library) # Library name set(CMAKE_CXX_STANDARD 17) # C++ standard set(CMAKE_CXX_STANDARD_REQUIRED ON) # C++ standard required set(CMAKE_CXX_EXTENSIONS OFF) # 표준 C++만 사용 ########################################################### # 1. Define variable and print set(bool_variable1 True) # custom variable set(int_variable1 3) # custom variable set(string_variable1 "string variable1") # custom variable message(STATUS "bool_variable1 is :"${bool_variable1}) message(STATUS "int_variable1 is :"${int_variable1}) message(STATUS "string_variable1 is :"${string_variable1}) option(option1 "This is custom option1" True) message(STATUS "This is custom option1:"${option1}) # print CMake variables message(STATUS "System Name: ${CMAKE_SYSTEM_NAME}") message(STATUS "System Version: ${CMAKE_SYSTEM_VERSION}") message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}") message(STATUS "Install Directory: ${CMAKE_INSTALL_PREFIX}") message(STATUS "CMAKE_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}") # 2.If,elseif else statement # 2.1 Check OS and print it according to ${CMAKE_SYSTEM_NAME} if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") message("Windows!") elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") message("Linux!") else() message("unknown!") endif() # 2.2 Check OS and print it according to WIN32 and LINUX if(WIN32) message("Windows!!!") elseif(LINUX) message("Linux!!!") else() message("unknown!!!") endif() # 2.3 Check option1 and print it if(option1) message("Option 1 is true") else() message("Option 1 is false") endif() # 3. Build configuration options # 3.1 전역적인 설정 방법. 동적 라이브러리로 설정 # set(BUILD_SHARED_LIBS true) # true: shared, false: static. 전역적인 설정 # add_library(${LIBRARY_NAME} src/source1.cpp) # 3.2 전역적인 설정 방법. 정적 라이브리러리로 설정 # set(BUILD_STATIC_LIBS true) # true: static, false: shared. 전역적인 설정 # add_library(${LIBRARY_NAME} src/source1.cpp) # 3.3 타겟별 설정 방법 add_library(${LIBRARY_NAME}_static STATIC src/source1.cpp) # 명시적으로 정적 라이브러리 설정 add_library(${LIBRARY_NAME}_shared SHARED src/source1.cpp) # 명시적으로 동적 라이브러리 설정 # 4. make executable file add_executable(${EXECUTABLE_NAME} src/main.cpp) # 5. include directories target_include_directories(${EXECUTABLE_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) # 6. link library target_link_libraries(${EXECUTABLE_NAME} ${LIBRARY_NAME}_static) # 정적 라이브러리로 링크 # target_link_libraries(${EXECUTABLE_NAME} ${LIBRARY_NAME}_shared) # 동적 라이브러리로 링크 # 7. install # install 명령어를 통해 라이브러리와 실행파일을 설치할 수 있음 # cmake 빌드 후, 터미널에 cmake --install build --config debug/release 명령어를 수행해야 함 install(TARGETS ${LIBRARY_NAME}_static DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/install_test) install(TARGETS ${LIBRARY_NAME}_shared DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/install_test) install(TARGETS ${EXECUTABLE_NAME} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/install_test)
작성한 hello_world 프로젝트를 빌드하기 위해서 터미널에 아래 명령어를 입력해야 한다.
1
cmake --build .
옵션을 바꾸고 빌드를 하려면 터미널에 아래 명령어를 입력해야 한다. 참고로, cmake -Doptopon1=FALSE
는 CmakeCache.txt 파일 내용을 변경하는 명령어다.
1
2
cmake -Doption1=FALSE
cmake --build .
2. CMakeLists의 다양한 문법
CMakeLists에 작성할 수 있는 문법은 정말 다양하다. 기본적인 것들을 정리해 보자
2.1 set
set()
는 변수를 정의할 때 사용된다. 사용자 정의 변수뿐만 아니라 CMake에서 제공하는 내장 변수들도 설정할 수 있다.
1
2
3
set(MY_VARIABLE "hello") # 문자열 변수 설정
set(MY_NUMBER 42) # 숫자 변수 설정
set(CMAKE_CXX_STANDARD 17) # 내장 변수 설정 (C++17 사용)
2.2 message
message()
는 CMake 실행 시 메시지를 출력하는 데 사용된다. 로그 용도로 유용하며, 디버깅 시 많이 사용된다.
1
2
3
4
message("이 메시지는 항상 출력됩니다.")
message(STATUS "상태 메시지입니다.")
message(WARNING "경고 메시지입니다.")
message(FATAL_ERROR "에러 발생 후 빌드 중단")
2.4 option
option()
은 사용자로부터 ON/OFF 형태의 설정을 받을 수 있게 한다. 커맨드라인에서 설정도 가능하다.
ex) custom library 적용여부 확인 방법
USE_MYMATH 라는 사용자 정의라이브러리를 사용할지 여부를 option 기능을 통해 사용해보자.
1
2
3
4
5
6
7
8
...
option(USE_MYMATH "사용자 정의 수학 라이브러리를 사용할지 여부" ON)
...
if(USE_MYMATH)
message(STATUS "사용자 정의 수학 라이브러리를 사용합니다.")
else()
message(STATUS "기본 수학 라이브러리를 사용합니다.")
endif()
1
> cmake -DUSE_MYMATH=OFF ..
2.5 조건문 (if, elseif, else)
if
, elseif
, else
통해 다양한 분기 처리를 할 수 있다.
ex) OS에 따라 분기하는 방법
1
2
3
4
5
6
7
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
message("Windows!")
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
message("Linux!")
else()
message("unknown!")
endif()
또는, 더 간결하게 매크로를 사용할 수도 있다.
1
2
3
4
5
if(WIN32)
message("Windows 시스템입니다.")
elseif(UNIX)
message("Linux 또는 Unix 시스템입니다.")
endif()
2.6 BUILD_SATIC_LIBS, BUILD_SHARED_LIBS
CMake에서 add_library() 명령을 사용할 때, 라이브러리 종류(STATIC / SHARED)를 명시하지 않으면 SATIC 으로 빌드 된다.
그런데, 전역적으로 라이브러리를 어떤 종류로 빌드할지 BUILD_STATIC_LIBS
, BUILD_SHARED_LIBS
기능을 통해 설정할 수 있다.
ex) static으로 설정
1
2
set(BUILD_STATIC_LIBS true) # true: static, false: shared
add_library(${LIBRARY_NAME} src/source1.cpp)
또는 add_library에 static으로 명시적으로 설정할 수 있다.
1
add_library(${LIBRARY_NAME} STATIC src/lib.cpp)
ex) shared로 설정
1
2
set(BUILD_SHARED_LIBS true) # true: shared, false: static
add_library(${LIBRARY_NAME} src/source1.cpp)
또는 add_library에 shared로 명시적으로 설정할 수 있다.
1
add_library(${LIBRARY_NAME} SHARED src/lib.cpp)
2.8 install
install()
은 빌드된 라이브러리, 실행 파일, 헤더 파일 등을 지정된 디렉토리로 복사(설치)하는 데 사용된다. 패키징, 배포, 시스템 설치 시 중요한 역할을 한다.
install을 수행하기 위해서는 다음과 같이 bash에 명령어를 입력해야 한다.
--config
뒤에는 cmake --build
모드에 따라 --config debug
또는 --config release
를 입력한다.
1
2
cmake --build .
cmake --install build --config debug
예제를 통해 ~/build/install_test 폴더안에 라이브러리, 실행파일, 헤더파일을 설치해 보자.
ex) 라이브러리, 실행파일 설치방법
1
2
3
4
5
6
7
8
9
10
11
# 정적 라이브러리 설치
install(TARGETS MyLibrary_static
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/install_test)
# 공유 라이브러리 설치
install(TARGETS MyLibrary_shared
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/install_test)
# 실행 파일 설치
install(TARGETS MyExecutable
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/install_test)
ex) 헤더파일 설치 방법
1
install(FILES include/header1.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/install_test/include)