package.xml 의 build_depend 탐구

Published:

package.xml 의 build_depend 탐구

package.xml 는 catkin workspace의 중요 구성요소 중 하나이다.

오늘은 package.xml 의 항목 중 build_depend 가 과연 빌드 순서에 영향을 주는지가 궁금해져 이 부분을 직접 테스트해보았다.

테스트를 하기 위해 package bar, package foo 를 생성하였다.

package foo 의 package.xml 에 <build_depend>bar</build_depend> 를 추가하여 아래와 같이 수정한뒤 catkin_make 를 진행해보았다.

<?xml version="1.0"?>
<package format="2">
  <name>foo</name>
  <version>0.0.0</version>
  <description>The foo package</description>
  <maintainer email="kyuhwanyeon@todo.todo">kyuhwanyeon</maintainer>
  <license>TODO</license>
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>bar</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  <export>
  </export>
</package>

그 결과 터미널에서 topological order 를 관찰할 수 있었다.

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~  traversing 2 packages in topological order:
-- ~~  - bar
-- ~~  - foo
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'bar'
-- ==> add_subdirectory(bar)
-- +++ processing catkin package: 'foo'
-- ==> add_subdirectory(foo)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/kyuhwanyeon/personnel/cmake_tutorial/build
####
#### Running command: "make -j8 -l8" in "/home/kyuhwanyeon/personnel/cmake_tutorial/build"
####
Scanning dependencies of target bar
Scanning dependencies of target foo
[ 50%] Building CXX object foo/CMakeFiles/foo.dir/src/foo.cpp.o
[ 50%] Building CXX object bar/CMakeFiles/bar.dir/src/bar.cpp.o
[100%] Linking CXX shared library /home/kyuhwanyeon/personnel/cmake_tutorial/devel/lib/libbar.so
[100%] Linking CXX executable /home/kyuhwanyeon/personnel/cmake_tutorial/devel/lib/foo/foo
[100%] Built target bar
[100%] Built target foo

위 결과를 보면, bar package가 먼저 생성이 됨을 관찰할 수 있다. 이 뜻은 foo package에서 build depend로 bar package를 가지고 있기 때문이다.

이번엔 bar 패키지의 package.xml에 <build_depend>foo</build_depend> 을 추가해서 아래와 같이 수정했다.

<?xml version="1.0"?>
<package format="2">
  <name>bar</name>
  <version>0.0.0</version>
  <description>The bar package</description>
  <maintainer email="kyuhwanyeon@todo.todo">kyuhwanyeon</maintainer>
  <license>TODO</license>
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>foo</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  <export>
  </export>
</package>

catkin_make를 진행했더니 아래의 에러가 나온다.

CMake Error at /home/kyuhwanyeon/personnel/cmake_tutorial/build/catkin_generated/order_packages.cmake:7 (message):
  Circular dependency in subset of packages:

  bar, foo
Call Stack (most recent call first):
  /opt/ros/melodic/share/catkin/cmake/catkin_workspace.cmake:42 (include)
  CMakeLists.txt:69 (catkin_workspace)

패키지간 순환 참조가 이루어져서 빌드를 진행할 수 없다는 내용이다. 즉 boofoo 에 의존성을 걸고 fooboo에 의존성이 있으니 서로 물고 물리는 관계라 빌드를 할 수가 없음을 알수 있다.

이번엔 처음에 추가했었던 foo package의 <build_depend>bar</build_depend> 를 지우고 다시 빌드를 해보았다.

그러면 예상 되는 결과는 barfoo 에 의존성이 있으니, foo가 먼저 빌드가 되고 bar가 빌드가 될것이라 추측할 수 있다.

catkin_make의 결과는

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~  traversing 2 packages in topological order:
-- ~~  - foo
-- ~~  - bar
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'foo'
-- ==> add_subdirectory(foo)
-- +++ processing catkin package: 'bar'
-- ==> add_subdirectory(bar)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/kyuhwanyeon/personnel/cmake_tutorial/build
####
#### Running command: "make -j8 -l8" in "/home/kyuhwanyeon/personnel/cmake_tutorial/build"
####
Scanning dependencies of target foo
Scanning dependencies of target bar
[ 25%] Building CXX object foo/CMakeFiles/foo.dir/src/foo.cpp.o
[ 50%] Building CXX object bar/CMakeFiles/bar.dir/src/bar.cpp.o
[ 75%] Linking CXX shared library /home/kyuhwanyeon/personnel/cmake_tutorial/devel/lib/libbar.so
[100%] Linking CXX executable /home/kyuhwanyeon/personnel/cmake_tutorial/devel/lib/foo/foo
[100%] Built target bar
[100%] Built target foo

위의 결과처럼 foo가 먼저 빌드가 됨을 관찰할 수 있다 :)

Summary

  • package.xml 엔 패키지간 의존성이 기입되어있다.
  • bar package의 package.xml 에 <build_depend> foo <build_depend> 가 기입되어 있다는 뜻은, bar보다 foo 가 먼저 빌드가 되길 원한다는 뜻이다. 즉 <build_depend>를 통해 빌드시 topological order를 표현 해줄 수 있다.
  • 관련 ROS answer link