Repository navigation
625 lines (557 loc) · 26.8 KB
/
Copy pathbuild-linux.yml
File metadata and controls
625 lines (557 loc) · 26.8 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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
name: Linux build
on:
workflow_dispatch:
inputs:
testnet:
description: 'Build testnet binaries (-DTESTNET=TRUE)'
type: boolean
default: false
# Also callable from build-all.yml, which fans mainnet and testnet
# builds out across all three platforms in a single run.
workflow_call:
inputs:
testnet:
description: 'Build testnet binaries (-DTESTNET=TRUE)'
type: boolean
default: false
ref:
description: 'Commit SHA or ref to build (defaults to the triggering commit)'
type: string
default: ''
permissions:
contents: read
env:
BOOST_VERSION: 1.84.0
BOOST_SHA256: cc4b893acf645c9d4b698e9a0f08ca8846aa5d6c68275c14c3e7949c24109454
OPENSSL_VERSION: 3.5.8
OPENSSL_SHA256: a8f84a39918ec6415ce765d9b429d313ba97b8143169c172e734b9514464f5b2
QT_VERSION: 6.8.3
LINUXDEPLOY_VERSION: 1-alpha-20251107-1
LINUXDEPLOY_QT_VERSION: 1-alpha-20250213-1
jobs:
build:
name: Linux ${{ matrix.arch }} (full)${{ inputs.testnet == true && ' (testnet)' || '' }}
runs-on: ${{ matrix.runner }}
timeout-minutes: 300
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: ubuntu-22.04
cmake_arch: x86-64
boost_arch: x86
openssl_target: linux-x86_64
qt_host: linux
qt_arch: linux_gcc_64
appimage_arch: x86_64
elf_machine: Advanced Micro Devices X86-64
baseline: Ubuntu 22.04 / glibc 2.35
linuxdeploy_sha256: c20cd71e3a4e3b80c3483cef793cda3f4e990aca14014d23c544ca3ce1270b4d
linuxdeploy_qt_sha256: 15106be885c1c48a021198e7e1e9a48ce9d02a86dd0a1848f00bdbf3c1c92724
- arch: arm64
runner: ubuntu-24.04-arm
cmake_arch: default
boost_arch: arm
openssl_target: linux-aarch64
qt_host: linux_arm64
qt_arch: linux_gcc_arm64
appimage_arch: aarch64
elf_machine: AArch64
baseline: Ubuntu 24.04 / glibc 2.39
linuxdeploy_sha256: 620095110d693282b8ebeb244a95b5e911cf8f65f76c88b4b47d16ae6346fcff
linuxdeploy_qt_sha256: bf1c24aff6d749b5cf423afad6f15abd4440f81dec1aab95706b25f6667cdcf1
env:
DEPS_DIR: ${{ github.workspace }}/_deps-linux
BUILD_DIR: ${{ github.workspace }}/build-linux
DIST_DIR: ${{ github.workspace }}/dist-linux
defaults:
run:
shell: bash
steps:
- name: Checkout (with submodules)
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: ${{ inputs.ref || github.sha }}
submodules: recursive
# src/version.cmake and libmdbx derive versions from Git history.
fetch-depth: 0
persist-credentials: false
- name: Install Linux build prerequisites
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential \
bzip2 \
ca-certificates \
curl \
desktop-file-utils \
file \
libbz2-dev \
libevent-dev \
libgl1-mesa-dev \
libicu-dev \
libminizip-dev \
libnss3 \
libxkbcommon-x11-0 \
libxcb-cursor0 \
patchelf \
perl \
pkg-config \
rsync \
zlib1g-dev
# restore/save are separate so successfully built dependencies enter the cache immediately even if a later Zano or packaging step fails
- name: Restore Boost and OpenSSL cache
id: deps-cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ${{ env.DEPS_DIR }}
key: deps-${{ matrix.runner }}-${{ matrix.arch }}-boost${{ env.BOOST_VERSION }}-openssl${{ env.OPENSSL_VERSION }}-linux-rtstatic-v2
- name: Build Boost and OpenSSL (static)
if: steps.deps-cache.outputs.cache-hit != 'true'
run: |
set -euo pipefail
jobs=$(nproc)
if (( jobs > 4 )); then jobs=4; fi
rm -rf "$DEPS_DIR"
mkdir -p "$DEPS_DIR/src"
cd "$DEPS_DIR/src"
openssl_archive="openssl-${OPENSSL_VERSION}.tar.gz"
curl --fail --location --retry 3 --output "$openssl_archive" \
"https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_VERSION}/${openssl_archive}"
echo "${OPENSSL_SHA256} ${openssl_archive}" | sha256sum --check --strict
tar -xzf "$openssl_archive"
pushd "openssl-${OPENSSL_VERSION}"
./Configure "${{ matrix.openssl_target }}" no-shared no-tests \
--prefix="$DEPS_DIR/openssl" \
--openssldir="$DEPS_DIR/openssl" \
--libdir=lib
make -s -j"$jobs"
make -s install_sw
install -m 0644 LICENSE.txt "$DEPS_DIR/openssl/LICENSE.txt"
popd
boost_underscore=${BOOST_VERSION//./_}
boost_archive="boost_${boost_underscore}.tar.bz2"
curl --fail --location --retry 3 --output "$boost_archive" \
"https://archives.boost.io/release/${BOOST_VERSION}/source/${boost_archive}"
echo "${BOOST_SHA256} ${boost_archive}" | sha256sum --check --strict
tar -xjf "$boost_archive"
pushd "boost_${boost_underscore}"
./bootstrap.sh \
--prefix="$DEPS_DIR/boost" \
--with-libraries=system,filesystem,thread,date_time,chrono,regex,serialization,atomic,program_options,locale,timer,log
# Zano's STATIC=TRUE configuration sets Boost_USE_STATIC_RUNTIME=ON.
./b2 -j"$jobs" -d1 \
architecture="${{ matrix.boost_arch }}" \
address-model=64 \
link=static \
runtime-link=static \
threading=multi \
variant=release \
install
install -m 0644 LICENSE_1_0.txt "$DEPS_DIR/boost/LICENSE_1_0.txt"
popd
rm -rf "$DEPS_DIR/src"
test -f "$DEPS_DIR/boost/lib/libboost_system.a"
test -f "$DEPS_DIR/openssl/lib/libcrypto.a"
- name: Verify Boost and OpenSSL installation
run: |
set -euo pipefail
test -f "$DEPS_DIR/boost/lib/libboost_system.a"
test -f "$DEPS_DIR/boost/LICENSE_1_0.txt"
grep -R --include='libboost_system-variant-*.cmake' -F '# runtime-link=static' \
"$DEPS_DIR/boost/lib/cmake/boost_system-${BOOST_VERSION}"
test -f "$DEPS_DIR/openssl/lib/libcrypto.a"
test -f "$DEPS_DIR/openssl/LICENSE.txt"
- name: Save Boost and OpenSSL cache
if: steps.deps-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ${{ env.DEPS_DIR }}
key: ${{ steps.deps-cache.outputs.cache-primary-key }}
- name: Set up Python for Qt installer
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
python-version: '3.13.3'
- name: Install Qt 6.8 (WebEngine)
uses: jurplel/install-qt-action/action@48d3ad6db93f3627c8ee7a0454bc6f3744f7e730 # v4
with:
version: ${{ env.QT_VERSION }}
host: ${{ matrix.qt_host }}
target: desktop
arch: ${{ matrix.qt_arch }}
modules: 'qtwebengine qtwebchannel qtpositioning qtserialport'
cache: true
cache-key-prefix: qt-${{ matrix.runner }}-${{ matrix.qt_arch }}
aqtversion: '==3.3.0'
py7zrversion: '==1.0.0'
- name: Configure (CMake, Release ${{ matrix.arch }})
run: |
set -euo pipefail
testnet=FALSE
if [[ "${{ inputs.testnet }}" == true ]]; then testnet=TRUE; fi
cmake -S . -B "$BUILD_DIR" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DTESTNET="$testnet" \
-DBUILD_GUI=TRUE \
-DBUILD_TESTS=FALSE \
-DUSE_PCH=FALSE \
-DSTATIC=TRUE \
-DARCH="${{ matrix.cmake_arch }}" \
-DBOOST_ROOT="$DEPS_DIR/boost" \
-DBOOST_LIBRARYDIR="$DEPS_DIR/boost/lib" \
-DOPENSSL_ROOT_DIR="$DEPS_DIR/openssl" \
-DOPENSSL_USE_STATIC_LIBS=TRUE \
-DCMAKE_PREFIX_PATH="$QT_ROOT_DIR"
- name: Build Zano applications
run: |
set -euo pipefail
# Keep the high-memory Qt WebEngine link serial, as in the legacy
# Linux release script; the CLI targets can safely use two jobs.
cmake --build "$BUILD_DIR" --parallel 2 \
--target daemon simplewallet connectivity_tool gateway_rpc_proxy
cmake --build "$BUILD_DIR" --parallel 1 --target Zano
- name: Verify ELF outputs and run CLI smoke checks
run: |
set -euo pipefail
binaries=(Zano zanod simplewallet connectivity_tool gateway_rpc_proxy)
for binary in "${binaries[@]}"; do
path="$BUILD_DIR/src/$binary"
test -x "$path"
file "$path"
readelf -h "$path" | grep -F "Machine:" | grep -F "${{ matrix.elf_machine }}"
if ldd "$path" | grep -F 'not found'; then
echo "::error::$binary has unresolved shared-library dependencies"
exit 1
fi
done
"$BUILD_DIR/src/zanod" --version
"$BUILD_DIR/src/simplewallet" --version
"$BUILD_DIR/src/connectivity_tool" --version
"$BUILD_DIR/src/gateway_rpc_proxy" --version
- name: Derive package version
run: |
set -euo pipefail
quoted_define() {
local name=$1
sed -nE "s/^#define[[:space:]]+${name}[[:space:]]+\"([^\"]+)\".*/\\1/p" src/version.h.in
}
major=$(quoted_define PROJECT_MAJOR_VERSION)
minor=$(quoted_define PROJECT_MINOR_VERSION)
revision=$(quoted_define PROJECT_REVISION)
build_no=$(sed -nE 's/^#define[[:space:]]+PROJECT_VERSION_BUILD_NO[[:space:]]+([0-9]+).*/\1/p' src/version.h.in)
commit=$(git rev-parse --short=7 HEAD)
if [[ -z "$major" || -z "$minor" || -z "$revision" || -z "$build_no" || -z "$commit" ]]; then
echo '::error::Could not derive the package version'
exit 1
fi
package_version="${major}.${minor}.${revision}.${build_no}-${commit}"
network_suffix=''
network_name=mainnet
if [[ "${{ inputs.testnet }}" == true ]]; then
network_suffix=-testnet
network_name=testnet
fi
{
echo "PACKAGE_VERSION=$package_version"
echo "PKG_TAG=${GITHUB_REF_NAME//\//-}${network_suffix}-v${major}.${minor}.${revision}.${build_no}[${commit}]"
echo "NETWORK_NAME=$network_name"
echo "CLI_BASENAME=zano-linux-${{ matrix.arch }}-cli${network_suffix}-${package_version}"
echo "GUI_BASENAME=zano-linux-${{ matrix.arch }}-gui${network_suffix}-${package_version}"
} >> "$GITHUB_ENV"
- name: Assemble CLI package
run: |
set -euo pipefail
mkdir -p "$DIST_DIR"
stage_root="$RUNNER_TEMP/zano-stage-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${{ matrix.arch }}"
cli_root="$stage_root/$CLI_BASENAME"
mkdir -p "$cli_root/licenses/source-tree"
echo "STAGE_ROOT=$stage_root" >> "$GITHUB_ENV"
for binary in zanod simplewallet connectivity_tool gateway_rpc_proxy; do
install -m 0755 "$BUILD_DIR/src/$binary" "$cli_root/$binary"
done
install -m 0644 LICENSE "$cli_root/LICENSE.txt"
install -m 0644 LICENSE "$cli_root/licenses/Zano.txt"
install -m 0644 "$DEPS_DIR/boost/LICENSE_1_0.txt" "$cli_root/licenses/Boost-1.0.txt"
install -m 0644 "$DEPS_DIR/openssl/LICENSE.txt" "$cli_root/licenses/OpenSSL.txt"
while IFS= read -r -d '' notice; do
destination="$cli_root/licenses/source-tree/$notice"
mkdir -p "$(dirname "$destination")"
cp "$notice" "$destination"
done < <(find contrib src/gui/qt-daemon/layout -type f \
\( -iname 'LICENSE' -o -iname 'LICENSE.*' -o -iname 'COPYING' -o -iname 'COPYING.*' \) -print0)
cat > "$cli_root/README-LINUX.txt" <<EOF
Zano Linux ${{ matrix.arch }} CLI package
Network: $NETWORK_NAME
Version: $PACKAGE_VERSION
Runtime baseline: ${{ matrix.baseline }}
Programs:
zanod full-node daemon
simplewallet CLI wallet and wallet RPC mode
connectivity_tool connectivity diagnostics
gateway_rpc_proxy gateway RPC proxy
Boost, OpenSSL, libgcc, and libstdc++ are linked statically. glibc and
core Linux libraries remain system dependencies. License texts are
under licenses/.
EOF
cat > "$cli_root/THIRD-PARTY-NOTICES.txt" <<'EOF'
This distribution contains Zano and third-party components.
License texts shipped by Zano, Boost, OpenSSL, and bundled source-tree
dependencies are collected under licenses/.
EOF
cat > "$cli_root/BUILD-INFO.txt" <<EOF
Source commit: $GITHUB_SHA
Source ref: $GITHUB_REF
Configuration: Release
Platform: Linux ${{ matrix.arch }}
Runner/runtime baseline: ${{ matrix.baseline }}
Boost: $BOOST_VERSION (static)
OpenSSL: $OPENSSL_VERSION (static)
Qt: not required by this CLI archive
Network: $NETWORK_NAME
Debug symbols: embedded in the ELF binaries
Signing: none (GitHub records an artifact digest on upload)
EOF
tar -cjf "$DIST_DIR/$CLI_BASENAME.tar.bz2" -C "$stage_root" "$CLI_BASENAME"
- name: Download and verify AppImage packaging tools
env:
TOOLS_DIR: ${{ runner.temp }}/zano-appimage-tools
run: |
set -euo pipefail
mkdir -p "$TOOLS_DIR"
linuxdeploy="$TOOLS_DIR/linuxdeploy-${{ matrix.appimage_arch }}.AppImage"
qt_plugin="$TOOLS_DIR/linuxdeploy-plugin-qt-${{ matrix.appimage_arch }}.AppImage"
curl --fail --location --retry 3 --output "$linuxdeploy" \
"https://github.com/linuxdeploy/linuxdeploy/releases/download/${LINUXDEPLOY_VERSION}/linuxdeploy-${{ matrix.appimage_arch }}.AppImage"
echo "${{ matrix.linuxdeploy_sha256 }} $linuxdeploy" | sha256sum --check --strict
curl --fail --location --retry 3 --output "$qt_plugin" \
"https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/${LINUXDEPLOY_QT_VERSION}/linuxdeploy-plugin-qt-${{ matrix.appimage_arch }}.AppImage"
echo "${{ matrix.linuxdeploy_qt_sha256 }} $qt_plugin" | sha256sum --check --strict
chmod 0755 "$linuxdeploy" "$qt_plugin"
- name: Assemble Qt 6 GUI AppImage
env:
TOOLS_DIR: ${{ runner.temp }}/zano-appimage-tools
run: |
set -euo pipefail
appdir="$RUNNER_TEMP/$GUI_BASENAME.AppDir"
rm -rf "$appdir"
mkdir -p \
"$appdir/usr/bin" \
"$appdir/usr/share/applications" \
"$appdir/usr/share/icons/hicolor/scalable/apps" \
"$appdir/usr/share/icons/hicolor/256x256/apps" \
"$appdir/usr/share/doc/zano"
for binary in Zano zanod simplewallet connectivity_tool gateway_rpc_proxy; do
install -m 0755 "$BUILD_DIR/src/$binary" "$appdir/usr/bin/$binary"
done
rsync -a \
--exclude less \
--exclude package.json \
--exclude gulpfile.js \
src/gui/qt-daemon/layout/html/ "$appdir/usr/bin/html/"
test -f "$appdir/usr/bin/html/index.html"
install -m 0644 utils/Zano.desktop "$appdir/usr/share/applications/Zano.desktop"
sed -i 's/^Terminal=.*/Terminal=false/' "$appdir/usr/share/applications/Zano.desktop"
printf '%s\n' 'Exec=Zano %u' 'StartupWMClass=Zano' >> "$appdir/usr/share/applications/Zano.desktop"
install -m 0644 resources/app_icon.svg "$appdir/usr/share/icons/hicolor/scalable/apps/Zano.svg"
install -m 0644 resources/app_icon_256.png "$appdir/usr/share/icons/hicolor/256x256/apps/Zano.png"
cp -a "$STAGE_ROOT/$CLI_BASENAME/licenses" "$appdir/usr/share/doc/zano/licenses"
install -m 0644 LICENSE "$appdir/usr/share/doc/zano/LICENSE.txt"
install -m 0644 "$STAGE_ROOT/$CLI_BASENAME/BUILD-INFO.txt" "$appdir/usr/share/doc/zano/BUILD-INFO.txt"
install -m 0644 "$STAGE_ROOT/$CLI_BASENAME/THIRD-PARTY-NOTICES.txt" \
"$appdir/usr/share/doc/zano/THIRD-PARTY-NOTICES.txt"
linux_runtime_license_root="$appdir/usr/share/doc/zano/licenses/Linux-runtime"
mkdir -p "$linux_runtime_license_root"
install -m 0644 /usr/share/doc/libevent-dev/copyright \
"$linux_runtime_license_root/libevent.txt"
install -m 0644 /usr/share/doc/libminizip-dev/copyright \
"$linux_runtime_license_root/minizip.txt"
qt_license_root="$appdir/usr/share/doc/zano/licenses/Qt"
mkdir -p "$qt_license_root/kit" "$qt_license_root/kit-files"
while IFS= read -r -d '' directory; do
relative=${directory#"$QT_ROOT_DIR"/}
destination="$qt_license_root/kit/$relative"
mkdir -p "$destination"
cp -a "$directory"/. "$destination"/
done < <(find "$QT_ROOT_DIR" -type d -name LICENSES -print0)
while IFS= read -r -d '' notice; do
relative=${notice#"$QT_ROOT_DIR"/}
destination="$qt_license_root/kit-files/$relative"
mkdir -p "$(dirname "$destination")"
cp "$notice" "$destination"
done < <(find "$QT_ROOT_DIR" -type f \
\( -iname 'LICENSE' -o -iname 'LICENSE.*' -o -iname 'COPYING' -o -iname 'COPYING.*' -o -iname 'licenseInfo.*' \) -print0)
if [[ -d utils/linux_licenses/qt ]]; then
mkdir -p "$qt_license_root/release-approved"
cp -a utils/linux_licenses/qt/. "$qt_license_root/release-approved"/
else
echo '::warning title=Qt release licensing::No curated utils/linux_licenses/qt bundle is present; review Qt/WebEngine obligations before publishing'
fi
cat > "$qt_license_root/README-RELEASE-LICENSING.txt" <<EOF
Qt / Qt WebEngine release licensing checkpoint
Files under kit/ and kit-files/ were copied from the Qt $QT_VERSION
binary kit used for this build. They are retained when available, but
are not assumed to be a complete Chromium/Qt WebEngine notice bundle.
Before public release, review the applicable Qt commercial or
open-source agreement and WebEngine third-party notices. An approved
distributable notice bundle can be committed under
utils/linux_licenses/qt and will then appear under release-approved/.
References:
https://doc.qt.io/qt-6.8/licenses-used-in-qt.html
https://doc.qt.io/qt-6.8/qtwebengine-licensing.html
EOF
cat > "$appdir/usr/share/doc/zano/THIRD-PARTY-NOTICES.txt" <<'EOF'
This distribution contains Zano and third-party components.
License texts shipped by Zano, Boost, OpenSSL, the Qt binary kit,
bundled Linux runtime libraries, and source-tree dependencies are
collected under licenses/. Qt WebEngine contains Chromium-derived
third-party software; see
licenses/Qt/README-RELEASE-LICENSING.txt before publishing.
EOF
cat > "$appdir/usr/share/doc/zano/BUILD-INFO.txt" <<EOF
Source commit: $GITHUB_SHA
Source ref: $GITHUB_REF
Configuration: Release
Platform: Linux ${{ matrix.arch }}
Runner/runtime baseline: ${{ matrix.baseline }}
Boost: $BOOST_VERSION (static)
OpenSSL: $OPENSSL_VERSION (static)
Qt: $QT_VERSION / ${{ matrix.qt_arch }}
Linux runtime libraries: Qt WebEngine dependencies bundled by linuxdeploy
Network: $NETWORK_NAME
Debug symbols: embedded in the ELF binaries
Signing: none (GitHub records an artifact digest on upload)
EOF
cat > "$appdir/usr/share/doc/zano/README-LINUX.txt" <<EOF
Zano Linux ${{ matrix.arch }} GUI AppImage
Network: $NETWORK_NAME
Version: $PACKAGE_VERSION
Runtime baseline: ${{ matrix.baseline }}
The AppImage contains the Zano Qt 6/WebEngine desktop wallet plus
zanod, simplewallet, connectivity_tool, and gateway_rpc_proxy.
Select a CLI program with --exec=<name>; pass its arguments with
--exec-args='<arguments>'. License texts are under usr/share/doc/zano/.
EOF
linuxdeploy="$TOOLS_DIR/linuxdeploy-${{ matrix.appimage_arch }}.AppImage"
export APPIMAGE_EXTRACT_AND_RUN=1
export ARCH="${{ matrix.appimage_arch }}"
export NO_STRIP=1
export OUTPUT="$DIST_DIR/$GUI_BASENAME.AppImage"
export QMAKE="$QT_ROOT_DIR/bin/qmake"
export PATH="$QT_ROOT_DIR/bin:$PATH"
export LD_LIBRARY_PATH="$QT_ROOT_DIR/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
mapfile -t qt_runtime_sonames < <(
ldd "$BUILD_DIR/src/Zano" |
awk '$1 ~ /^libevent-2[.]1[.]so[.]/ || $1 ~ /^libminizip[.]so[.]/ { print $1 }'
)
# NSS loads softokn/freebl/dbm modules dynamically, so ldd alone misses them.
# Bundle the complete native NSS/NSPR library set, including package aliases only once.
native_arch=$(dpkg --print-architecture)
nss_package_files=$(dpkg-query -L "libnss3:$native_arch" "libnspr4:$native_arch")
mapfile -t nss_runtime_libraries < <(
printf '%s\n' "$nss_package_files" |
awk -F/ '$NF ~ /^lib.*[.]so$/ && !seen[$NF]++ { print }'
)
test "${#nss_runtime_libraries[@]}" -gt 0
nss_library_args=()
for library in "${nss_runtime_libraries[@]}"; do
nss_library_args+=(--library "$library")
done
"$linuxdeploy" \
--appdir "$appdir" \
"${nss_library_args[@]}" \
--executable "$appdir/usr/bin/Zano" \
--executable "$appdir/usr/bin/zanod" \
--executable "$appdir/usr/bin/simplewallet" \
--executable "$appdir/usr/bin/connectivity_tool" \
--executable "$appdir/usr/bin/gateway_rpc_proxy" \
--desktop-file "$appdir/usr/share/applications/Zano.desktop" \
--icon-file "$appdir/usr/share/icons/hicolor/256x256/apps/Zano.png" \
--custom-apprun utils/Zano_appimage_wrapper.sh \
--plugin qt \
--output appimage
test -x "$OUTPUT"
file "$OUTPUT"
readelf -h "$OUTPUT" | grep -F "Machine:" | grep -F "${{ matrix.elf_machine }}"
test -x "$appdir/AppRun"
webengine_process=$(find "$appdir" -type f -name QtWebEngineProcess -print -quit)
test -n "$webengine_process"
test -x "$webengine_process"
readelf -h "$webengine_process" | grep -F "Machine:" | grep -F "${{ matrix.elf_machine }}"
find "$appdir" -type f -name icudtl.dat -print -quit | grep -q .
find "$appdir" -type d -name qtwebengine_locales -print -quit | grep -q .
for soname in "${qt_runtime_sonames[@]}"; do
if ! find "$appdir/usr/lib" -name "${soname}*" -print -quit | grep -q .; then
echo "::error::$soname was not bundled in the AppDir"
exit 1
fi
done
nss_runtime_files=()
for library in "${nss_runtime_libraries[@]}"; do
bundled_library="$appdir/usr/lib/${library##*/}"
if [[ ! -f "$bundled_library" ]]; then
echo "::error::NSS/NSPR library ${library##*/} was not bundled in the AppDir"
exit 1
fi
nss_runtime_files+=("$bundled_library")
done
xcb_plugin=$(find "$appdir" -type f -name libqxcb.so -path '*/platforms/*' -print -quit)
test -n "$xcb_plugin"
readelf -h "$xcb_plugin" | grep -F "Machine:" | grep -F "${{ matrix.elf_machine }}"
unset LD_LIBRARY_PATH
deployed_zano_ldd=$(ldd "$appdir/usr/bin/Zano")
for soname in "${qt_runtime_sonames[@]}"; do
if ! printf '%s\n' "$deployed_zano_ldd" | grep -F "$soname => $appdir/" >/dev/null; then
echo "::error::$soname was not resolved from inside the AppDir"
exit 1
fi
done
for runtime_file in "$appdir/usr/bin/Zano" "$webengine_process" "$xcb_plugin" "${nss_runtime_files[@]}"; do
runtime_ldd=$(ldd "$runtime_file")
if printf '%s\n' "$runtime_ldd" | grep -F 'not found'; then
echo "::error::$runtime_file has unresolved shared-library dependencies"
exit 1
fi
for library in "${nss_runtime_libraries[@]}"; do
soname=${library##*/}
if printf '%s\n' "$runtime_ldd" | grep -F "$soname => " >/dev/null &&
! printf '%s\n' "$runtime_ldd" | grep -F "$soname => $appdir/" >/dev/null; then
echo "::error::$runtime_file resolves NSS/NSPR library $soname outside the AppDir"
exit 1
fi
done
done
for binary in Zano zanod simplewallet connectivity_tool gateway_rpc_proxy; do
if ldd "$appdir/usr/bin/$binary" | grep -F 'not found'; then
echo "::error::Deployed $binary has unresolved shared-library dependencies"
exit 1
fi
done
- name: Write workflow summary
run: |
{
echo "### Linux ${{ matrix.arch }} build"
echo
echo "- Network: $NETWORK_NAME"
echo "- Runtime baseline: ${{ matrix.baseline }}"
echo "- CLI: \`$CLI_BASENAME.tar.bz2\`"
echo "- GUI: \`$GUI_BASENAME.AppImage\`"
echo "- Linux platform signing: not configured"
echo "- Release checksums: GitHub shows an artifact digest; no separate checksum artifact is produced"
} >> "$GITHUB_STEP_SUMMARY"
- name: Upload CLI package
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: zano-linux-${{ matrix.arch }}-cli-${{ env.PKG_TAG }}
path: dist-linux/zano-linux-${{ matrix.arch }}-cli*.tar.bz2
if-no-files-found: error
compression-level: 0
- name: Upload GUI AppImage
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: zano-linux-${{ matrix.arch }}-gui-${{ env.PKG_TAG }}
path: dist-linux/zano-linux-${{ matrix.arch }}-gui*.AppImage
if-no-files-found: error
compression-level: 0