参考文献:
[1] https://medium.com/@tahsincankose/cross-compiling-ros-project-for-arm-263642b405ac
宿主机平台:虚拟机ubuntu16.04LTS系统
目标运行平台:树莓派4B
目标平台系统:Raspbian Buster with desktop and recommended software
采用的方法:
- 在树莓派平台上编译好ROS kinetic,并拷贝到PC ubuntu16下面(/home/liqiang/work/linux/raspberrypi/lib/);
- 拷贝树莓派系统下的/usr和/lib两个目录拷贝到PC ubuntu16下面(/home/liqiang/work/linux/raspberrypi/lib/);
- 可以查看ROS kinetic的share目录下的cmake的find_package命令所需的配置文件中的内容,比如cv_bridgeConfig.cmake,其中有:
`set(libraries "cv_bridge;/usr/local/lib/libopencv_core.so.3.4.3;/usr/local/lib/libopencv_imgproc.so.3.4.3;/usr/local/lib/libopencv_imgcodecs.so.3.4.3")`
可以看到,其连接的共享库都指向本地目录这都是PC环境下运行的共享库,我们需要替换其中的内容;
4. 修改kinect下所有文件中跟PC环境库和头文件相关的位置到从树莓派4b拷贝过来的目录对应位置:其中(以下指令均在kinect目录下执行)
find . -type f | xargs sed -i 's#/opt/ros/kinetic#${CMAKE_CROSS_COMPILE_PREFIX}#g'
find . -type f | xargs sed -i 's#/usr/lib#${CMAKE_CROSS_COMPILE_PREFIX}/usr/lib#g'
`
find . -type f | xargs sed -i 's#/usr/local/lib#${CMAKE_CROSS_COMPILE_PREFIX}/usr/local/lib#g'
find . -type f | xargs sed -i 's#/usr/local/include#${CMAKE_CROSS_COMPILE_PREFIX}/usr/local/include#g'
find . -type f | xargs sed -i 's#/usr/include#${CMAKE_CROSS_COMPILE_PREFIX}/usr/include#g'
- 配置好交叉编译环境,这里下载自:https://github.com/raspberrypi/tools,使用的是gcc-linaro-arm-linux-gnueabihf-raspbian-x64 (大坑)
- 编写rostoolchain.cmake文件,其内容为,详见参考文献1,
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_LIBRARY_ARCHITECTURE arm-linux-gnueabihf)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
SET(RASPBERRY_ROOT_PATH /home/liqiang/work/linux/raspberrypi/lib)
SET(RASPBERRY_KINETIC_PATH ${RASPBERRY_ROOT_PATH}/opt/ros/kinetic)
SET(CMAKE_FIND_ROOT_PATH ${RASPBERRY_ROOT_PATH} ${CATKIN_DEVEL_PREFIX})
SET(CMAKE_PREFIX_PATH ${RASPBERRY_KINETIC_PATH} ${RASPBERRY_ROOT_PATH}/usr)
# Have to set this one to BOTH, to allow CMake to find rospack
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
#SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot=${RASPBERRY_ROOT_PATH}" CACHE INTERNAL "" FORCE)
#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --sysroot=${RASPBERRY_ROOT_PATH}" CACHE INTERNAL "" FORCE)
#SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} --sysroot=${RASPBERRY_ROOT_PATH}" CACHE INTERNAL "" FORCE)
#SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} --sysroot=${RASPBERRY_ROOT_PATH}" CACHE INTERNAL "" FORCE)
SET(LD_LIBRARY_PATH ${RASPBERRY_KINETIC_PATH}/lib)
include_directories(/home/liqiang/work/linux/raspberrypi/lib/usr/include/arm-linux-gnueabihf)
set(CMAKE_CROSS_COMPILE_PREFIX /home/liqiang/work/linux/raspberrypi/lib)
LINK_DIRECTORIES(${CMAKE_CROSS_COMPILE_PREFIX}/lib/arm-linux-gnueabihf)
- 在catkin工程目录下运行以下指令,进行编译
catkin_make -DCMAKE_TOOLCHAIN_FILE=/home/liqiang/work/mobileRobot/rostoolchain.cmake
备注:得到这样的结果已经奋战了好几天了,离成功不远了。
解决试探:
可以看到库有问题,但究竟谁的库有问题了(交叉编译器的自带的库还是从目标机器拷贝的库),标准c:库交叉编译器自带的为libc-2.13.so,而树莓派的库为libc-2.28.so,标准C++库:通过执行以下指令:
readelf -a libstdc++.so | grep 3.4
比较得知,交叉编译器的c++库只支持到GLIBCXX_3.4.19,而树莓派系统自带的库支持到GLIBCXX_3.4.25,故编译器的库版本较低。从编译错误看出,需要支持到GLIBCXX_3.4.21。
决定用树莓派的库替换交叉编译器的库,结果是连编译都无法完成了,不是连接错误。
看来需要更高版本的交叉编译器了,查看编译器的版本:
arm-linux-gnueabihf-gcc -v
树莓派:gcc version 8.3.0 (Raspbian 8.3.0-6+rpi1)
交叉编译器: gcc version 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650 - Linaro GCC 2014.03)
可以看出,交叉编译器的版本很低,进而需要寻找更高版本的交叉编译器,在错误编译结果之后给出寻找正确交叉编译器的过程:
错误编译结果:
[ 66%] Building CXX object robot_base/bin/CMakeFiles/robot_base.dir/src/Communication.cpp.o
[ 66%] Building CXX object robot_base/bin/CMakeFiles/robot_base.dir/src/main.cpp.o
[100%] Linking CXX executable robot_base
/home/liqiang/work/linux/raspberrypi/lib/usr/lib/arm-linux-gnueabihf/libcrypt.so.1: undefined reference to `__open_nocancel@GLIBC_PRIVATE'
/home/liqiang/work/linux/raspberrypi/lib/opt/ros/kinetic/lib/libtf.so: undefined reference to `VTT for std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >@GLIBCXX_3.4.21'
/home/liqiang/work/linux/raspberrypi/lib/usr/lib/arm-linux-gnueabihf/liblog4cxx.so: undefined reference to `std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_replace_aux(unsigned int, unsigned int, unsigned int, wchar_t)@GLIBCXX_3.4.21'
/home/liqiang/work/linux/raspberrypi/lib/opt/ros/kinetic/lib/libroscpp.so: undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned int, unsigned int, char const*, unsigned int)@GLIBCXX_3.4.21'
/home/liqiang/work/linux/raspberrypi/lib/opt/ros/kinetic/lib/libroscpp.so: undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::find(char const*, unsigned int, unsigned int) const@GLIBCXX_3.4.21'
/home/liqiang/work/linux/raspberrypi/lib/opt/ros/kinetic/lib/libtf.so: undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@GLIBCXX_3.4.21'
/home/liqiang/work/linux/raspberrypi/lib/opt/ros/kinetic/lib/libroscpp.so: undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::rfind(char, unsigned int)

本文详细记录了在Ubuntu16.04上为树莓派4B交叉编译ROSkinetic项目的全过程,包括解决C++库兼容性问题,以及如何选择合适的交叉编译工具链。
最低0.47元/天 解锁文章
549

被折叠的 条评论
为什么被折叠?



