본문 바로가기

프로그램 언어

[CMake] CMake 간단한 설명 + 예제

CMake

CMake란 여러 환경(window , linux 등)에 맞는 build process를 작성한 것으로, CMakeLists.txt에 기술된 내용을 바탕으로 각 확경에 맞는 Makefile생성해 주는 빌드 프로그램이다.

CMake를 통해 Makefile을 만들게 되면, 추가적인 파일이 추가되지 않는 한 Makefile을 수정하지 않고, 자동으로 생성해준다는 장점이 있지만, 단순히 Makefile을 생성해 주는 것이기 때문에 Make를 추가로 해야한다.

이 포스트는 linux 기준으로 설명한다.

 

Install

linux에 CMake가 없을 경우 다음과 같이 설치할 수 있다.

sudo apt install cmake

 

CMakeLists.txt

앞에서 말했듯이 CMake는 CMakeLists.txt에 기술 된 것을 바탕으로 Makefile을 생성하기 때문에 이를 작성해 주어야 한다. 먼저, 작성한 코드의 파일 구조는 다음과 같다.

workspace |-CMakeLists.txt
          |-main.cpp

이때, main.cpp를 build하여 example이라는 실행파일을 만들기 위한 CMakeLists.txt는 다음과 같다.

cmake_minimum_required(VERSION 3.0.1)
project(example)
add_executable(${PROJECT_NAME} main.cpp)

이제 cmake를 사용하는 방법은 다음과 같다.

cmake <CMakeLists.txt가 있는 파일 경로>

그러면 위의 파일구조에서의 cmake 예시는 아래와 같다.

~/workspace$ cmake .

그러면 다음과 같이 파일들이 생성된다.

workspace |-CMakeLists.txt
          |-main.cpp
          |-CMakeCache.txt
          |-cmake_install.cmake
          |-Makefile
          |-CMakeFiles          -| ...

이제 여기서 Make를 실행하면 실행파일인 example이 생성되고, 실행하면 기존 코드가 정상적으로 실행되는 걸 확인 할 수 있다.

 

Functions

cmake_minimum_required(VERSION 3.0.1)

project를 build하기 위해 필요한 최소한의 CMake의 버젼 명시

project(name)

project의 이름을 명시, 이 함수 실행 후 CMake내부  매크로로 ${PROJECT_NAME}으로 project이름을 호출할 수 있다.

add_library(library_name lib.cpp lib.h)

lib.cpp 와 lib.h로 정의된 library를 library_name으로 생성할 때 사용한다. 이때, 생성만 되고 프로젝트의 소스 코드를 빌드할 때는 자동 추가 되지 않으며, 뒤에 target_link_libraries를 통해 빌드에 추가 해 주어야 한다.

include_directories(dir ...)

.cpp파일에서 include의 기본 경로들을 추가해 준다.

add_executable(result src)

Makefile을 작성할 때 gcc -o result src와 같다. result라는 실행 파일을 src를 빌드하여 만드는 걸 명시 한다.

add_dependenciese(target depend1 ... )

target의 빌드 의존성을 추가해 준다.

target_link_libraries(target lib1 ... )

linker가 실행파일을 생성할 때 필요한 target에 대한 libraries를 명시해 준다.

message(msg)

CMake가 실행 될때 msg에 해당하는 문자들을 출력해 준다.

file(GLOB dst <type>)

<type>에는 모든 경로 & 파일을 의미하는 * 또는 특정 확장자를 명시하는 *.cpp 와 같은 구문이 들어갈 수 있으며, 이에 해당하는 파일경로 또는 파일 이름들을 dst에 저장하게 되며, 항목이 여러개일 경우 ;을 통해 구분되어 들어간다.

foreach(src srcs) / endforeach()

여러개의 항목이 정의 되고 ;으로 구분된 srcs를 하나 씩 src에 넣어서 foreach() 와 endforeach()사이의 구문을 반복하게 된다.

if(IS_DIRECTORY src) / endif()

간단한 if 구문에 옵션을 추가한 것으로 src에 오는 문자열이 파일경로를 의미하는지 아닌지 판단해 준다.

add_subdirectory(dir)

CMake를 하는 경로를 추가해 준다. 추가된 경로에 있는 CMakeLists.txt의 내용들도 반영하여 추가적인 Makefile을 생성한다.

 

응용

위의 함수들을 응용하여 CMakeLists.txt를 작성하면 다음과 같다.

cmake_minimum_required(VERSION 3.0.2)
project(robot_core)

add_compile_options(-std=c++11)

file(GLOB FILE_LISTS include/*)
set(INCLUDE_DIR "")
set(LIB_SRCS "")
set(LIB_HEADERS "")
foreach(FILE_LIST ${FILE_LISTS})
  if(IS_DIRECTORY ${FILE_LIST})
    list(APPEND INCLUDE_DIR ${FILE_LIST})
    message("ADD INCLUDE DIRECTORY : ${FILE_LIST}")
    file(GLOB LIB_SRC ${FILE_LIST}/*.cpp )
    list(APPEND LIB_SRCS ${LIB_SRC})
    file(GLOB LIB_HEADER ${FILE_LIST}/*.h )
    list(APPEND LIB_HEADERS ${LIB_HEADER})
  endif()
endforeach()

include_directories(
  include
  ${INCLUDE_DIR}
)

message("LIB_SRCS : ${LIB_SRCS}")
message("LIB_HEADERS : ${LIB_HEADERS}")
add_library(my_lib ${LIB_SRCS} ${LIB_HEADERS})
target_include_directories(my_lib 
PRIVATE include ${INCLUDE_DIR}
)

add_executable(robot_core src/main.cpp)
target_link_libraries(robot_core
   ${catkin_LIBRARIES} my_lib
)

 

이상 포스팅을 마친다.

틀린거나 모르는거 댓글로 알려주세요

'프로그램 언어' 카테고리의 다른 글

[ C / C++ ] make , Makefile  (1) 2021.01.30
[ C / C ++ ] 프로그램하기전 지식  (1) 2021.01.30