4 분 소요

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)

태그:

카테고리:

업데이트: