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)
패키지간 순환 참조가 이루어져서 빌드를 진행할 수 없다는 내용이다. 즉 boo
가 foo
에 의존성을 걸고 foo
가 boo
에 의존성이 있으니 서로 물고 물리는 관계라 빌드를 할 수가 없음을 알수 있다.
이번엔 처음에 추가했었던 foo
package의 <build_depend>bar</build_depend>
를 지우고 다시 빌드를 해보았다.
그러면 예상 되는 결과는 bar
가 foo
에 의존성이 있으니, 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