Add ARM64 (aarch64) support for AppImage builds
This commit is contained in:
@@ -2,10 +2,12 @@
|
||||
# from https://docs.appimage.org/introduction/concepts.html :
|
||||
# "[AppImages] should be built on the oldest possible system, allowing them to run on newer system[s]"
|
||||
|
||||
ARG TARGETARCH=x86_64
|
||||
FROM debian:bullseye@sha256:cf48c31af360e1c0a0aedd33aae4d928b68c2cdf093f1612650eb1ff434d1c34
|
||||
|
||||
ENV LC_ALL=C.UTF-8 LANG=C.UTF-8
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TARGETARCH=${TARGETARCH}
|
||||
|
||||
# need ca-certificates before using snapshot packages
|
||||
RUN apt update -qq > /dev/null && apt install -qq --yes --no-install-recommends \
|
||||
|
||||
@@ -4,8 +4,18 @@ set -e
|
||||
|
||||
APPDIR="$(dirname "$(readlink -e "$0")")"
|
||||
|
||||
export LD_LIBRARY_PATH="${APPDIR}/usr/lib/:${APPDIR}/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}"
|
||||
# Detect architecture-specific lib directory
|
||||
if [ -d "${APPDIR}/usr/lib/x86_64-linux-gnu" ]; then
|
||||
ARCH_LIB_DIR="x86_64-linux-gnu"
|
||||
elif [ -d "${APPDIR}/usr/lib/aarch64-linux-gnu" ]; then
|
||||
ARCH_LIB_DIR="aarch64-linux-gnu"
|
||||
else
|
||||
# Fallback to x86_64 for backward compatibility
|
||||
ARCH_LIB_DIR="x86_64-linux-gnu"
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH="${APPDIR}/usr/lib/:${APPDIR}/usr/lib/${ARCH_LIB_DIR}${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}"
|
||||
export PATH="${APPDIR}/usr/bin:${PATH}"
|
||||
export LDFLAGS="-L${APPDIR}/usr/lib/x86_64-linux-gnu -L${APPDIR}/usr/lib"
|
||||
export LDFLAGS="-L${APPDIR}/usr/lib/${ARCH_LIB_DIR} -L${APPDIR}/usr/lib"
|
||||
|
||||
exec "${APPDIR}/usr/bin/python3" -s "${APPDIR}/usr/bin/electrum" "$@"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# env vars:
|
||||
# - ELECBUILD_NOCACHE: if set, forces rebuild of docker image
|
||||
# - ELECBUILD_COMMIT: if set, do a fresh clone and git checkout
|
||||
# - ARCH: target architecture (x86_64 or aarch64, default: x86_64)
|
||||
|
||||
set -e
|
||||
|
||||
@@ -15,6 +16,13 @@ BUILD_UID=$(/usr/bin/stat -c %u "$PROJECT_ROOT")
|
||||
|
||||
. "$CONTRIB"/build_tools_util.sh
|
||||
|
||||
# Determine architecture (default to x86_64 if not set)
|
||||
export ARCH="${ARCH:-x86_64}"
|
||||
if [ "$ARCH" != "x86_64" ] && [ "$ARCH" != "aarch64" ]; then
|
||||
fail "Unsupported ARCH: $ARCH. Must be x86_64 or aarch64"
|
||||
fi
|
||||
info "Building AppImage for architecture: $ARCH"
|
||||
|
||||
|
||||
DOCKER_BUILD_FLAGS=""
|
||||
if [ ! -z "$ELECBUILD_NOCACHE" ] ; then
|
||||
@@ -29,6 +37,7 @@ fi
|
||||
info "building docker image."
|
||||
docker build \
|
||||
$DOCKER_BUILD_FLAGS \
|
||||
--build-arg TARGETARCH="$ARCH" \
|
||||
-t pallectrum-appimage-builder-img \
|
||||
"$CONTRIB_APPIMAGE"
|
||||
|
||||
@@ -78,6 +87,7 @@ docker run $DOCKER_RUN_FLAGS \
|
||||
-v "$PROJECT_ROOT_OR_FRESHCLONE_ROOT":/opt/pallectrum \
|
||||
--rm \
|
||||
--workdir /opt/pallectrum/contrib/build-linux/appimage \
|
||||
-e ARCH="$ARCH" \
|
||||
pallectrum-appimage-builder-img \
|
||||
./make_appimage.sh
|
||||
|
||||
|
||||
@@ -20,6 +20,20 @@ git -C "$PROJECT_ROOT" rev-parse 2>/dev/null || fail "Building outside a git clo
|
||||
|
||||
export GCC_STRIP_BINARIES="1"
|
||||
|
||||
# Determine architecture (default to x86_64 if not set)
|
||||
ARCH="${ARCH:-x86_64}"
|
||||
if [ "$ARCH" != "x86_64" ] && [ "$ARCH" != "aarch64" ]; then
|
||||
fail "Unsupported ARCH: $ARCH. Must be x86_64 or aarch64"
|
||||
fi
|
||||
info "Building for architecture: $ARCH"
|
||||
|
||||
# Set architecture-specific variables
|
||||
if [ "$ARCH" = "aarch64" ]; then
|
||||
LINUX_GNU_ARCH="aarch64-linux-gnu"
|
||||
else
|
||||
LINUX_GNU_ARCH="x86_64-linux-gnu"
|
||||
fi
|
||||
|
||||
# pinned versions
|
||||
PYTHON_VERSION=3.12.11
|
||||
PY_VER_MAJOR="3.12" # as it appears in fs paths
|
||||
@@ -36,8 +50,12 @@ info "downloading some dependencies."
|
||||
download_if_not_exist "$CACHEDIR/functions.sh" "https://raw.githubusercontent.com/AppImage/pkg2appimage/$PKG2APPIMAGE_COMMIT/functions.sh"
|
||||
verify_hash "$CACHEDIR/functions.sh" "8f67711a28635b07ce539a9b083b8c12d5488c00003d6d726c7b134e553220ed"
|
||||
|
||||
download_if_not_exist "$CACHEDIR/appimagetool" "https://github.com/AppImage/appimagetool/releases/download/1.9.0/appimagetool-x86_64.AppImage"
|
||||
verify_hash "$CACHEDIR/appimagetool" "46fdd785094c7f6e545b61afcfb0f3d98d8eab243f644b4b17698c01d06083d1"
|
||||
download_if_not_exist "$CACHEDIR/appimagetool-$ARCH" "https://github.com/AppImage/appimagetool/releases/download/1.9.0/appimagetool-$ARCH.AppImage"
|
||||
if [ "$ARCH" = "x86_64" ]; then
|
||||
verify_hash "$CACHEDIR/appimagetool-$ARCH" "46fdd785094c7f6e545b61afcfb0f3d98d8eab243f644b4b17698c01d06083d1"
|
||||
else
|
||||
verify_hash "$CACHEDIR/appimagetool-$ARCH" "04f45ea45b5aa07bb2b071aed9dbf7a5185d3953b11b47358c1311f11ea94a96"
|
||||
fi
|
||||
# note: desktop-file-utils in the docker image is needed to run desktop-file-validate for appimagetool <= 1.9.0, so it can be removed once
|
||||
# appimagetool tags a new release (see https://github.com/AppImage/appimagetool/pull/47)
|
||||
|
||||
@@ -99,7 +117,7 @@ cp -f "$DLL_TARGET_DIR/libzbar.so.0" "$APPDIR/usr/lib/" || fail "Could not copy
|
||||
appdir_python() {
|
||||
env \
|
||||
PYTHONNOUSERSITE=1 \
|
||||
LD_LIBRARY_PATH="$APPDIR/usr/lib:$APPDIR/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}" \
|
||||
LD_LIBRARY_PATH="$APPDIR/usr/lib:$APPDIR/usr/lib/$LINUX_GNU_ARCH${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}" \
|
||||
"$APPDIR/usr/bin/python${PY_VER_MAJOR}" "$@"
|
||||
}
|
||||
|
||||
@@ -118,12 +136,12 @@ info "determining version for AppImage filename."
|
||||
VERSION=$("$python" "$CONTRIB"/print_electrum_version.py)
|
||||
if [ -n "$ELECBUILD_COMMIT" ] || git diff-index --quiet HEAD -- ; then
|
||||
# Reproducible build or clean repo: clean version only
|
||||
APPIMAGE="$DISTDIR/pallectrum-v$VERSION-x86_64.AppImage"
|
||||
APPIMAGE="$DISTDIR/pallectrum-v$VERSION-$ARCH.AppImage"
|
||||
else
|
||||
# Development build with uncommitted changes: add git info
|
||||
GIT_HASH=$(git rev-parse --short=9 HEAD)
|
||||
VERSION_WITH_HASH="v$VERSION-$(git rev-list --count HEAD)-g$GIT_HASH-dirty"
|
||||
APPIMAGE="$DISTDIR/pallectrum-$VERSION_WITH_HASH-x86_64.AppImage"
|
||||
APPIMAGE="$DISTDIR/pallectrum-$VERSION_WITH_HASH-$ARCH.AppImage"
|
||||
fi
|
||||
info "AppImage will be: $APPIMAGE"
|
||||
|
||||
@@ -160,8 +178,26 @@ export ELECTRUM_ECC_DONT_COMPILE=1
|
||||
info "installing electrum and its dependencies."
|
||||
"$python" -m pip install --no-build-isolation --no-dependencies --no-binary :all: --no-warn-script-location \
|
||||
--cache-dir "$PIP_CACHE_DIR" -r "$CONTRIB/deterministic-build/requirements.txt"
|
||||
"$python" -m pip install --no-build-isolation --no-dependencies --no-binary :all: --only-binary PyQt6,PyQt6-Qt6,cryptography --no-warn-script-location \
|
||||
--cache-dir "$PIP_CACHE_DIR" -r "$CONTRIB/deterministic-build/requirements-binaries.txt"
|
||||
|
||||
# For aarch64, PyQt6 6.9.0 is not available, so we install compatible versions without hash verification
|
||||
if [ "$ARCH" = "aarch64" ]; then
|
||||
info "Installing binaries for aarch64 (using latest compatible versions)..."
|
||||
"$python" -m pip install --no-build-isolation --no-dependencies --only-binary PyQt6,PyQt6-Qt6,cryptography --no-warn-script-location \
|
||||
--cache-dir "$PIP_CACHE_DIR" \
|
||||
'cffi==1.17.1' \
|
||||
'cryptography==45.0.3' \
|
||||
'pip==25.1.1' \
|
||||
'pycparser==2.22' \
|
||||
'PyQt6>=6.7.0,<6.8.0' \
|
||||
'PyQt6-Qt6>=6.7.0,<6.8.0' \
|
||||
'PyQt6-sip==13.10.2' \
|
||||
'setuptools==80.9.0' \
|
||||
'wheel==0.45.1'
|
||||
else
|
||||
"$python" -m pip install --no-build-isolation --no-dependencies --no-binary :all: --only-binary PyQt6,PyQt6-Qt6,cryptography --no-warn-script-location \
|
||||
--cache-dir "$PIP_CACHE_DIR" -r "$CONTRIB/deterministic-build/requirements-binaries.txt"
|
||||
fi
|
||||
|
||||
"$python" -m pip install --no-build-isolation --no-dependencies --no-binary :all: --no-warn-script-location \
|
||||
--cache-dir "$PIP_CACHE_DIR" -r "$CONTRIB/deterministic-build/requirements-hw.txt"
|
||||
|
||||
@@ -200,11 +236,11 @@ info "finalizing AppDir."
|
||||
info "Copying additional libraries"
|
||||
(
|
||||
# On some systems it can cause problems to use the system libusb (on AppImage excludelist)
|
||||
cp -f /usr/lib/x86_64-linux-gnu/libusb-1.0.so "$APPDIR/usr/lib/libusb-1.0.so" || fail "Could not copy libusb"
|
||||
cp -f /usr/lib/$LINUX_GNU_ARCH/libusb-1.0.so "$APPDIR/usr/lib/libusb-1.0.so" || fail "Could not copy libusb"
|
||||
# some distros lack libxkbcommon-x11
|
||||
cp -f /usr/lib/x86_64-linux-gnu/libxkbcommon-x11.so.0 "$APPDIR"/usr/lib/x86_64-linux-gnu || fail "Could not copy libxkbcommon-x11"
|
||||
cp -f /usr/lib/$LINUX_GNU_ARCH/libxkbcommon-x11.so.0 "$APPDIR"/usr/lib/$LINUX_GNU_ARCH || fail "Could not copy libxkbcommon-x11"
|
||||
# some distros lack some libxcb libraries (see https://github.com/Electron-Cash/Electron-Cash/issues/2196)
|
||||
cp -f /usr/lib/x86_64-linux-gnu/libxcb-* "$APPDIR"/usr/lib/x86_64-linux-gnu || fail "Could not copy libxcb"
|
||||
cp -f /usr/lib/$LINUX_GNU_ARCH/libxcb-* "$APPDIR"/usr/lib/$LINUX_GNU_ARCH || fail "Could not copy libxcb"
|
||||
)
|
||||
|
||||
info "stripping binaries from debug symbols."
|
||||
@@ -233,7 +269,7 @@ PYDIR="$APPDIR/usr/lib/python${PY_VER_MAJOR}"
|
||||
rm -rf "$PYDIR"/{test,ensurepip,lib2to3,idlelib,turtledemo}
|
||||
rm -rf "$PYDIR"/{ctypes,sqlite3,tkinter,unittest}/test
|
||||
rm -rf "$PYDIR"/distutils/{command,tests}
|
||||
rm -rf "$PYDIR"/config-3.*-x86_64-linux-gnu
|
||||
rm -rf "$PYDIR"/config-3.*-$LINUX_GNU_ARCH
|
||||
rm -rf "$PYDIR"/site-packages/{opt,pip,setuptools,wheel}
|
||||
rm -rf "$PYDIR"/site-packages/Cryptodome/SelfTest
|
||||
rm -rf "$PYDIR"/site-packages/{psutil,qrcode,websocket}/tests
|
||||
@@ -271,7 +307,7 @@ find -exec touch -h -d '2000-11-11T11:11:11+00:00' {} +
|
||||
info "creating the AppImage."
|
||||
(
|
||||
cd "$BUILDDIR"
|
||||
cp "$CACHEDIR/appimagetool" "$CACHEDIR/appimagetool_copy"
|
||||
cp "$CACHEDIR/appimagetool-$ARCH" "$CACHEDIR/appimagetool_copy"
|
||||
# zero out "appimage" magic bytes, as on some systems they confuse the linker
|
||||
sed -i 's|AI\x02|\x00\x00\x00|' "$CACHEDIR/appimagetool_copy"
|
||||
chmod +x "$CACHEDIR/appimagetool_copy"
|
||||
@@ -285,7 +321,7 @@ args=\$(echo "\$@" | sed -e 's/-mkfs-time 0//')
|
||||
"$BUILDDIR/squashfs-root/usr/bin/mksquashfs_orig" \$args
|
||||
EOF
|
||||
chmod +x "$BUILDDIR/squashfs-root/usr/bin/mksquashfs"
|
||||
env VERSION="$VERSION" ARCH=x86_64 ./squashfs-root/AppRun --runtime-file "$TYPE2_RUNTIME_REPO_DIR/runtime-x86_64" --no-appstream --verbose "$APPDIR" "$APPIMAGE"
|
||||
env VERSION="$VERSION" ARCH="$ARCH" ./squashfs-root/AppRun --runtime-file "$TYPE2_RUNTIME_REPO_DIR/runtime-$ARCH" --no-appstream --verbose "$APPDIR" "$APPIMAGE"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -13,12 +13,18 @@ TYPE2_RUNTIME_REPO="https://github.com/AppImage/type2-runtime.git"
|
||||
|
||||
. "$CONTRIB"/build_tools_util.sh
|
||||
|
||||
# Determine architecture (default to x86_64 if not set)
|
||||
ARCH="${ARCH:-x86_64}"
|
||||
if [ "$ARCH" != "x86_64" ] && [ "$ARCH" != "aarch64" ]; then
|
||||
fail "Unsupported ARCH: $ARCH. Must be x86_64 or aarch64"
|
||||
fi
|
||||
info "Building type2-runtime for architecture: $ARCH"
|
||||
|
||||
# Use a shared cache location that persists across fresh clones
|
||||
# This is critical for reproducible builds with ELECBUILD_COMMIT
|
||||
TYPE2_RUNTIME_REPO_DIR="$PROJECT_ROOT/contrib/build-linux/appimage/.cache/appimage/type2-runtime"
|
||||
if [ -f "$TYPE2_RUNTIME_REPO_DIR/runtime-x86_64" ] && [ -s "$TYPE2_RUNTIME_REPO_DIR/runtime-x86_64" ]; then
|
||||
info "type2-runtime already built ($(du -h "$TYPE2_RUNTIME_REPO_DIR/runtime-x86_64" | cut -f1)), skipping"
|
||||
if [ -f "$TYPE2_RUNTIME_REPO_DIR/runtime-$ARCH" ] && [ -s "$TYPE2_RUNTIME_REPO_DIR/runtime-$ARCH" ]; then
|
||||
info "type2-runtime already built ($(du -h "$TYPE2_RUNTIME_REPO_DIR/runtime-$ARCH" | cut -f1)), skipping"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -42,21 +48,21 @@ fi
|
||||
|
||||
info "building type2-runtime in build container..."
|
||||
cd "$TYPE2_RUNTIME_REPO_DIR/scripts/docker"
|
||||
env ARCH=x86_64 ./build-with-docker.sh || fail "Failed to build type2-runtime with docker"
|
||||
env ARCH="$ARCH" ./build-with-docker.sh || fail "Failed to build type2-runtime with docker"
|
||||
|
||||
# Verify the runtime was created in the expected location
|
||||
if [ ! -f "./runtime-x86_64" ]; then
|
||||
fail "Runtime binary was not created by docker build (expected at: $TYPE2_RUNTIME_REPO_DIR/scripts/docker/runtime-x86_64)"
|
||||
if [ ! -f "./runtime-$ARCH" ]; then
|
||||
fail "Runtime binary was not created by docker build (expected at: $TYPE2_RUNTIME_REPO_DIR/scripts/docker/runtime-$ARCH)"
|
||||
fi
|
||||
|
||||
mv "./runtime-x86_64" "$TYPE2_RUNTIME_REPO_DIR/"
|
||||
mv "./runtime-$ARCH" "$TYPE2_RUNTIME_REPO_DIR/"
|
||||
|
||||
# Verify runtime is valid (not empty)
|
||||
if [ ! -s "$TYPE2_RUNTIME_REPO_DIR/runtime-x86_64" ]; then
|
||||
if [ ! -s "$TYPE2_RUNTIME_REPO_DIR/runtime-$ARCH" ]; then
|
||||
fail "Runtime binary is empty or invalid"
|
||||
fi
|
||||
|
||||
# clean up the empty created 'out' dir to prevent permission issues
|
||||
rm -rf "$TYPE2_RUNTIME_REPO_DIR/out"
|
||||
|
||||
info "runtime build successful: $(sha256sum "$TYPE2_RUNTIME_REPO_DIR/runtime-x86_64")"
|
||||
info "runtime build successful: $(sha256sum "$TYPE2_RUNTIME_REPO_DIR/runtime-$ARCH")"
|
||||
|
||||
Reference in New Issue
Block a user