Crosscompiling

From Open Mower Wiki
Revision as of 15:19, 20 May 2024 by Damme (talk | contribs) (Created page with "Warning! You are in for a treat! :D - You have been warned. But reward is good, from 3250sec with docker buildx using qemu to 304s on my machine (Clean build) == Instructions == These instructions are made for Ubuntu 20.04.6 LTS <big>INSTALL ROS https://wiki.ros.org/noetic/Installation/Ubuntu</big> ==== Update source files ==== * Add '''<code>[arch=amd64]</code>''' after deb on each line in <code>/etc/apt/sources.list</code> (This should be changed to your current ma...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Warning! You are in for a treat! :D - You have been warned. But reward is good, from 3250sec with docker buildx using qemu to 304s on my machine (Clean build)


Instructions

These instructions are made for Ubuntu 20.04.6 LTS

INSTALL ROS https://wiki.ros.org/noetic/Installation/Ubuntu

Update source files

  • Add [arch=amd64] after deb on each line in /etc/apt/sources.list (This should be changed to your current machines native arch!)
  • Add [arch=amd64,arm64] after deb in /etc/apt/sources.list.d/ros-latest.list
  • Create /etc/apt/sources.list.d/arm-cross-compile-sources.list
deb [arch=arm64] http://ports.ubuntu.com/ focal main restricted
deb [arch=arm64] http://ports.ubuntu.com/ focal-updates main restricted
deb [arch=arm64] http://ports.ubuntu.com/ focal universe
deb [arch=arm64] http://ports.ubuntu.com/ focal-updates universe
deb [arch=arm64] http://ports.ubuntu.com/ focal multiverse
deb [arch=arm64] http://ports.ubuntu.com/ focal-updates multiverse
deb [arch=arm64] http://ports.ubuntu.com/ focal-backports main restricted universe multiverse
  • run
sudo apt update
sudo dpkg --add-architecture arm64

sudo apt install crossbuild-essential-arm64 parallel
  • Clone open_mower_ros and its componnets.
cd /opt/

git clone https://github.com/ClemensElflein/open_mower_ros
git submodule update --init --recursive

We will use CMAKE_SYSROOT /opt/sysroot_arm64 and /opt/sysroot_arm64_download - change these accordingly in the files for your needs. Total size to download is about 200MB and extracted is ~1.1GB. Change the number of download threads as desired.

  • create toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

# Specify the cross compiler
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)

#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
#set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static")

# Specify the target system root
set(CMAKE_SYSROOT /opt/sysroot_arm64)

set(SYSROOT_PATH ${CMAKE_SYSROOT})

unset(CMAKE_SYSTEM_PREFIX_PATH)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${CMAKE_SYSROOT}/opt/ros/noetic)

set(CMAKE_PREFIX_PATH ${CMAKE_SYSROOT}/opt/ros/noetic ${CMAKE_SYSROOT}/opt/ros/noetic/share)
set(CMAKE_LIBRARY_PATH ${CMAKE_SYSROOT}/opt/ros/noetic/lib)
set(CMAKE_INCLUDE_PATH ${CMAKE_SYSROOT}/opt/ros/noetic/include)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})

# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# For libraries and headers in the target directories
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_MODULE_PATH ${CMAKE_SYSROOT}/usr/share/cmake-3.13/Modules/)
set(ENV{PKG_CONFIG_PATH} ${CMAKE_SYSROOT}/usr/lib/aarch64-linux-gnu/pkgconfig/)


  • create 1_setup-sysroot.bash
#!/bin/bash

set -e

SYSROOT=/opt/sysroot_arm64
DOWNLOADDIR=/opt/sysroot_downloads
PARALLELDOWNLOAD=6

#########################

rm -rf $SYSROOT
mkdir -p $SYSROOT
mkdir -p $DOWNLOADDIR

# Link might not be needed? Cant remember :D
ln -s $SYSROOT/usr/lib $SYSROOT/lib

install_package() {
#  for PKG in "${PACKAGES[@]}"; do
    PKG=$1
    URL=$(apt-get download --print-uris $PKG | cut -d\' -f2)
    if [ -n "$URL" ]; then
      echo "Downloading $PKG ($URL)"
      wget -q -nc $URL -P $DOWNLOADDIR && dpkg -x $DOWNLOADDIR/$(basename $URL) $SYSROOT
# --show-progress
#      dpkg -x $DOWNLOADDIR/$(basename $URL) $SYSROOT
      echo "Done installing $PKG"
    else
      echo "$PKG NOT FOUND!"
    fi
#  done
}

export -f install_package
export DOWNLOADDIR
export SYSROOT

# read packages.txt into PACKAGES
while IFS= read -r line; do
    PACKAGES+=("$line")
done < "packages.txt"


parallel -j $PARALLELDOWNLOAD install_package ::: "${PACKAGES[@]}"


echo "Done!"
  • Download my little packages.txt # Focal Ubuntu 20.04.6 LTS!
wget https://gist.githubusercontent.com/Damme/3161f92ccadf452b4d5f3eee32da097e/raw/8df0172858e95da76091b04f8492705fc0cf0396/packages.txt -O packages.txt
  • create 2-fix-links-cmake.bash
SYSROOT=/opt/sysroot_arm64

echo "Linking some missing library links, broken links /hardcoded to /lib/..."

ln -sf $SYSROOT/usr/lib/aarch64-linux-gnu/libPocoFoundation.so.62 $SYSROOT/usr/lib/aarch64-linux-gnu/libPocoFoundation.so
ln -sf $SYSROOT/usr/lib/aarch64-linux-gnu/blas/libblas.so.3 $SYSROOT/usr/lib/aarch64-linux-gnu/libblas.so.3
ln -sf $SYSROOT/usr/lib/aarch64-linux-gnu/lapack/liblapack.so.3 $SYSROOT/usr/lib/aarch64-linux-gnu/liblapack.so.3

ln -sf $SYSROOT/lib/aarch64-linux-gnu/librt.so.1 $SYSROOT/sysroot_arm64/usr/lib/aarch64-linux-gnu/librt.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libpthread.so.0 $SYSROOT/usr/lib/aarch64-linux-gnu/libpthread.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libBrokenLocale.so.1 $SYSROOT/usr/lib/aarch64-linux-gnu/libBrokenLocale.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libanl.so.1 $SYSROOT/usr/lib/aarch64-linux-gnu/libanl.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libblkid.so.1.1.0 $SYSROOT/usr/lib/aarch64-linux-gnu/libblkid.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libbz2.so.1.0 $SYSROOT/usr/lib/aarch64-linux-gnu/libbz2.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libexpat.so.1.6.11 $SYSROOT/usr/lib/aarch64-linux-gnu/libexpat.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libgpg-error.so.0 $SYSROOT/usr/lib/aarch64-linux-gnu/libgpg-error.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libkeyutils.so.1 $SYSROOT/usr/lib/aarch64-linux-gnu/libkeyutils.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/liblzma.so.5.2.4 $SYSROOT/usr/lib/aarch64-linux-gnu/liblzma.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libm.so.6 $SYSROOT/usr/lib/aarch64-linux-gnu/libm.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libmount.so.1.1.0 $SYSROOT/usr/lib/aarch64-linux-gnu/libmount.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libnsl.so.1 $SYSROOT/usr/lib/aarch64-linux-gnu/libnsl.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libnss_compat.so.2 $SYSROOT/usr/lib/aarch64-linux-gnu/libnss_compat.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libnss_dns.so.2 $SYSROOT/usr/lib/aarch64-linux-gnu/libnss_dns.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libnss_files.so.2 $SYSROOT/usr/lib/aarch64-linux-gnu/libnss_files.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libnss_hesiod.so.2 $SYSROOT/usr/lib/aarch64-linux-gnu/libnss_hesiod.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libnss_nis.so.2 $SYSROOT/usr/lib/aarch64-linux-gnu/libnss_nis.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libnss_nisplus.so.2 $SYSROOT/usr/lib/aarch64-linux-gnu/libnss_nisplus.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libpcre.so.3 $SYSROOT/usr/lib/aarch64-linux-gnu/libpcre.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libresolv.so.2 $SYSROOT/usr/lib/aarch64-linux-gnu/libresolv.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libthread_db.so.1 $SYSROOT/usr/lib/aarch64-linux-gnu/libthread_db.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libutil.so.1 $SYSROOT/usr/lib/aarch64-linux-gnu/libutil.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libuuid.so.1.3.0 $SYSROOT/usr/lib/aarch64-linux-gnu/libuuid.so
ln -sf $SYSROOT/lib/aarch64-linux-gnu/libz.so.1.2.11 $SYSROOT/usr/lib/aarch64-linux-gnu/libz.so

echo "Fix cmake files with hardcoded paths.."
find $SYSROOT/opt/ros/noetic/ -name "*.cmake" | xargs sed -i s@/opt/ros/noetic/lib@\${SYSROOT_PATH}/opt/ros/noetic/lib@g
find $SYSROOT/opt/ros/noetic/ -name "*.cmake" | xargs sed -i s@PREFIX\ /opt/ros/noetic@PREFIX\ \${SYSROOT_PATH}/opt/ros/noetic@g
find $SYSROOT/opt/ros/noetic/ -name "*.cmake" | xargs sed -i s@\;/usr/@\;\$\{SYSROOT_PATH\}/usr/@g
find $SYSROOT/opt/ros/noetic/ -name "*.cmake" | xargs sed -i s@\"/usr/@\"\$\{SYSROOT_PATH\}/usr/@g
  • create 3-patch-openmower-cmake.bash
#!/bin/bash

cd src/lib/slic3r_coverage_planner

patch CMakeLists.txt <<'EOF'
@@ -33,7 +33,9 @@ ExternalProject_Add(

         CMAKE_CACHE_ARGS
         SOURCE_SUBDIR src
-        CMAKE_ARGS -DSLIC3R_BUILD_TESTS=OFF
+        CMAKE_ARGS -DSLIC3R_BUILD_TESTS=OFF -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
+               -DCMAKE_EXE_LINKER_FLAGS:STRING=--sysroot=${CMAKE_SYSROOT}\;-L${CMAKE_SYSROOT}/opt/ros/noetic/lib\;-L${CMAKE_SYSROOT}/usr/lib/aarch64-linux-gnu
+               -DCMAKE_SHARED_LINKER_FLAGS:STRING=--sysroot=${CMAKE_SYSROOT}\;-L${CMAKE_SYSROOT}/opt/ros/noetic/lib\;-L${CMAKE_SYSROOT}/usr/lib/aarch64-linux-gnu
         BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config Release
 )
EOF

cd ../../../

cd src/lib/xbot_driver_gps

patch CMakeLists.txt <<'EOF'
@@ -32,6 +32,9 @@ ExternalProject_Add(
         INSTALL_COMMAND cmake -E echo "Skipping install step."

         CMAKE_CACHE_ARGS
+        CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
+               -DCMAKE_EXE_LINKER_FLAGS:STRING=--sysroot=${CMAKE_SYSROOT}\;-L${CMAKE_SYSROOT}/opt/ros/noetic/lib\;-L${CMAKE_SYSROOT}/usr/lib/aarch64-linux-gnu
+               -DCMAKE_SHARED_LINKER_FLAGS:STRING=--sysroot=${CMAKE_SYSROOT}\;-L${CMAKE_SYSROOT}/opt/ros/noetic/lib\;-L${CMAKE_SYSROOT}/usr/lib/aarch64-linux-gnu
         BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config Release
 )
EOF

cd ../../../
  • run the following:
bash 1-setup_sysroot.bash
bash 2-fix-links-cmake.bash
bash 3-patch-openmower-cmake.bash
  • build with the following command, change -j1 for number of parallel processes. For some reason catkin_make does not parse toolchain.cmake without forcing it...
$ catkin_make -DCMAKE_TOOLCHAIN_FILE=/opt/open_mower_ros/toolchain.cmake -j1


Good luck!