參考資料:
https://zhuanlan.zhihu.com/p/183819313
https://www.guyuehome.com/33759
1、原理
所謂的交叉編譯,其實我們可以從編譯原理上理解這個步驟,C++的編譯大致可以分為預編譯、編譯和鏈接三個步驟,所以我們只要保證預編譯和編譯使用的編譯工具是目標平台的配套工具,最后鏈接的庫文件是目標平台的庫文件,即可保證交叉編譯的正確性。
下面以配置 x86 ubuntu 18.06 ROS melodic 交叉編譯環境為例
2、環境
編譯平台:x86_64 ubuntu 18.04
目標平台:arm ubuntu 18.04
ROS版本:ROS melodic for amd64
CPU架構:編譯環境和運行環境都是64位
3、編譯配置
首先在 目標平台 和 編譯平台 上全部裝好 ubuntu 18.04 和 ROS melodic 的環境並且保證無誤
3.1、在x86上安裝arm的編譯工具鏈
sudo apt install gcc-aarch64-linux-gnu
sudo apt install g++-aarch64-linux-gnu
此工具在后面用於編譯
安裝完成后,可以使用以下兩條指令查看工具版本
aarch64-linux-gnu-gcc --version
aarch64-linux-gnu-g++ --version
3.2、復制ROS庫
將 arm 平台中的 ROS 庫拷貝到 x86 中,替換 x86 的 ROS 庫文件(x86的最好先備份,用於后期),位置在 /opt/ros 目錄下
執行后,該目錄如下:
/opt/ros/melodic/ #這個是arm cpoy過來的/opt/ros/melodic整個目錄
/opt/ros/melodic_bak/ #這個是x86原來的目錄
之所以保留原先的目錄,是因為 x86 的環境還需要使用的
下面這段和交叉編譯無關
這時候,如果再次執行 roscore 會報錯,原因是,現在的 roscore 執行的是 /opt/ros/melodic 目錄下的環境,手動指定成 /opt/ros/melodic_bak/ 即可
source /opt/ros/melodic_bak/setup.bash
如果希望繼續使用 x86 環境下的指令,需要指定 LD_LIBRARY_PATH 參數
export LD_LIBRARY_PATH=/opt/ros/melodic_bak/lib/
3.3、復制庫
將下面三個目錄復制到x86中,這兩個目錄下主要是 linux 平台的一些通用庫
/lib
/usr/lib
/usr/include
/usr/local
路徑任意,比如,本次放在 /home/robot/cross_compile 下,全路徑為:
/home/robot/cross_compile/lib
/home/robot/cross_compile/usr/lib
/home/robot/cross_compile/usr/include
/home/robot/cross_compile/usr/local
該路徑在后面編寫工具鏈配置文件的時候會再用到
3.4、修改ROS編譯鏈配置
編譯文件 /opt/ros/melodic/share/catkin/cmake/tools/rt.cmake
if(NOT (APPLE OR WIN32 OR MINGW OR ANDROID))
修改為
if(NOT (APPLE OR WIN32 OR MINGW OR ANDROID OR UNIX))
3.5、編寫ROS工具鏈配置
#File rostoolchain.cmake
INCLUDE(CMakeForceCompiler)
set(CMAKE_SYSTEM_NAME Linux)
message(STATUS "home path $ENV{HOME}")
set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++)
set(CMAKE_CXX_FLAGS -fpermissive)
set(CMAKE_C_FLAGS -fpermissive)
# specify the cross compiler
#CMAKE_FORCE_C_COMPILER(aarch64-linux-gnu-gcc GNU)
#CMAKE_FORCE_CXX_COMPILER(aarch64-linux-gnu-g++ GNU)
set(CMAKE_FIND_ROOT_PATH /opt/ros/melodic $ENV{HOME}/cross_compile)
set(CMAKE_LIBRARY_PATH
# /opt/ros/melodic/lib/aarch64-linux-gnu
#$ENV{HOME}/cross_compile/opt/ros/melodic/lib
$ENV{HOME}/cross_compile/lib
$ENV{HOME}/cross_compile/usr/lib
$ENV{HOME}/cross_compile/usr/local/lib
$ENV{HOME}/cross_compile/lib/aarch64-linux-gnu
$ENV{HOME}/cross_compile/usr/lib/aarch64-linux-gnu)
set(CMAKE_INCLUDE_PATH
$ENV{HOME}/cross_compile/usr/include
$ENV{HOME}/cross_compile/usr/include/freetype2
$ENV{HOME}/cross_compile/usr/include/aarch64-linux-gnu
$ENV{HOME}/cross_compile/usr/local/include)
set(LD_LIBRARY_PATH
# /opt/ros/melodic/lib/aarch64-linux-gnu
#$ENV{HOME}/cross_compile/opt/ros/melodic/lib
$ENV{HOME}/cross_compile/lib
$ENV{HOME}/cross_compile/usr/lib
$ENV{HOME}/cross_compile/usr/local/lib
$ENV{HOME}/cross_compile/lib/aarch64-linux-gnu
$ENV{HOME}/cross_compile/usr/lib/aarch64-linux-gnu)
message(STATUS "rostoolchain LD_LIBRARY_PATH ${LD_LIBRARY_PATH}")
set(PYTHON_EXECUTABLE /usr/bin/python2.7)
#set(BOOST_ROOT $ENV{HOME}/cross_compile/usr)
#set(PCL_ROOT $ENV{HOME}/cross_compile/usr)
set(PCL_DIR $ENV{HOME}/cross_compile/usr/lib/aarch64-linux-gnu/cmake/pcl)
set(CMAKE_CROSSCOMPILING true)
message("${CMAKE_CROSSCOMPILING}")
# Have to set this one to BOTH, to allow CMake to find rospack
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)#FOR COMPILE TOOL WORKS
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
4、編譯
使用 CMAKE_TOOLCHAIN_FILE 參數指定編譯鏈配置文件,如:
catkin_make -DCMAKE_TOOLCHAIN_FILE=/home/robot/catkin_ws/rostoolchain.cmake
5、錯誤處理
5.1、roscpp 路徑錯誤
修改 /opt/ros/melodic/share/roscpp/cmake/roscppConfig.cmake
set(libraries "roscpp;pthread;/home/robot/cross_compile/usr/lib/aarch64-linux-gnu/libboost_chrono.so;/home/robot/cross_compile/usr/lib/aarch64-linux-gnu/libboost_filesystem.so;/home/robot/cross_compile/usr/lib/aarch64-linux-gnu/libboost_system.so;/home/robot/cross_compile/usr/lib/aarch64-linux-gnu/libboost_signals.so;/home/robot/cross_compile/usr/lib/aarch64-linux-gnu/liblog4cxx.so")
5.2、鏈接過程中庫文件錯誤
具體表現為,默認會從 /usr/lib/aarch64-linux-gnu 目錄和 /lib/aarch64-linux-gnu 目錄下尋找.so文件,實際上,我們需要從 /home/robot/cross_compile/usr/lib/aarch64-linux-gnu 和 /home/robot/cross_compile/lib/aarch64-linux-gnu 下查找,解決方法是建立軟鏈接即可
sudo ln -s /home/robot/cross_compile/lib/aarch64-linux-gnu /lib/aarch64-linux-gnu
sudo ln -s /home/robot/cross_compile/usr/lib/aarch64-linux-gnu /usr/lib/aarch64-linux-gnu
5.3、其他安裝庫錯誤
除了上述庫外,一些后期安裝庫的鏈接錯誤(這些庫可能是apt-get安裝或者源碼安裝),具體表現在平台不匹配或者庫找不到,這時候需要在對應平台的庫copy到交叉編譯環境下的指定目錄(如 /home/robot/cross_compile )下,再統一在編譯鏈文件中統一指定庫路徑即可
示例:
set(Qt5Gui_DIR /cross_compile/usr/lib/aarch64-linux-gnu/cmake/Qt5Gui)