-
Notifications
You must be signed in to change notification settings - Fork 295
203 lines (188 loc) · 8.2 KB
/
Copy pathlinux.yml
File metadata and controls
203 lines (188 loc) · 8.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
name: Linux
on:
workflow_dispatch:
#push:
# branches: [ master ]
#
# Two separate builds rather than one universal binary, because there is no such
# thing on Linux: x86_64 and aarch64 are different instruction sets, and unlike
# Windows on ARM there is no emulation layer to fall back on. So each gets its
# own tarball.
#
# Both are built on Ubuntu 22.04 on purpose. The glibc a binary is linked
# against sets the oldest system it can run on, and 22.04 provides 2.35 - low
# enough for Raspberry Pi OS (Debian 12, glibc 2.36) while still satisfying
# Qt 6's own 2.34 requirement. Building on 24.04 would raise the floor to 2.39
# and the aarch64 build would then refuse to start on a Pi, which is the whole
# reason for choosing the older image. There is a step below that checks this
# rather than trusting it.
#
jobs:
build:
name: ${{ matrix.arch }}
runs-on: ${{ matrix.runner }}
#
# The two architectures use different Qt versions, and not by accident.
#
# Qt builds its official packages on a deliberately old base so the result
# runs widely - but only for x86_64. What each was actually built on:
#
# Qt 6.8.3 x86_64 RHEL 8.10 moc needs glibc 2.28
# Qt 6.11.1 x86_64 RHEL 9.6 moc needs glibc 2.34
# Qt 6.7.3 aarch64 Debian 11.6 moc needs 2.28, libQt6Core 2.30
# Qt 6.8.0+ aarch64 Ubuntu 24.04 moc needs 2.38, libQt6Core 2.35
#
# From 6.8.0 onwards every aarch64 release is built on Ubuntu 24.04, so its
# moc will not start on this runner - "libc.so.6: version GLIBC_2.38 not
# found". Only the *tools* are too new; the libraries need just 2.35. But a
# code generator that cannot run is fatal.
#
# 6.7.3 is therefore the newest official aarch64 build usable here, and it is
# comfortably above this project's Qt 6.5 minimum. If Qt ever publishes an
# aarch64 build on an older base again, raise this and drop the comment.
#
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runner: ubuntu-22.04
qt_host: linux
qt_arch: linux_gcc_64
qt_version: 6.8.3
- arch: aarch64
runner: ubuntu-22.04-arm
qt_host: linux_arm64
qt_arch: linux_gcc_arm64
qt_version: 6.7.3
env:
#
# Highest glibc the finished tarball may require. 2.36 is Raspberry Pi OS
# (Debian 12) and Debian 12 generally; going above it silently drops those
# targets, so the build fails instead.
#
MAX_GLIBC: "2.36"
steps:
- name: Checkout code
uses: actions/checkout@v4
#
# Only what TaskExplorer links directly needs a -dev package: libX11 for
# the window enumeration, the GL stubs that Qt6::OpenGL pulls in, and
# elfutils for the helper's stack unwinding.
#
# libcups2-dev is there for Qt6PrintSupport, whose CMake config refuses to
# load without Cups - qwt compiles qwt_plot_renderer.cpp, which uses
# QPrinter. It is a build-time dependency only: the finished binary does
# not link libQt6PrintSupport (the printing code is never pulled out of
# qwt's static archive), so nothing about the shipped bundle changes.
# Needed explicitly because the ARM runner image is slimmer than the x86
# one, which already had it - hence x86_64 configuring fine and aarch64
# failing on the same source tree.
#
# The runtime-only packages below are here so the deploy script has
# something to copy: Qt 6 will not start without libxcb-cursor, and most
# distributions do not install it or the xcb-util family by default.
#
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential cmake ninja-build pkg-config \
libx11-dev libgl1-mesa-dev libglx-dev libopengl-dev \
libcups2-dev \
libdw-dev libelf-dev \
libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
libxcb-render-util0 libxcb-util1 libxcb-xkb1 \
libxkbcommon0 libxkbcommon-x11-0
#
# Official Qt binaries rather than the distribution's: Ubuntu 22.04 ships
# Qt 6.2, and this project needs 6.5 or newer. Qt has published desktop
# aarch64 builds since 6.7, which is what makes the ARM job possible
# without building Qt from source.
#
#
# No `modules:` list: for Qt 6 the SVG module and the Linguist tools are
# part of the base package, not add-ons, and naming a module that does not
# exist in the repository makes the install fail outright.
#
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: ${{ matrix.qt_version }}
host: ${{ matrix.qt_host }}
target: desktop
arch: ${{ matrix.qt_arch }}
cache: true
- name: Configure
run: |
echo "building with Qt ${{ matrix.qt_version }} for ${{ matrix.arch }}"
cmake -S . -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DTE_BUNDLE_QT=ON
#
# The post-build step bundles Qt into Bin/linux-* and prints the glibc
# floor it ended up with; see Installer/README-portable.md.
#
- name: Build
run: cmake --build build -j$(nproc)
- name: Locate output
id: out
run: echo "dir=$(ls -d Bin/linux-*)" >> "$GITHUB_OUTPUT"
#
# The floor is the highest glibc requirement across every shipped object,
# not just the executables - a bundled libstdc++ or libdw from too new a
# host raises it. Checked here so a runner image change cannot quietly
# drop Raspberry Pi and Debian 12 support.
#
- name: Check glibc floor
working-directory: ${{ steps.out.outputs.dir }}
run: |
floor=$(for f in TaskExplorer TaskHelper lib/*.so* plugins/*/*.so; do
[ -f "$f" ] && objdump -T "$f" 2>/dev/null | grep -o 'GLIBC_[0-9.]*'
done | sed 's/GLIBC_//' | sort -uV | tail -1)
echo "bundle requires glibc $floor, limit is $MAX_GLIBC"
if [ "$(printf '%s\n%s\n' "$floor" "$MAX_GLIBC" | sort -V | tail -1)" != "$MAX_GLIBC" ]; then
echo "::error::bundle requires glibc $floor, above the $MAX_GLIBC limit -" \
"it would not run on Raspberry Pi OS or Debian 12." \
"Build on an older image, or see Installer/README-portable.md."
exit 1
fi
#
# Proves the bundle is self-contained before it ships: with the loader
# given no help, nothing may resolve to the runner's Qt, and nothing may
# be missing. Cheap, and it catches a broken RPATH or a library the deploy
# script failed to copy.
#
- name: Verify the bundle resolves against itself
working-directory: ${{ steps.out.outputs.dir }}
run: |
for bin in TaskExplorer TaskHelper; do
echo "--- $bin"
out=$(env -u LD_LIBRARY_PATH ldd "./$bin")
echo "$out" | grep -E 'libQt6|libdw|libelf|libstdc' || true
if echo "$out" | grep -q "not found"; then
echo "::error::$bin has unresolved libraries"; echo "$out" | grep "not found"; exit 1
fi
if echo "$out" | grep -q "/opt/hostedtoolcache.*libQt6"; then
echo "::error::$bin resolves Qt from the runner instead of the bundle"; exit 1
fi
done
#
# A single top-level directory inside the archive, so unpacking cannot
# scatter files into the current one.
#
- name: Package
id: pack
run: |
name="TaskExplorer-${{ github.ref_name }}-linux-${{ matrix.arch }}"
name="${name//\//-}"
mkdir -p "staging/TaskExplorer"
cp -a "${{ steps.out.outputs.dir }}/." "staging/TaskExplorer/"
tar -czf "$name.tar.gz" -C staging TaskExplorer
echo "file=$name.tar.gz" >> "$GITHUB_OUTPUT"
ls -lh "$name.tar.gz"
- name: Upload
uses: actions/upload-artifact@v4
with:
name: TaskExplorer_linux_${{ matrix.arch }}
path: ${{ steps.pack.outputs.file }}