ROS로 살펴보는 CMake 작성법 1편

ROS로 살펴보는 CMake 작성법 1편

ROS 패키지를 설치하는 과정과 필요한 파일들을 하나 하나 면밀히 살펴보면 생각보다 다양한 종류의 파일들이 섞여 있습니다. 패키지를 빌드할 때 무심코 사용하던 파일 중 하나인 CMakeLists.txt, 이번 글은 이 CMake와 작성법 대한 내용을 ROS와 함께 다루어보고자 합니다.

그림1

CMake란?

CMake는 빌드 파일을 생성해주는 ‘프로그램’입니다. CMake를 통해서 빌드를 하면 Makefile을 생성하고 이를 make하여 최종적으로 빌드를 하게 되는 것입니다.

이러한 능력은 유닉스 계열인 리눅스, BSD 등의 운영체제뿐만 아니라 윈도우 계열까지도 지원하니 처음 접할 때는 ‘편의성’에 의문을 표할 수 있는 친구이지만, 막상 라이브러리부터 바이너리 하나 하나 내가 수동으로 연결짓는 경험해보시면 CMake의 ‘편의성’을 이해할 수 있을 겁니다.

여기에 ROS는 ROS의 빌드 패키지와 CMake의 빌드 편의성을 활용하여 독특한 빌드시스템을 구축합니다.

catkin_make & colcon build

특정 패키지를 빌드하실 때, ROS1에서는 catkin_make를 ROS2에서는 colcon build라는 명령어를 입력하여 빌드를 했었을 겁니다. 단순히 교육 자료나 Github, 유명 플랫폼에서 다루는 패키지들을 위의 빌드 명령어를 입력하는 것만으로 설치를 간단히 해왔던게 사실은 많은 내용과 배경지식을 담고 있습니다.

처음에 이야기했듯이 ROS에서 패키지를 구성하는 파일 확장자의 종류는 정말 다양합니다.

.launch / .xarco / .urdf / .cpp / .hpp / .c / .h / .py / .xml / .rviz 등등의 파일들이 catkin_make나 colcon build를 통해서 모두 빌드 및 패키지 설치가 완료됩니다. 이 많은 유형의 파일들을 유용하게 관리하기 위해 쓰이는 프로그램이자 도구가 CMake이며, 이는 ROS1과 ROS2를 통틀어 CMakeLists.txt 파일에 패키지를 설치하는데 필요한 내용들을 작성하는 것입니다.

빌드(Build)

ROS2 빌드 명령어를 보다시피 ROS2는 colcon ‘build’입니다. 빌드(build)는 컴파일과 링크로 구분합니다. 컴파일은 여러분이 다운받았거나 또는 여러분이 작성한 C, C++ 코드들을 .o / .obj와 같은 오브젝트 파일 확장자로 변환하는 겁니다. 이를 ‘기계어로 번역’한다고 표현하기도 합니다.

C 언어나 C++ 코드는 그나마 인간이 이해하기 쉽게 표현하도록 사용하는 언어이지만 컴퓨터가 이해할 수 있도록 컴파일을 통해 통역을 한다고 생각하셔도 좋을 것 같습니다.

그리고 ‘링크(Link)’는 오브젝트 파일들을 묶고 라이브러리 파일들(.so/.a와 같은)을 합쳐서 ‘실행 가능한 파일’의 형태로 생성하는 작업입니다.

  • 컴파일(Compile) 👉 기계가 이해할 수 있는 오브젝트(.o/.obj)파일로 변환
  • 링크(Link) 👉 오브젝트 파일 & 라이브러리 파일들을 실행 가능한 파일로 생성

위와 같이 빌드를 하기 위해서 리눅스 계열 환경에서는 CMake를 활용하는 경우가 많습니다. 이에 대한 구체적인 구조는 몇 가지의 패키지를 사용하는 걸로는 파악하기가 힘듭니다. 저도 제한된 환경의 보드 위에서 작업을 하면서 본격적으로 CMake에서 작성된 도구들의 기능을 하나씩 이해하기 시작했습니다.

소스 파일부터 헤더, 라이브러리까지 연결하기 위한 여정을 거치다보면 ROS가 가져가려는 빌드시스템과 이러한 운영체제와 상관없이 빌드라는 개념 이해의 벽을 마주하게 되는 듯 합니다. CMake의 내용과 활용을 좀 더 살펴보도록 하겠습니다.

CMake와 환경변수

ROS에서 일반적인 패키지 설치 과정은 크게 ‘빌드 + 환경변수 설정’으로 이루어집니다. 여기서 셸(Shell)과 커널(Kernel) 개념의 등장으로 CLI 환경인 터미널이 혼합되면서 이해가 어려웠는데 우선 얕은 범위로 접근하여 이야기해보겠습니다.

ROS1에서는 catkin_make라는 명령어로 패키지를 빌드하고 설치된 devel 폴더에서 아래와 같은 명령어를 입력하셨을 겁니다.

source {$설치된 경로}/setup.bash

환경에 따라 .sh / .zsh 등의 확장자를 사용할 것이고, ROS2에서도 마찬가지로 colcon build를 하고 나서 마찬가지로 환경변수 파일을 source 할 겁니다.

ROS1 또는 ROS2 설치 또한 최종적으로 source /opt/ros/${여러분의 ROS 버전}/setup.bash 를 입력하셨을 겁니다. 이를 통해 ROS 설치를 적용하는 것이죠. 그래서 해외에서는 ‘ROS 스크립트(.sh과 같은 파일때문에)’라고 ROS를 지칭하기도 합니다.

운영체제의 개념보다 하나의 프로그램, 툴 정도로 보는 것이죠. 아무튼! 본론으로 돌아와서…

catkin_make는 catkin이라는 빌드 툴, colcon build는 ament_cmake라는 빌드 패키지를 이용하여 빌드합니다. 그래서 package.xml에는 CMake 빌드에 사용할 최소한의 패키지를 따라 설치하도록 하는 것이죠.

그림2

LDS LiDAR의 ROS2 package.xml 내용

그림3

LDS LiDAR의 ROS1 package.xml 내용

CMake는 ‘다양한 운영체제에서 빌드하기 위한 도구’이며, ‘makefile을 생성하여 make 명령어로 빌드할 때 파일 관리를 알아서 해주는 역할’정도는 기억해두는게 좋겠습니다. 우선은 기존의 ROS 빌드 패키지를 사용하지 않고 CMake를 통해 빌드와 환경변수 설정까지 진행해보겠습니다.

cmake & make 명령어를 통한 빌드

지금부터의 내용은 WSL1을 윈도우에서 설치하고 Ubuntu 18.04 LTS로 진행하였습니다. ROS1을 설치하는데 Ubuntu 버전에 맞춰 Melodic을 설정한 환경입니다.

-사양 확인-

  • Window WSL1
  • Ubuntu 18.04 LTS
  • ROS1 Melodic

그림4

ds_ws라는 워크스페이스를 만들고 ~/lds_ws/src/ 경로에서 git clone (melodic ver)을 입력하여 ROS 패키지를 설치한 것이 위의 이미지 상황입니다.

그림5

일반적인 경우처럼 빌드 패키지를 이용한다고 하면, 위의 이미지처럼 lds_ws로 와서 catkin_make를 입력하여 빌드를 할 겁니다. CMake의 특성을 이용해서 본래의 방법대로 보여드린다고 했죠?

~/lds_ws/src/hls_lfcd_lds_driver 경로로 이동해 아래 명령어를 입력하겠습니다.

cmake .

그림6

현재 디렉토리에 있는 CMakeLists.txt를 cmake를 통해 실행해봅니다. 그러면 아래처럼 Makefile 생성을 위한 작업이 이루어집니다.

그림7

아래의 이미지를 보다시피 현재 디렉토리에 cmake 내용에 따라 Makefile을 생성했습니다. 그리고 ROS1에서 패키지 빌드 진행하면 생성하는 익숙한 devel 폴더도 있군요.

그림8

바로 이어서 Makefile을 통해 빌드를 진행해보겠습니다.

make

그림9

‘hlds_laser_publisher’라는 이름으로 실행 파일을 생성하였습니다.

그림10

앞에서 잠깐 언급했던대로 패키지 빌드를 하고 나면? 환경 변수를 설정해주어야 합니다.

그림11

현재 디렉토리에서 빌드를 했으니 위의 이미지처럼 hls_lfcd_lds_driver 디렉토리에 설치된 devel 폴더로 이동하시면 위의 이미지처럼 각종 shell 관련 파일들이 있는 것을 볼 수 있습니다.

그림12

저는 기존의 ROS 사용할 때처럼 setup.bash 파일을 source하도록 하겠습니다. 그럼 rospack list로 패키지 확인할 때 없던 hls_lfcd_lds_driver가 정상적으로 추가된 상황입니다.

그림13그림14

빌드 툴인 catkin_make를 거치지 않았지만 당연하게도 ROS 관련 명령어, 실행은 문제없이 동일하게 사용할 수 있구요.

그림15

rosrun으로 실행

그림16

roslaunch로 실행

Rviz에서 디스플레이도 정상적으로 동작합니다.

그림17

앞에서 계속 이야기한 ‘빌드 + 환경변수’가 좀 더 드라나게끔 본래의 CMake 과정을 구성한 내용입니다. ROS2도 다를 바 없습니다. CMake란 시스템의 매커니즘을 인지하고 있다면, ROS에서 어떠한 활용을 하고 있는지 대강 흐름을 느낄 수 있을 겁니다. ROS가 C++로 작성되는만큼 플랫폼의 변화에 따라 이 흐름을 인지하고 있어야 다양한 상황에서도 흔들리지 않고 대응할 수 있을 겁니다.


CMake와 셸(Shell)은 유닉스 운영체제 계열에서 어떤 작용을 하는지, catkin_make나 colcon build라는 간단한 명령어 입력의 편의로 인해 핵심을 놓치고 있었습니다.

다음글에서부터는 본격적으로 ROS 빌드 틀과 함께 CMakeLists.txt 안의 내용들을 살펴보면서, cmake 관련 명령어들을 ROS 설치까지 어떠한 흐름을 따르는지 정리를 해보도록 하겠습니다. 부족하지만 참고에 도움이 되길 바라며, 잘못된 사항은 피드백 부탁드리겠습니다. 감사합니다.

참고하면 좋은 사이트 목록

👉CMake 공식 사이트

👉박동하님의 CMake할때 쪼오오금 도움이 되는 문서