From dd3103497a1555c5cd4337f6a6ab973c7b633da5 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sat, 1 Apr 2023 11:10:41 +0100 Subject: [PATCH] aarch64-linux-gnu cross-compilation Allows one to easily cross-compile for aarch64 on a Debian/Ubuntu host. Also adds a GitHub Action for it. --- .github/workflows/Linux_aarch64.yml | 79 +++++++++++++++++++ .gitignore | 3 + CMake/platforms/aarch64-linux-gnu-pkg-config | 1 + .../aarch64-linux-gnu.toolchain.cmake | 18 +++++ CMake/platforms/debian-cross-pkg-config.sh | 50 ++++++++++++ Packaging/nix/AppImage.sh | 23 ++++-- Packaging/nix/debian-cross-aarch64-prep.sh | 24 ++++++ README.md | 1 + docs/building.md | 18 +++++ 9 files changed, 212 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/Linux_aarch64.yml create mode 120000 CMake/platforms/aarch64-linux-gnu-pkg-config create mode 100644 CMake/platforms/aarch64-linux-gnu.toolchain.cmake create mode 100755 CMake/platforms/debian-cross-pkg-config.sh create mode 100755 Packaging/nix/debian-cross-aarch64-prep.sh diff --git a/.github/workflows/Linux_aarch64.yml b/.github/workflows/Linux_aarch64.yml new file mode 100644 index 00000000000..154af477190 --- /dev/null +++ b/.github/workflows/Linux_aarch64.yml @@ -0,0 +1,79 @@ +name: Linux AArch64 + +on: + push: + branches: + - master + paths-ignore: + - '*.md' + pull_request: + types: [opened, synchronize] + paths-ignore: + - '*.md' + release: + types: [published] + paths-ignore: + - '*.md' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Create Build Environment + run: | + # Work around the somewhat broken packages in the GitHub Actions Ubuntu 20.04 image. + # https://github.com/actions/runner-images/issues/4620#issuecomment-981333260 + sudo apt-get -y install --allow-downgrades libpcre2-8-0=10.34-7 + Packaging/nix/debian-cross-aarch64-prep.sh + + - name: Build + working-directory: ${{github.workspace}} + shell: bash + env: + CMAKE_BUILD_TYPE: ${{github.event_name == 'release' && 'Release' || 'RelWithDebInfo'}} + # We set DEVILUTIONX_SYSTEM_LIBFMT=OFF because its soversion changes frequently. + run: | + cmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/aarch64-linux-gnu.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=${{env.CMAKE_BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=/usr -DCPACK=ON \ + -DDEVILUTIONX_SYSTEM_LIBFMT=OFF && \ + cmake --build build -j $(getconf _NPROCESSORS_ONLN) --target package + + - name: Package + run: Packaging/nix/LinuxReleasePackaging.sh && mv devilutionx.tar.xz devilutionx-aarch64.tar.xz + + # AppImage cross-packaging is not implemented yet. + # - name: Package AppImage + # run: Packaging/nix/AppImage.sh && mv devilutionx.appimage devilutionx-aarch64.appimage + + - name: Upload Package + if: ${{ !env.ACT }} + uses: actions/upload-artifact@v2 + with: + name: devilutionx-aarch64.tar.xz + path: devilutionx-aarch64.tar.xz + + # AppImage cross-packaging is not implemented yet. + # - name: Upload AppImage + # if: ${{ !env.ACT }} + # uses: actions/upload-artifact@v2 + # with: + # name: devilutionx-aarch64.appimage + # path: devilutionx-aarch64.appimage + + - name: Update Release + if: ${{ github.event_name == 'release' && !env.ACT }} + uses: svenstaro/upload-release-action@v2 + with: + file: devilutionx-aarch64.* + file_glob: true + overwrite: true diff --git a/.gitignore b/.gitignore index fa75a1dc969..e2eab6ac877 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,9 @@ comparer-config.toml # Extra files in the source distribution (see make_src_dist.py) /dist/ +*.appimage +*.AppImage + # ELF object file, shared library and object archive. *.o *.so diff --git a/CMake/platforms/aarch64-linux-gnu-pkg-config b/CMake/platforms/aarch64-linux-gnu-pkg-config new file mode 120000 index 00000000000..e0fb47b9d9c --- /dev/null +++ b/CMake/platforms/aarch64-linux-gnu-pkg-config @@ -0,0 +1 @@ +debian-cross-pkg-config.sh \ No newline at end of file diff --git a/CMake/platforms/aarch64-linux-gnu.toolchain.cmake b/CMake/platforms/aarch64-linux-gnu.toolchain.cmake new file mode 100644 index 00000000000..f3d13cccd89 --- /dev/null +++ b/CMake/platforms/aarch64-linux-gnu.toolchain.cmake @@ -0,0 +1,18 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +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 "/usr/aarch64-linux-gnu;/usr") +set(CMAKE_LIBRARY_ARCHITECTURE aarch64-linux-gnu) + +set(PKG_CONFIG_EXECUTABLE "${CMAKE_CURRENT_LIST_DIR}/aarch64-linux-gnu-pkg-config" CACHE STRING "Path to pkg-config") + +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) + +set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE arm64) diff --git a/CMake/platforms/debian-cross-pkg-config.sh b/CMake/platforms/debian-cross-pkg-config.sh new file mode 100755 index 00000000000..df78ef11ade --- /dev/null +++ b/CMake/platforms/debian-cross-pkg-config.sh @@ -0,0 +1,50 @@ +#!/bin/sh +# pkg-config wrapper for cross-building +# Sets pkg-config search path to search multiarch and historical cross-compiling paths. + +# https://gist.github.com/doug65536/ea9c52f9a65a655a2fd5cc4997e8443b + +# If the user has already set PKG_CONFIG_LIBDIR, believe it (even if empty): +# it's documented to be an override +if [ x"${PKG_CONFIG_LIBDIR+set}" = x ]; then + # GNU triplet for the compiler, e.g. i486-linux-gnu for Debian i386, + # i686-linux-gnu for Ubuntu i386 + basename="`basename "$0"`" + triplet="${basename%-pkg-config}" + # Normalized multiarch path if any, e.g. i386-linux-gnu for i386 + multiarch="`dpkg-architecture -t"${triplet}" -qDEB_HOST_MULTIARCH 2>/dev/null`" + # Native multiarch path + native_multiarch="$(cat /usr/lib/pkg-config.multiarch)" + + # This can be used for native builds as well, in that case, just exec pkg-config "$@" directly. + if [ "$native_multiarch" = "$multiarch" ]; then + exec pkg-config "$@" + fi + + PKG_CONFIG_LIBDIR="/usr/local/${triplet}/lib/pkgconfig" + # For a native build we would also want to append /usr/local/lib/pkgconfig + # at this point; but this is a cross-building script, so don't + PKG_CONFIG_LIBDIR="$PKG_CONFIG_LIBDIR:/usr/local/share/pkgconfig" + + if [ -n "$multiarch" ]; then + PKG_CONFIG_LIBDIR="/usr/local/lib/${multiarch}/pkgconfig:$PKG_CONFIG_LIBDIR" + PKG_CONFIG_LIBDIR="$PKG_CONFIG_LIBDIR:/usr/lib/${multiarch}/pkgconfig" + fi + + PKG_CONFIG_LIBDIR="$PKG_CONFIG_LIBDIR:/usr/${triplet}/lib/pkgconfig" + # For a native build we would also want to append /usr/lib/pkgconfig + # at this point; but this is a cross-building script, so don't + # If you want to allow use of un-multiarched -dev packages for crossing + # (at the risk of finding build-arch stuff you didn't want, if not in a clean chroot) + # Uncomment the next line: + # PKG_CONFIG_LIBDIR="$PKG_CONFIG_LIBDIR:/usr/lib/pkgconfig" + # ... but on Ubuntu we rely cross-building with non-multiarch libraries: + if dpkg-vendor --derives-from Ubuntu; then + PKG_CONFIG_LIBDIR="$PKG_CONFIG_LIBDIR:/usr/lib/pkgconfig" + fi + PKG_CONFIG_LIBDIR="$PKG_CONFIG_LIBDIR:/usr/share/pkgconfig" + + export PKG_CONFIG_LIBDIR +fi + +exec pkg-config "$@" diff --git a/Packaging/nix/AppImage.sh b/Packaging/nix/AppImage.sh index 0a76fd77d37..6244aaf0a59 100755 --- a/Packaging/nix/AppImage.sh +++ b/Packaging/nix/AppImage.sh @@ -1,6 +1,19 @@ -make install -Cbuild DESTDIR=AppDir -mv build/AppDir/usr/share/diasurgical/devilutionx/devilutionx.mpq build/AppDir/usr/bin/devilutionx.mpq -wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage -N -chmod +x linuxdeploy-x86_64.AppImage -./linuxdeploy-x86_64.AppImage --appimage-extract-and-run --appdir=build/AppDir --custom-apprun=Packaging/nix/AppRun -d Packaging/nix/devilutionx.desktop -o appimage +#!/usr/bin/env bash +set -euo pipefail +set -x + +BUILD_DIR="${1-build}" +cmake --install "$BUILD_DIR" --prefix "${BUILD_DIR}/AppDir/usr" +mv "$BUILD_DIR"/AppDir/usr/share/diasurgical/devilutionx/devilutionx.mpq "$BUILD_DIR"/AppDir/usr/bin/devilutionx.mpq + +APPIMAGE_BUILDER="${APPIMAGE_BUILDER:-linuxdeploy-x86_64.AppImage}" +if ! which "$APPIMAGE_BUILDER"; then + if ! [[ -f linuxdeploy-x86_64.AppImage ]]; then + wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage -N + chmod +x linuxdeploy-x86_64.AppImage + fi + APPIMAGE_BUILDER=./linuxdeploy-x86_64.AppImage +fi +"$APPIMAGE_BUILDER" --appimage-extract-and-run --appdir="$BUILD_DIR"/AppDir --custom-apprun=Packaging/nix/AppRun -d Packaging/nix/devilutionx.desktop -o appimage + mv DevilutionX*.AppImage devilutionx.appimage diff --git a/Packaging/nix/debian-cross-aarch64-prep.sh b/Packaging/nix/debian-cross-aarch64-prep.sh new file mode 100755 index 00000000000..38f1247d61f --- /dev/null +++ b/Packaging/nix/debian-cross-aarch64-prep.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail +set -x + +FLAVOR="$(lsb_release -sc)" + +if dpkg-vendor --derives-from Ubuntu; then + sudo tee /etc/apt/sources.list.d/arm64.list <
macOS