Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0265f2b

Browse files
committed
Set up ARM builds with QEMU and Docker
This commit allows us to provide both 32-bit and 64-bit ARM binaries for our users.
1 parent ae11d7b commit 0265f2b

File tree

9 files changed

+285
-181
lines changed

9 files changed

+285
-181
lines changed

.github/workflows/main.yml

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,48 +12,44 @@ jobs:
1212
build-and-test:
1313
strategy:
1414
matrix:
15-
ARCH: [x86_64, i386]
16-
BUILD_TYPE: [appimage, coverage]
15+
ARCH: [x86_64, i386, armhf, aarch64]
16+
BUILD_TYPE: ["appimage"]
1717
USE_STATIC_RUNTIME: [""]
18+
1819
include:
20+
# test build
21+
- ARCH: x86_64
22+
DOCKER_ARCH: amd64
23+
BUILD_TYPE: coverage
24+
25+
# experimental build
1926
- ARCH: x86_64
2027
BUILD_TYPE: appimage
2128
USE_STATIC_RUNTIME: 1
29+
2230
fail-fast: false
2331

24-
name: ${{ matrix.BUILD_TYPE }} ${{ matrix.ARCH }} static=${{ matrix.USE_STATIC_RUNTIME }}
32+
name: ${{ matrix.BUILD_TYPE }} ${{ matrix.ARCH }} static_runtime=${{ matrix.USE_STATIC_RUNTIME }}
33+
# Ubuntu 22.04 with qemu-static and ldd is a bad combination apparently
2534
runs-on: ubuntu-20.04
2635

2736
env:
2837
ARCH: ${{ matrix.ARCH }}
2938
BUILD_TYPE: ${{ matrix.BUILD_TYPE }}
3039
USE_STATIC_RUNTIME: ${{ matrix.USE_STATIC_RUNTIME }}
40+
# make sure to always(!) pull the base image
41+
UPDATE: 1
3142

3243
steps:
3344
- uses: actions/checkout@v3
3445
with:
3546
submodules: recursive
3647

37-
- name: Install dependencies (x86_64)
38-
if: matrix.ARCH == 'x86_64'
39-
run: |
40-
sudo apt-get update
41-
sudo apt-get install -y gcovr libmagic-dev libjpeg-dev libpng-dev cimg-dev libfuse2
48+
- name: Set up QEMU integration for Docker
49+
run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
4250

43-
- name: Install dependencies (i386)
44-
if: matrix.ARCH == 'i386'
45-
run: |
46-
sudo dpkg --add-architecture i386
47-
sudo apt-get update
48-
sudo apt-get install -y gcovr libmagic-dev:i386 libjpeg-dev:i386 libpng-dev:i386 cimg-dev gcc-multilib g++-multilib libfuse2:i386
49-
50-
- name: Test coverage
51-
run: bash -ex ci/test-coverage.sh
52-
if: matrix.BUILD_TYPE == 'coverage'
53-
54-
- name: Build, test and build AppImage
55-
run: bash -ex ci/build.sh
56-
if: matrix.BUILD_TYPE != 'coverage'
51+
- name: Build
52+
run: bash ci/build-in-docker.sh
5753

5854
- name: Archive artifacts
5955
uses: actions/upload-artifact@v2

ci/build-in-docker.sh

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#! /bin/bash
2+
3+
log_message() {
4+
color="$1"
5+
shift
6+
if [ -t 0 ]; then tput setaf "$color"; fi
7+
if [ -t 0 ]; then tput bold; fi
8+
echo "$@"
9+
if [ -t 0 ]; then tput sgr0; fi
10+
}
11+
info() {
12+
log_message 2 "[info] $*"
13+
}
14+
warning() {
15+
log_message 3 "[warning] $*"
16+
}
17+
error() {
18+
log_message 1 "[error] $*"
19+
}
20+
21+
if [[ "$ARCH" == "" ]]; then
22+
error "Usage: env ARCH=... bash $0"
23+
exit 2
24+
fi
25+
set -euo pipefail
26+
27+
this_dir="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")"
28+
29+
case "$ARCH" in
30+
x86_64)
31+
docker_arch=amd64
32+
;;
33+
i386)
34+
docker_arch=i386
35+
;;
36+
armhf)
37+
docker_arch=arm32v7
38+
;;
39+
aarch64)
40+
docker_arch=arm64v8
41+
;;
42+
*)
43+
echo "Unsupported \$ARCH: $ARCH"
44+
exit 3
45+
;;
46+
esac
47+
48+
# first, we need to build the image
49+
# we always attempt to build it, it will only be rebuilt if Docker detects changes
50+
# optionally, we'll pull the base image beforehand
51+
info "Building Docker image for $ARCH (Docker arch: $docker_arch)"
52+
53+
build_args=()
54+
if [[ "${UPDATE:-}" == "" ]]; then
55+
warning "\$UPDATE not set, base image will not be pulled!"
56+
else
57+
build_args+=("--pull")
58+
fi
59+
60+
image_tag="linuxdeploy-build:$ARCH"
61+
62+
docker build \
63+
--build-arg ARCH="$ARCH" \
64+
--build-arg docker_arch="$docker_arch" \
65+
"${build_args[@]}" \
66+
-t "$image_tag" \
67+
"$this_dir"/docker
68+
69+
docker_args=()
70+
# only if there's more than 1G of free space in RAM, we can build in a RAM disk
71+
if [[ "${GITHUB_ACTIONS:-}" != "" ]]; then
72+
warning "Building on GitHub actions, which does not support --tmpfs flag -> building on regular disk"
73+
elif [[ "$(free -m | grep "Mem:" | awk '{print $4}')" -gt 1024 ]]; then
74+
info "Host system has enough free memory -> building in RAM disk"
75+
docker_args+=(
76+
"--tmpfs"
77+
"/docker-ramdisk:exec,mode=777"
78+
)
79+
else
80+
warning "Host system does not have enough free memory -> building on regular disk"
81+
fi
82+
83+
if [[ "${BUILD_TYPE:-}" == "coverage" ]]; then
84+
build_script="ci/test-coverage.sh"
85+
else
86+
build_script="ci/build.sh"
87+
fi
88+
89+
90+
if [ -t 1 ]; then
91+
# needed on unixoid platforms to properly terminate the docker run process with Ctrl-C
92+
docker_args+=("-t")
93+
fi
94+
95+
DOCKER_OPTS=()
96+
# fix for https://stackoverflow.com/questions/51195528/rcc-error-in-resource-qrc-cannot-find-file-png
97+
if [ "${CI:-}" != "" ]; then
98+
docker_args+=(
99+
"--security-opt"
100+
"seccomp:unconfined"
101+
)
102+
fi
103+
104+
# run the build with the current user to
105+
# a) make sure root is not required for builds
106+
# b) allow the build scripts to "mv" the binaries into the /out directory
107+
uid="${UID:-"$(id -u)"}"
108+
info "Running build with uid $uid"
109+
docker run \
110+
--rm \
111+
-i \
112+
-e GITHUB_RUN_NUMBER \
113+
-e ARCH \
114+
-e BUILD_TYPE \
115+
-e USE_STATIC_RUNTIME \
116+
-e CI \
117+
--user "$uid" \
118+
"${docker_args[@]}" \
119+
-v "$(readlink -f "$this_dir"/..):/ws" \
120+
-w /ws \
121+
"$image_tag" \
122+
bash -xc "$build_script"

ci/build-static-patchelf.sh

Lines changed: 0 additions & 62 deletions
This file was deleted.

ci/build.sh

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
#! /bin/bash
22

3-
set -e
4-
set -x
3+
set -euxo pipefail
54

65
# use RAM disk if possible
7-
if [ "$CI" == "" ] && [ -d /dev/shm ]; then
8-
TEMP_BASE=/dev/shm
6+
if [ -d /docker-ramdisk ]; then
7+
TEMP_BASE=/docker-ramdisk
98
else
109
TEMP_BASE=/tmp
1110
fi
@@ -26,49 +25,43 @@ old_cwd="$(readlink -f "$PWD")"
2625

2726
pushd "$build_dir"
2827

28+
# work around ninja colors bug
2929
extra_cmake_args=()
30-
31-
case "$ARCH" in
32-
"x86_64")
33-
;;
34-
"i386")
35-
echo "Enabling x86_64->i386 cross-compile toolchain"
36-
extra_cmake_args=("-DCMAKE_TOOLCHAIN_FILE=$repo_root/cmake/toolchains/i386-linux-gnu.cmake" "-DUSE_SYSTEM_CIMG=OFF")
37-
;;
38-
*)
39-
echo "Architecture not supported: $ARCH" 1>&2
40-
exit 1
41-
;;
42-
esac
43-
44-
# fetch up-to-date CMake
45-
mkdir cmake-prefix
46-
wget -O- https://github.com/Kitware/CMake/releases/download/v3.18.1/cmake-3.18.1-Linux-x86_64.tar.gz | tar -xz -C cmake-prefix --strip-components=1
47-
export PATH="$(readlink -f cmake-prefix/bin):$PATH"
48-
cmake --version
30+
if [ -t 0 ]; then
31+
extra_cmake_args+=(
32+
"-DCMAKE_C_FLAGS=-fdiagnostics-color=always"
33+
"-DCMAKE_CXX_FLAGS=-fdiagnostics-color=always"
34+
)
35+
fi
4936

5037
# configure build for AppImage release
51-
cmake "$repo_root" -DSTATIC_BUILD=On -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=RelWithDebInfo "${extra_cmake_args[@]}"
52-
53-
make -j"$(nproc)"
38+
cmake \
39+
-G Ninja \
40+
"$repo_root" \
41+
-DSTATIC_BUILD=ON \
42+
-DCMAKE_INSTALL_PREFIX=/usr \
43+
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
44+
"${extra_cmake_args[@]}"
5445

55-
# build patchelf
56-
"$repo_root"/ci/build-static-patchelf.sh "$(readlink -f out/)"
57-
patchelf_path="$(readlink -f out/usr/bin/patchelf)"
46+
nprocs="$(nproc)"
47+
[[ "${CI:-}" == "" ]] && [[ "$nprocs" -gt 2 ]] && nprocs="$(nproc --ignore=1)"
5848

59-
# build custom strip
60-
"$repo_root"/ci/build-static-binutils.sh "$(readlink -f out/)"
61-
strip_path="$(readlink -f out/usr/bin/strip)"
62-
63-
# use tools we just built for linuxdeploy test run
64-
PATH="$(readlink -f out/usr/bin):$PATH"
65-
export PATH
49+
ninja -j"$nprocs" -v
6650

6751
## Run Unit Tests
6852
ctest -V
6953

7054
# args are used more than once
71-
linuxdeploy_args=("--appdir" "AppDir" "-e" "bin/linuxdeploy" "-i" "$repo_root/resources/linuxdeploy.png" "-d" "$repo_root/resources/linuxdeploy.desktop" "-e" "$patchelf_path" "-e" "$strip_path")
55+
patchelf_path="$(which patchelf)"
56+
strip_path="$(which strip)"
57+
linuxdeploy_args=(
58+
--appdir AppDir
59+
-e bin/linuxdeploy
60+
-i "$repo_root/resources/linuxdeploy.png"
61+
-d "$repo_root/resources/linuxdeploy.desktop"
62+
-e "$patchelf_path"
63+
-e "$strip_path"
64+
)
7265

7366
# deploy patchelf which is a dependency of linuxdeploy
7467
bin/linuxdeploy "${linuxdeploy_args[@]}"
@@ -83,18 +76,20 @@ git clone --recursive https://github.com/linuxdeploy/linuxdeploy-plugin-appimage
8376
bash linuxdeploy-plugin-appimage/ci/build-bundle.sh
8477
mv linuxdeploy-plugin-appimage-bundle AppDir/plugins/linuxdeploy-plugin-appimage
8578

86-
ln -s ../../plugins/linuxdeploy-plugin-appimage/AppRun AppDir/usr/bin/linuxdeploy-plugin-appimage
79+
ln -s ../../plugins/linuxdeploy-plugin-appimage/usr/bin/linuxdeploy-plugin-appimage AppDir/usr/bin/linuxdeploy-plugin-appimage
8780

8881
# interpreted by linuxdeploy-plugin-appimage
8982
export UPD_INFO="gh-releases-zsync|linuxdeploy|linuxdeploy|continuous|linuxdeploy-$ARCH.AppImage.zsync"
9083
export OUTPUT="linuxdeploy-$ARCH.AppImage"
9184

9285
# special set of builds using a different experimental runtime, used for testing purposes
93-
if [[ "$USE_STATIC_RUNTIME" != "" ]]; then
86+
if [[ "${USE_STATIC_RUNTIME:-}" != "" ]]; then
87+
custom_runtime_url="https://github.com/AppImage/type2-runtime/releases/download/continuous/runtime-$ARCH"
88+
wget "$custom_runtime_url"
89+
runtime_filename="$(echo "$custom_runtime_url" | rev | cut -d/ -f1 | rev)"
90+
LDAI_RUNTIME_FILE="$(readlink -f "$runtime_filename")"
91+
export LDAI_RUNTIME_FILE
9492
export OUTPUT="linuxdeploy-static-$ARCH.AppImage"
95-
wget https://github.com/AppImage/type2-runtime/releases/download/continuous/runtime-"$ARCH"
96-
runtime_filename="$(echo "$CUSTOM_RUNTIME_URL" | rev | cut -d/ -f1 | rev)"
97-
export LDAI_RUNTIME_FILE"$(readlink -f "$runtime_filename")"
9893
fi
9994

10095
# build AppImage using plugin
@@ -103,6 +98,9 @@ AppDir/usr/bin/linuxdeploy-plugin-appimage --appdir AppDir/
10398
# rename AppImage to avoid "Text file busy" issues when using it to create another one
10499
mv "$OUTPUT" test.AppImage
105100

101+
# qemu is not happy about the AppImage type 2 magic bytes, so we need to "fix" that
102+
dd if=/dev/zero bs=1 count=3 seek=8 conv=notrunc of=test.AppImage
103+
106104
# verify that the resulting AppImage works
107105
./test.AppImage "${linuxdeploy_args[@]}"
108106

0 commit comments

Comments
 (0)