问题
workspace中有多个包A, B, C, D,其中A的编译成功首先需要依赖B的编译成功,但是编译器往往会先编译A,这个时候还没有编译好B,因此就会报错,需要重新进行catkin build一次才能够成功。
可能原因
依赖声明不完整
package.xml
或CMakeLists.txt
里没有把依赖包完整声明为build_depend
/exec_depend
/depend
。- 如果没有正确声明,
catkin
在构建依赖关系时就不知道应该先构建谁。
混合了
find_package()
和手动路径- 有些包直接在
CMakeLists.txt
里硬编码路径,绕过了 Catkin 的依赖机制,导致依赖顺序不正确。
- 有些包直接在
消息定义(.msg/.srv)依赖没有声明
- 生成消息的包如果被使用方没在
package.xml
和CMakeLists.txt
中显式声明message_generation
/message_runtime
相关依赖,就会出现需要多编译几次的情况。
- 生成消息的包如果被使用方没在
解决办法
1. 检查并补全依赖声明
在 package.xml 中:
<build_depend>some_pkg</build_depend>
<exec_depend>some_pkg</exec_depend>
或 ROS 1 推荐的简写:
<depend>some_pkg</depend>
在 CMakeLists.txt 中:
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
some_pkg # 要依赖的包
)
catkin_package(
CATKIN_DEPENDS roscpp rospy std_msgs some_pkg
)
如果是消息类型(msg/srv/action)依赖别的包里的类型,还需要:
add_message_files(...)
generate_messages(
DEPENDENCIES std_msgs some_pkg
)
并在 package.xml
加上:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
<depend>std_msgs</depend>
<depend>some_pkg</depend>
2. 用 catkin build --summarize --interleave-output
检查依赖拓扑
catkin build
会告诉你哪些包失败,是因为缺少头文件/库,这往往就是依赖没声明。
3. 先构建消息依赖的包(分步编译)
如果你一时没法改所有依赖声明,可以先构建消息/核心依赖的包:
catkin build msgs_pkg1 msgs_pkg2
catkin build
但这是临时解决方法,从长远看还是要修正依赖。
4. 清理再全量构建
有时之前的残留会干扰依赖判断:
catkin clean
catkin build
5. 确认不要用 catkin_make
与 catkin build
混用
catkin_make
和 catkin build
的构建缓存 / 目录结构不同,混用可能导致奇怪的顺序问题。
✅ 最根本的办法:
补全 package.xml 和 CMakeLists.txt 中的依赖声明,使得 Catkin 能在一次编译中解析完整依赖关系。
如果希望进一步了解find_package的使用方法和细节,可以参考这篇文章。