ROS2交叉编译aarch64和x86循环依赖的问题
发布时间:2026-05-29 17:30:27.988 文章来源:AiSoftCloud 浏览次数:3 下载次数:1 

问题现象

近期在编译一个Ros2的包(jazzy)时,出现交叉编译一直无法编译通过的问题,但是在非交叉编译环境能正常编译和运行,报错如下:

错误信息

上图错误信息主要显示:
1、在编译elevation_map_publisher_node这个节点的时候,要链接libbuiltin_interfacesrosidl_generator_c.so
2、这个库在交叉编译工具链中存在,并已经被编译器找到(dir 0 is [/opt/sysroot/opt/ros/jazzy/lib]),该路径为交叉编译目录(aarch64)
3、但是提示(dir 4 must precede it due to runtime library [libuiltin_interfacesrosidl_generator_c.so]),意思是dir 的路径必须要在运行时库libuiltin_interfacesrosidl_generator_c.so之前链接
4、dir 4(/opt/ros/jazzy/lib)是主机环境目录(x86_64),但是提示dir 0必须在运行时库libnav_msgsrosidl_generator_py.so之前链接
5、/usr/lib/gcc-cross/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/bin/ld: /opt/ros/jazzy/lib/libbuiltin_interfacesrosidl_generator_c.so: error adding symbols: file in wrong format,显示libbuiltin_interfacesrosidl_generator_c.so文件格式错误

核心报错有两个:
1、同时链接到了交叉编译环境(aarch64)和主机环境(x86),并存在循环依赖的问题,导致编译器无法确定到底要链接哪个库,编译报错
2、链接libbuiltin_interfacesrosidl_generator_c.so的时候,链接到了/opt/ros/jazzy/lib/libbuiltin_interfacesrosidl_generator_c.so路径,该文件路径是x86_64的环境,应该链接到aarch64的环境,导致报库文件格式不对的错误。

求助cursor,回答如下:

问题排查

1、检查CMakeLists.txt文件
首先怀疑是Ros2包CMakeLists.txt的问题,可能哪里依赖不对,但是检查后没发现任何异常,这是一个比较简单常见写法的CMakeLists.txt:

  1. cmake_minimum_required(VERSION 3.10)
  2. project(elevation_map_publisher)
  3. # ROS 2 jazzy 推荐使用 C++17
  4. if(NOT CMAKE_CXX_STANDARD)
  5. set(CMAKE_CXX_STANDARD 17)
  6. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  7. endif()
  8. if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  9. add_compile_options(-Wall -Wextra -Wpedantic -O2)
  10. endif()
  11. find_package(ament_cmake REQUIRED)
  12. find_package(rclcpp REQUIRED)
  13. find_package(std_msgs REQUIRED)
  14. find_package(sensor_msgs REQUIRED)
  15. find_package(geometry_msgs REQUIRED)
  16. find_package(nav_msgs REQUIRED)
  17. find_package(tf2 REQUIRED)
  18. find_package(tf2_ros REQUIRED)
  19. find_package(tf2_eigen REQUIRED)
  20. find_package(tf2_geometry_msgs REQUIRED)
  21. find_package(grid_map_core REQUIRED)
  22. find_package(grid_map_ros REQUIRED)
  23. find_package(grid_map_msgs REQUIRED)
  24. find_package(pcl_ros REQUIRED)
  25. find_package(pcl_conversions REQUIRED)
  26. find_package(PCL REQUIRED COMPONENTS common io filters)
  27. find_package(Eigen3 REQUIRED)
  28. include_directories(
  29. include
  30. ${EIGEN3_INCLUDE_DIRS}
  31. ${PCL_INCLUDE_DIRS}
  32. )
  33. add_executable(elevation_map_publisher_node
  34. src/MapCropper.cpp
  35. src/ElevationMapNode.cpp
  36. src/elevation_map_node_main.cpp
  37. )
  38. ament_target_dependencies(elevation_map_publisher_node
  39. rclcpp
  40. std_msgs
  41. sensor_msgs
  42. geometry_msgs
  43. nav_msgs
  44. tf2
  45. tf2_ros
  46. tf2_eigen
  47. tf2_geometry_msgs
  48. grid_map_core
  49. grid_map_ros
  50. grid_map_msgs
  51. pcl_ros
  52. pcl_conversions
  53. )
  54. target_link_libraries(elevation_map_publisher_node
  55. ${PCL_LIBRARIES}
  56. Eigen3::Eigen
  57. )
  58. install(TARGETS elevation_map_publisher_node
  59. DESTINATION lib/${PROJECT_NAME}
  60. )
  61. install(DIRECTORY launch config rviz
  62. DESTINATION share/${PROJECT_NAME}
  63. )
  64. install(DIRECTORY include/
  65. DESTINATION include/
  66. )
  67. if(BUILD_TESTING)
  68. find_package(ament_lint_auto REQUIRED)
  69. ament_lint_auto_find_test_dependencies()
  70. endif()
  71. ament_package()

2、检查交叉编译配置
交叉环境的配置文件已经使用过很长时间,之前从来没有出现过类似问题,相关设置也是标准设置:

  1. # Copyright (c) 2018, ARM Limited.
  2. # SPDX-License-Identifier: Apache-2.0
  3. set(CMAKE_SYSTEM_NAME Linux)
  4. set(CMAKE_SYSTEM_VERSION 1)
  5. set(CMAKE_SYSTEM_PROCESSOR aarch64)
  6. # Specify the cross compiler
  7. set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc)
  8. set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++)
  9. set(CMAKE_SYSROOT /opt/sysroot)
  10. set(CMAKE_FIND_ROOT_PATH /opt/sysroot /opt/sysroot/opt/ros/jazzy)
  11. set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
  12. set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
  13. set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
  14. set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

在交叉编译配置文件中强制设置rosidl_typesupport_c的查找目录为交叉编译环境目录(已经确认头文件和库文件都存在):

  1. set(rosidl_typesupport_c_DIR ${CMAKE_SYSROOT}/opt/ros/jazzy/share/rosidl_typesupport_c/cmake CACHE PATH "" FORCE)
  2. set(rosidl_typesupport_c_LIB ${CMAKE_SYSROOT}/opt/ros/jazzy/lib)

重新编译依然报相同错误。
3、修改编译脚本
怀疑是编译脚本中的环境设置问题(主要是AMENT_PREFIX_PATH和CMAKE_PREFIX_PATH环境便来那个),导致同时链接到了交叉编译目录和主机目录,尝试修改:
修改前:

  1. source /opt/ros/jazzy/local_setup.bash
  2. colcon build \
  3. --cmake-args -DCMAKE_TOOLCHAIN_FILE=/opt/sysroot/toolchain_aarch64.cmake

修改脚本,把AMENT_PREFIX_PATH等环境变量都unset掉,然后强制设置AMENT_PREFIX_PATH指向交叉编译目录,并增加环境变量的打印:
修改后:

  1. source /opt/ros/jazzy/local_setup.bash
  2. unset AMENT_PREFIX_PATH
  3. unset CMAKE_PREFIX_PATH
  4. unset LD_LIBRARY_PATH
  5. unset ROS_DISTRO
  6. unset COLCON_PREFIX_PATH
  7. # 强制设置AMENT_PREFIX_PATH指向交叉编译目录
  8. export AMENT_PREFIX_PATH=/opt/sysroot/opt/ros/jazzy
  9. # 打印AMENT_PREFIX_PATH
  10. env | grep AMENT_
  11. source /opt/sysroot/opt/ros/jazzy/setup.bash
  12. # 打印AMENT_PREFIX_PATH
  13. env | grep AMENT_
  14. # 清空后必须为空!
  15. echo "====================================="
  16. echo "AMENT_PREFIX_PATH=$AMENT_PREFIX_PATH"
  17. echo "CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH"
  18. echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
  19. echo "====================================="
  20. colcon build \
  21. --cmake-args -DCMAKE_TOOLCHAIN_FILE=/opt/sysroot/toolchain_aarch64.cmake
  22. env | grep AMENT_

修改完后重新编译,依然报错。
4、继续求助cursor:
cursor给出了几个疑点,其中这个疑点最可疑:

大致意思是编译中有Ros包在它自己的*Config.cmake 文件中导出了它自己的绝对路径的库目录(/opt/ros/jazzy/lib/…),并给出了查看方法:

  1. grep -rln "/opt/ros/jazzy/lib" /opt/sysroot/opt/ros/jazzy/share 2>/dev/null | head -20

搜索了一下,果然有两个文件中包含绝对路径:

  1. /opt/sysroot/opt/ros/jazzy/share/nav2_costmap_2d/cmake/export_nav2_costmap_2dExport.cmake
  2. /opt/sysroot/opt/ros/jazzy/share/pcl_ros/cmake/export_pcl_rosExport.cmake

对应的两个包分别是pcl_ros和nav2_constmap_2d,这两个包都是使用apt直接安装的。
看文件内容:
头文件目录固定指向了/usr/include和/opt/ros/jazzy/include,库文件目录固定指向了/usr/lib和/opt/ros/jazzy/lib:

解决方法

找到了问题所在,解决方法很简单,将上面两个Config.cmake中的路径指向修改为交叉编译路径:

  1. cd /opt/sysroot/opt/ros/jazzy/share/pcl_ros/cmake
  2. sudo cp export_pcl_rosExport.cmake export_pcl_rosExport.cmake.bk
  3. sudo sed -i "s|/usr/include|/opt/sysroot/usr/include|g" export_pcl_rosExport.cmake
  4. sudo sed -i "s|/usr/lib|/opt/sysroot/usr/lib|g" export_pcl_rosExport.cmake
  5. sudo sed -i "s|/opt/ros/jazzy|/opt/sysroot/opt/ros/jazzy|g" export_pcl_rosExport.cmake
  6. cd /opt/sysroot/opt/ros/jazzy/share/nav2_costmap_2d/cmake
  7. sudo cp export_nav2_costmap_2dExport.cmake export_nav2_costmap_2dExport.cmake.bk
  8. sudo sed -i "s|/usr/include|/opt/sysroot/usr/include|g" export_nav2_costmap_2dExport.cmake
  9. sudo sed -i "s|/usr/lib|/opt/sysroot/usr/lib|g" export_nav2_costmap_2dExport.cmake
  10. sudo sed -i "s|/opt/ros/jazzy|/opt/sysroot/opt/ros/jazzy|g" export_nav2_costmap_2dExport.cmake

重新编译,OK,在此感谢cursor的强大!

更多文章可关注公众号
aisoftcloud