catkin_package DEPENDS, CATKIN_DEPENDS 탐구 (I)
Published:
이 포스트를 읽기에 앞서, find_package
를 잘 모르고 있다면 이 포스트를 먼저 읽어보길 권한다.
CMakeList를 작성하다보면 catkin_package
의 DEPENDS
, CATKIN_DEPENDS
가 너무나 헷갈린다. 어쩔 땐 find_package()
에 있는 패키지를 추가해야하고, 어느 패키지는 추가하지 않아도 빌드가 되기 때문이다.
이를 이해하기 위해 catkin_package()
가 왜 쓰이는지 먼저 살펴보자
catkin_package()
It installs the package.xml file, and it generates code for
find_package
andpkg-config
so that other packages can get information about this package. For this purpose the information about include directories, libraries, further dependencies and CMake variables are used.
project(example_package)
...
catkin_package(CATKIN_DEPENDS std_msgs
DEPENDS Boost
INCLUDE_DIRS include
LIBRARIES your_library)
Your
catkin_package()
needs to export all your library build targets so other catkin packages can use them. Supposeyour_library
depends on the ROSstd_msgs
package and on the systemBoost
thread library:
<depend>std_msgs</depend>
<build_export_depend>boost</build_export_depend>
Ref: catkin_package, Building and installing C++ libraries and headers
번역하면, example_package의 정보를 export하기 위한 용도로 catkin_package가 사용 된다고 한다.
예를 들면 catkin_package(DEPENDS Boost)
는 example_package를 빌드하기 위해서 Boost
가 필요함을 다른 패키지에 알려주는 것이다 . 이 점이 find_package
와 목적이 다르다.
find_package()
: 현재example_package
를 빌드할 때 필요한 패키지들을 찾아온다.catkin_package(DEPENDS ... CATKIN_DEPENDS ...)
:example_package
의 의존성이 있는 패키지들의 목록을 export 하기 위함이다. 즉 다른 패키지가 알 수 있게 하기 위함이다.
따라서, 처음 질문인 “find_package()에 포함된 패키지중 어느 패키지가 catkin_package
의 DEPENDS
, CATKIN_DEPENDS
에 추가 되어야 하는가?” 에 대한 답변은
다른 패키지에게, 의존성을 알려주어야하는 패키지들이 추가 되어야 한다고 답변을 할 수 있다.
예제를 통해 좀 더 정확히 이해해보자
예제
catkin workspace를 아래와 같이 bar
, foo
, fred
의 3가지 패키지를 가지도록 구성하였다.
(base) kyuhwanyeon@kyuhwanyeon-MS-7B17:~/personnel/cmake_tutorial$ tree -d
.
└── src
├── bar
│ ├── include
│ └── src
├── foo
│ ├── include
│ └── src
└── fred
├── include
└── src
여기서 의존 관계를
fred –> bar –> foo가 되도록 CMakeList를 작성해보자.
또한 fred –> bar –> foo 순서로 빌드가 될 수 있도록 package.xml 을 작성 해놓자. (이 포스트 참조)
이해를 돕기 위해 먼저 catkin_package의 DEPENDS
와 CATKIN_DEPENDS
를 비워두고 빌드해보겠다.
[fred CMakeList.txt]
cmake_minimum_required(VERSION 3.0.2)
project(fred)
catkin_package(
INCLUDE_DIRS include
LIBRARIES fred
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
add_library(${PROJECT_NAME}
src/fred.cpp
)
fred library 를 만들도록 작성하였다. foo
, boo
로 부터의 dependency 가 없음을 유의하자.
[bar CMakeList.txt]
cmake_minimum_required(VERSION 3.0.2)
project(bar)
find_package(catkin REQUIRED COMPONENTS
fred
)
catkin_package(
INCLUDE_DIRS include
LIBRARIES bar
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
add_library(${PROJECT_NAME}
src/bar.cpp
)
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
bar library를 만들도록 작성하였다. find_package
를 통해 fred
가 필요함을 명시하였고, fred
의 라이브러리 결과물이 catkin_LIBRARIES
에 포함이 되어있을테니까, 이를 사용할 수 있도록 link를 걸어주었다.
[foo CMakeList.txt]
cmake_minimum_required(VERSION 3.0.2)
project(foo)
find_package(catkin REQUIRED COMPONENTS
bar
)
catkin_package(
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
add_executable(${PROJECT_NAME} src/foo.cpp)
target_link_libraries(${PROJECT_NAME}
${catkin_LIBRARIES}
)
foo executable을 만들었다. bar library 를 사용하는 package이므로, find_package 를 통해 bar
를 찾도록 하였다. 또한 foo
패키지를 사용하는 다른 패키지는 없으니까 export 할 필요가 없으니 catkin_package를 비워 두었다.
이제 catkin_make 를 통해 빌드를 해보면 아래와 같은 에러가 나온다.
[ 83%] Building CXX object foo/CMakeFiles/foo.dir/src/foo.cpp.o
In file included from /home/kyuhwanyeon/personnel/cmake_tutorial/src/foo/include/foo.hpp:1:0,
from /home/kyuhwanyeon/personnel/cmake_tutorial/src/foo/src/foo.cpp:1:
/home/kyuhwanyeon/personnel/cmake_tutorial/src/bar/include/bar.hpp:1:10: fatal error: fred.hpp: No such file or directory
#include "fred.hpp"
^~~~~~~~~~
foo package의 foo.cpp를 빌드를 하는 과정에서 bar.hpp를 불러오는데 여기서, fred.hpp를 찾을 수 없다고 나오는 것이다!
이유는 명확하다
foo
는 bar
를 불러왔는데, export된 bar
의 정보에는 fred
의 dependency가 기입 되어 있지 않아서, foo
를 빌드할 때는 이를 모른채로 빌드를 하기 때문에 위와 같은 에러가 나온 것이다.
그럼 해결 방법 또한 명확하다.
bar
의 CMakeList.txt 에 CATKIN_DEPENDS fred
를 추가하는 것이다. 이를 통해, 다른 bar
를 이용하는 다른 패키지들은 “ bar
는 fred
에 의존성이 있구나” 를 알 수가 있다.
따라서 bar
의 CMakeList를 아래와 같이 수정해보자
cmake_minimum_required(VERSION 3.0.2)
project(bar)
find_package(catkin REQUIRED COMPONENTS
fred
)
catkin_package(
INCLUDE_DIRS include
LIBRARIES bar
CATKIN_DEPENDS fred
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
add_library(${PROJECT_NAME}
src/bar.cpp
)
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
CATKIN_DEPENDS fred
만 추가 된것이 다르다.
catkin_make 를 진행하면 정상 빌드가 된다 :)
[ 33%] Built target fred
[ 66%] Built target bar
[100%] Built target foo
Summary
catkin_package(DEPENDS ... CATKIN_DEPENDS ...)
는 현재 패키지의 의존성이 있는 패키지들의 목록을 export 하기 위해 사용된다. 즉 다른 패키지가 이러한 의존성 관계를 알 수 있게 하기 위함이다.