catkin_package DEPENDS, CATKIN_DEPENDS 탐구 (II)

Published:

catkin_package DEPENDS, CATKIN_DEPENDS 탐구 (I) 에서 catkin_package의 목적에 대해서 기술했다.

이번 포스트에서는 DEPENDS / CATKIN_DEPENDS 를 사용할 수 없는 예외적인 케이스에 대해 다뤄보려 한다.

find_package 포스트에선 find_package 를 통해 package를 찾는 것 뿐 실직적으로 lib을 추가하고 include 디렉토리를 불러 오지는 않는다고 했다. 따라서 추가적으로 INCLUDE_DIRECTORIES(${yourpkg+INCLUDE_DIRS})TARGET_LINK_LIBRARIES( ${PROJ_NAME} ${yourpkg+LIBRARIES} ) 까지 해야 한다.

예를들어, find_package(Boost REQUIRED)가 있고 작성한 헤더 중 하나에 #include <boost/function.hpp>가 기입되어 있다고 가정해 보자. 이럴 경우 boost pacakge를 link하고 build 하기 위해선, boost 의 include directory 를 include 하고 boost library 를 link 해야한다.

사실, 위와 같은 작업은 catkin_packageDEPENDS를 사용하면 보다 편히 할 수 있다. catkin_package(DEPENDS Boost) 를 하게 되면 ${Boost_LIBRARIES}${yourpkg_LIBRARIES} 에 더하고, ${Boost_INCLUDE_DIRS}${yourpkg_INCLUDE_DIRS}에 더해주는 작업이 같이 이뤄지기 때문이다.

하지만, 위와 같이 간편하게 catkin_packageDEPENDS 를 사용하지 못할때가 있다. cmake 에서 사용되는 네이밍룰 이 적용되지 않는 package에선 사용할 수 없다. (cmake에 사용되는 네이밍 룰을 따르는 변수를 compliant cmake variables 라 부르자. )

cmake에서 include directory 는 package_INCLUDE_DIRS 로 네이밍이 되어야 하고, library는 package_LIBRARIES 로 네이밍이되어야 한다. 안타깝게도, 위와 같은 네이밍 룰이 지켜지지 않을 때가 있다.

예를 들어 PythonLibsOpenGL 가 있다. find_package(PythonLibs REQUIRED)PYTHON_INCLUDE_PATH 를 만들어내고, find_package(OpenGL REQUIRED)OPENGL_INCLUDE_DIR를 만들어 내기 때문이다.

 PythonLibsOpenGL
PrefixPythonLibs -> PYTHONOpenGL->OPENGL
SuffixINCLUDE_DIRS->INCLUDE_DIRINCLUDE_DIRS->INCLUDE_DIR

먼저 Suffix 를 보면 둘 모두 compliant cmake variable인 INCLUDE_DIRS가 아니다. 또한 Prefix를 만들어내는 방식 또한, 보통의 cmake 와 다르다. compliant cmake variable이였다면 PythonLibs, OpenGL 이였을 것이다. 궁금하다면 CMakeLists.txt 에서 message(STATUS ${OPENGL_INCLUDE_DIR}) 을 해보고 message(STATUS ${OpenGL_INCLUDE_DIRS}) 를 해보는 걸 추천한다. Compliant cmake variable인 ${OpenGL_INCLUDE_DIRS} 에선 경로가 출력이 안되고, 오히려 ${OPENGL_INCLUDE_DIR}에서 경로가 출력이 될것이다.

예제 CMakeLists.txt분석

이제 여기까지 이해했다면 아래의 CMakeLists를 보자.

cmake_minimum_required(VERSION 2.8.3)
project(foo)

find_package(Boost REQUIRED
  COMPONENTS
  system
  thread
)

find_package(PythonLibs REQUIRED)
find_package(OpenGL REQUIRED)

find_package(catkin REQUIRED
  COMPONENTS
  rosconsole
  roscpp
)

include_directories(
  include
  ${catkin_INCLUDE_DIRS}
  ${OPENGL_INCLUDE_DIR}
  ${PYTHON_INCLUDE_PATH}
)

catkin_package(
  INCLUDE_DIRS include ${OPENGL_INCLUDE_DIR}
  LIBRARIES foo ${OPENGL_LIBRARIES}
  CATKIN_DEPENDS roscpp
  DEPENDS Boost
)

[Boost package]

Boost Package의 경우 compliant cmake variable을 생산하기 때문에, catkin_packageDEPENDS 를 사용하여 불러왔다. 이를 통해 별다른 고민 없이 library 가 link되고, include 가 include_directories 에 포함 되었을 것이다.

[OpenGL]

위에 설명한대로, OpenGL package는 compliant cmake variable을 생산 하지 않는다. 따라서, DEPENDS 를 사용할 수 없다. 위의 예시처럼 ${OPENGL_INCLUDE_DIR} 을 따로 INCLUDE_DIRS 에 추가 해주어야하고, ${OPENGL_LIBRARIES}LIBRARIES 에 추가해주어야 한다.

[PythonLibs]

PythonLibs또한 compliant cmake variable을 생산하지 않는다. 만약 PythonLibs의 header 파일을 include 하고 싶었다면, $INCLUDE_DIR 을 catkin_package의 INCLUDE_DIRS 에 추가 했어야 했다. 하지만 위와 같이 cmake 를 작성했다는 뜻은 PythonLibs의 header 파일을 include 하지 않을거란 뜻과 같다.

Summary

  • cmake 문법을 준수하는 패키지 일경우 catkin_package 에 DEPENDS 사용
  • cmake 문법을 준수하지 않는 패키지일 경우, catkin_package에 INCLUDE_DIRSLIBRARIES에 각각 패키지에서 출력되는 이름을 변수명을 기입한다.

Reference link


기타 참고할만한 링크