The x86 architecture uses docker to compile arm64 applications


The x86 architecture realizes the compilation of multi-platform system code, and there are many ways to implement it:

  1. Cross-compilation: toolchain [New third-party libraries are not easy to handle]
  2. The way to isolate the mount [slow, the file system will be disturbed]
    3. QEMU or other emulators to actually run docker [recommended]

1. Cross compilation: toolchain

https://github.com/dockcross/dockcross.git

toolchain-aarch64.cmake

# DO NOT EDIT THIS FILE
#
# To set up cross-compilation, create the file
# $(ROS_ROOT)/rostoolchain.cmake.  It gets read first, prior to
# any of cmake's system tests.

#############################################################
#
# An example for using the gumstix arm-linux toolchain is below.
# Copy these lines to $(ROS_ROOT)/rostoolchain.cmake to try them out.
#
#set(CMAKE_SYSTEM_NAME Linux)
#set(CMAKE_C_COMPILER /opt/arm-linux/bin/arm-linux-gcc)
#set(CMAKE_CXX_COMPILER /opt/arm-linux/bin/arm-linux-g++)
#set(CMAKE_FIND_ROOT_PATH /opt/arm-linux)
# 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)
#File rostoolchain.cmake

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm64)
set(CMAKE_SYSROOT /arm64)
set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++)
set(CMAKE_FIND_ROOT_PATH /opt/ros/melodic /arm64)

set(CMAKE_LIBRARY_PATH /arm64/usr/lib/aarch64-linux-gnu /arm64/usr/lib /arm64/lib /arm64/usr/local/lib)

set(CMAKE_INCLUDE_PATH /arm64/usr/include /arm64/usr/local/include)
set(LD_LIBRARY_PATH /arm64/usr/lib/aarch64-linux-gnu /arm64/usr/lib /arm64/lib /arm64/usr/local/lib)

set(PYTHON_EXECUTABLE /usr/bin/python)
set(PCL_ROOT /arm64/usr)

set(CMAKE_CROSSCOMPILING true)

# Have to set this one to BOTH, to allow CMake to find rospack

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

catkin_make install  -DCMAKE_TOOLCHAIN_FILE=/xx/toolchain-aarch64.cmake -j4

2. How to isolate the mount:

ch-mount.sh -m arm64
ch-mount.sh -u arm64

Copy the corresponding library file in the arm64 machine and put it on the x86 computer for isolation

$ ls arm64/
Arm64Env  arm64_xc.gz  bin  boot  dev  etc  home  lib  lost+found  mnt  opt  proc  root  sbin  snap  srv  sys  system  tmp  usr  var

ch-mount.sh

#!/bin/bash
# 
function mnt() {
    
    
    echo "MOUNTING"
    sudo mount -t proc /proc ${2}/proc
    sudo mount -t sysfs /sys ${2}/sys
    sudo mount -o bind /dev ${2}/dev
    sudo mount -o bind /dev/pts ${2}/dev/pts
#    sudo mount -o bind /run ${2}/run 
#    sudo mount -o bind /proc ${2}/proc
#    sudo mount -o bind /sys ${2}/sys
    sudo chroot ${2}
}
function umnt() {
    
    
    echo "UNMOUNTING"
    sudo umount ${2}/proc
    sudo umount ${2}/sys
    sudo umount ${2}/dev/pts
    sudo umount ${2}/dev
#    sudo umount ${2}/run
}
if [ "$1" == "-m" ] && [ -n "$2" ] ;
then
    mnt $1 $2
elif [ "$1" == "-u" ] && [ -n "$2" ];
then
    umnt $1 $2
else
    echo ""
    echo "Either 1'st, 2'nd or both parameters were missing"
    echo ""
    echo "1'st parameter can be one of these: -m(mount) OR -u(umount)"
    echo "2'nd parameter is the full path of rootfs directory(with trailing '/')"
    echo ""
    echo "For example: ch-mount -m /media/sdcard/"
    echo ""
    echo 1st parameter : ${1}
    echo 2nd parameter : ${2}
fi

3. QEMU or other emulator to actually run docker

If the Docker image you run on the x86 computer is already targeting the arm64 architecture (for example, use FROM arm64v8/ubuntu as the base image), then you do not need to configure cross-compilation. This is because the Docker image itself already contains libraries and tools for arm64.

In this case, you can compile arm64 programs directly in the Docker image. Note, however, that you may need to configure QEMU or another emulator on the host machine to actually run the arm64 Docker image on the x86 machine. Otherwise, you may run into compatibility issues because you're trying to run arm64 code on an x86 host.

When running an arm64 Docker image, Docker automatically sets up QEMU to emulate the arm64 architecture. Make sure you have QEMU installed on your host machine and enable the corresponding binary format support in order to run these images correctly.

安装QEMU和支持库:
sudo apt-get install qemu-user-static binfmt-support
将QEMU的ARM64静态二进制文件复制到Dockerfile的当前目录:

cp /usr/bin/qemu-aarch64-static .
在Dockerfile中添加以下指令以包含QEMU二进制文件:
COPY qemu-aarch64-static /usr/bin/

要确保您的宿主机上安装了 QEMU 并启用了对应的二进制格式支持,请按照以下步骤操作:

首先,安装 QEMU。在基于 Debian 的系统(如 Ubuntu)上,您可以使用以下命令进行安装:
 
sudo apt-get update
sudo apt-get install qemu qemu-user-static binfmt-support
在基于 RHEL 的系统(如 CentOS、Fedora)上,您可以使用以下命令进行安装:
 
sudo yum install qemu qemu-user-static
接下来,验证 QEMU 是否已安装:
 
qemu-system-aarch64 --version
如果成功安装,您应该会看到 QEMU 版本信息。

确认 binfmt-support 服务是否启用:
 
sudo systemctl status binfmt-support
如果服务未启用,请使用以下命令启用并启动服务:
 
sudo systemctl enable binfmt-support
sudo systemctl start binfmt-support
最后,确保您的系统已注册了 ARM64 架构的二进制格式支持。运行以下命令:
 
cat /proc/sys/fs/binfmt_misc/qemu-aarch64
如果已启用支持,您应该会看到包含 "flags: F" 和 "interpreter /usr/bin/qemu-aarch64-static" 的输出。

完成这些步骤后,您的宿主机应已准备好运行 ARM64 架构的 Docker 镜像。这意味着您可以在这些镜像中直接编译 ARM64 程序,而无需配置交叉编译。

Dockerfile.arm64_melodic

FROM arm64v8/ros:melodic-perception

ENV WS=/home/xx/yy
COPY start.sh /home/xx/yy/

COPY qemu-aarch64-static /usr/bin/
COPY sources.list.arm /etc/apt/sources.list
COPY ros.asc      /etc/

 
RUN apt-get install -y build-essential
 

RUN sh -c '. /etc/lsb-release && echo "deb http://mirrors.sjtug.sjtu.edu.cn/ros/ubuntu/ `lsb_release -cs` main" > /etc/apt/sources.list.d/ros-latest.list' && \
    apt-key add  /etc/ros.asc
#RUN apt-key adv --keyserver keys.gnupg.net --recv-key 6F3EFCDE   
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys  7EA0A9C3F273FCD8
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys  C8B3A55A6F3EFCDE
RUN apt update 
RUN apt-get install -y ros-melodic-desktop-full
RUN apt-get install -y python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential python-catkin-tools python3-vcstool
RUN apt-get install -y ros-melodic-ecl  libgoogle-glog-dev  libgflags-dev libbullet-dev libsdl2-dev zstd libsdl-image1.2-dev libsdl-dev  
RUN apt-get install -y ros-melodic-tf2-geometry-msgs ros-melodic-tf2-sensor-msgs ros-melodic-urdf  \
    ros-melodic-usb-cam ros-melodic-rgbd-launch ros-melodic-libuvc ros-melodic-libuvc-camera ros-melodic-libuvc-ros \
    ros-melodic-move-base-msgs ros-melodic-kobuki-msgs   libfcl-dev ros-melodic-bfl   ros-melodic-pcl-ros libpcl-dev  
RUN mv /usr/include/flann/ext/lz4.h /usr/include/flann/ext/lz4.h.bak && \
    mv /usr/include/flann/ext/lz4hc.h /usr/include/flann/ext/lz4.hc.bak && \
    ln -s /usr/include/lz4.h /usr/include/flann/ext/lz4.h && \
    ln -s /usr/include/lz4hc.h /usr/include/flann/ext/lz4hc.h

RUN echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc

RUN apt-get install -y ros-melodic-qt-build libevent-dev  gcc g++ gfortran git cmake liblapack-dev pkg-config swig ipython python-dev python-numpy python-scipy python-matplotlib --install-recommends

RUN apt-get install -y tmux ros-melodic-dynamic-reconfigure   libzstd-dev

RUN apt-get install -y \
    clang \
    cmake \
    g++ \
    git \
    google-mock \
    libboost-all-dev \
    libcairo2-dev \
    libcurl4-openssl-dev \
    libeigen3-dev \
    libgflags-dev \
    libgoogle-glog-dev \
    liblua5.2-dev \
    libsuitesparse-dev \
    lsb-release \
    ninja-build \
    stow 
RUN apt-get install -y      vim  net-tools git  ssh

RUN apt-get install -y  python-sphinx
RUN apt-get install -y  libceres-dev tar

WORKDIR /home/xx/carto_libs
#git clone http://gitlab.csjbot.com/RenBot/abseil-cpp.git
#git clone http://gitlab.csjbot.com/RenBot/ceres-solver.git
#git clone http://gitlab.csjbot.com/RenBot/protobuf.git

#ADD abseil-cpp.tar.gz    /home/xx/carto_libs/abseil-cpp.tar.gz
#ADD ceres-solver.tar.gz /home/xx/carto_libs/ceres-solver.tar.gz
#ADD protobuf.tar.gz    /home/xx/carto_libs/protobuf.tar.gz

COPY abseil-cpp.tar.gz    /home/xx/carto_libs/
COPY ceres-solver.tar.gz /home/xx/carto_libs/
COPY protobuf.tar.gz    /home/xx/carto_libs/

WORKDIR /home/xx/carto_libs/
RUN tar -xzvf /home/xx/carto_libs/abseil-cpp.tar.gz abseil-cpp && \
    tar -xzvf /home/xx/carto_libs/ceres-solver.tar.gz && \
    tar -xzvf /home/xx/carto_libs/protobuf.tar.gz

RUN echo "Start ceres"
WORKDIR /home/xx/carto_libs/ceres-solver
RUN cd  /home/xx/carto_libs/abseil-cpp && \
    #git checkout tags/carto  && \
    mkdir -p build  && \
    cd build  && \
    cmake ..  -DCXX11=ON && \
    make -j16 && \
    make install  >> ../install.info && \
    echo "Finish ceres"

RUN echo "Start abseil"
WORKDIR /home/xx/carto_libs/abseil-cpp/
#RUN cd abseil-cpp
RUN cd  /home/xx/carto_libs/abseil-cpp && \
    #git checkout tags/carto  && \
    mkdir -p build  && \
    cd build  && \
    cmake  -DCMAKE_BUILD_TYPE=Release  -DCXX11=ON  -DCMAKE_POSITION_INDEPENDENT_CODE=ON   -DCMAKE_INSTALL_PREFIX=/usr/local/stow/absl   ..  && \
    make  -j12 && \
    make install >> ../install.info
RUN cd /usr/local/stow && \
    stow --replace absl && \
    echo "Finish abseil"

WORKDIR /home/xx/carto_libs
RUN echo "Start protobuf"
RUN cd  /home/xx/carto_libs/protobuf && \
    #git checkout tags/carto  && \
    mkdir -p build  && \
    cd build  && \
    cmake  -DCMAKE_POSITION_INDEPENDENT_CODE=ON   -DCMAKE_BUILD_TYPE=Release   -Dprotobuf_BUILD_TESTS=OFF   ../cmake   && \
    make -j12  && \
    sudo make install  >> ../install.info  && \
    echo "Finish protobuf"
 
RUN echo "export DISABLE_AUTO_TITLE=true" >> ~/.bashrc
RUN echo 'LC_NUMERIC="en_US.UTF-8"' >> ~/.bashrc
RUN echo "source /usr/share/gazebo/setup.sh" >> ~/.bashrc
RUN echo 'alias cinstall="catkin_make install -j12"' >> ~/.bashrc
RUN echo 'alias cbuild="catkin_make -j12"' >> ~/.bashrc

RUN echo "bashrc"
RUN echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
RUN echo "source /opt/ros/melodic/setup.bash" >> /home/xx/.bashrc
RUN echo "source /home/xx/yy/install/setup.bash" >> /home/xx/.bashrc
RUN echo "source /home/xx/yy/install/setup.bash" >> ~/.bashrc
RUN pwd
WORKDIR $WS

CMD ["bash","-c","/home/xx/yy/start.sh"]



Guess you like

Origin blog.csdn.net/zyh821351004/article/details/129806776