Skip to content

Linux release build #651

Linux release build

Linux release build #651

Workflow file for this run

env:
TCL_VERSION: '8.6'
SQLITE_VERSION: '3530200'
PYTHON_VERSION: '3.13'
PORTABLE_DIR: ${{ github.workspace }}/output/portable/Letos
ICU_VERSION: '73.2'
ICU_URL: 'https://github.com/unicode-org/icu/releases/download/release-73-2/icu4c-73_2-src.tgz'
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
name: Linux release build
on:
workflow_dispatch:
inputs:
target:
description: "Build target"
type: choice
options:
- "all"
- "x64"
- "arm64"
required: false
default: "all"
use_ccache:
description: 'Use ccache (for workflow debugging only!)'
required: false
type: boolean
DEBUG:
description: 'Enable workflow debug messages'
required: false
type: boolean
default: false
debug_ssh:
description: "Open SSH tunnel at the end"
type: boolean
default: false
debug_on_failure:
description: "Open SSH tunnel if job fails"
type: boolean
default: false
schedule:
- cron: '30 3 * * 1' # run at 3:30 AM UTC every Monday
jobs:
generate:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set.outputs.matrix }}
steps:
- id: set
run: |
MATRIX_X64='{
"OS": "ubuntu-22.04",
"TARGET_ARCH": "x86_64",
"QT_VERSION": "6.11.1",
"QT_ARCH": "linux_gcc_64",
"QT_HOST": "linux",
"LIBSSL_DIR_URL": "http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/",
"LIBSSL_DEB": "libssl1.1_1.1.1f-1ubuntu2.24_amd64.deb",
"APPIMAGE_URL": "https://github.com/AppImage/appimagetool/releases/download/1.9.1/appimagetool-x86_64.AppImage",
"PYTHON_ARCH": "x64",
"SQLITE_ARCH": "x64",
"OUTPUT_FILE_ARCH": "x64"
}'
# Qt 6.7 for Linux on ARM, as newer versions of Qt for ARM require Ubuntu 24 (and its newer glibc)
MATRIX_ARM64='{
"OS": "ubuntu-22.04-arm",
"TARGET_ARCH": "aarch64",
"QT_VERSION": "6.7.3",
"QT_ARCH": "linux_gcc_arm64",
"QT_HOST": "linux_arm64",
"LIBSSL_DIR_URL": "http://ports.ubuntu.com/pool/main/o/openssl/",
"LIBSSL_DEB": "libssl1.1_1.1.1f-1ubuntu2.24_arm64.deb",
"APPIMAGE_URL": "https://github.com/AppImage/appimagetool/releases/download/1.9.1/appimagetool-aarch64.AppImage",
"PYTHON_ARCH": "arm64",
"SQLITE_ARCH": "arm",
"OUTPUT_FILE_ARCH": "arm64"
}'
if [ "${{ inputs.target }}" = "x64" ]; then
matrix="[$MATRIX_X64]"
elif [ "${{ inputs.target }}" = "arm64" ]; then
matrix="[$MATRIX_ARM64]"
else
matrix="[$MATRIX_X64,$MATRIX_ARM64]"
fi
{
echo "matrix<<EOF"
echo "$matrix"
echo "EOF"
} >> $GITHUB_OUTPUT
build:
needs: generate
strategy:
matrix:
include: ${{ fromJson(needs.generate.outputs.matrix) }}
runs-on: ${{ matrix.OS }}
steps:
- uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: ${{ matrix.PYTHON_ARCH }}
- name: Update APT metadata
run: sudo apt-get update
# CMake files in Qt 6.7 have bugged dependency on Cups headers, making them mandatory in the OS.
# It's easy and fast to install it.
- name: Workaround for Qt 6.7.x CUPS bug
run: sudo apt-get install libcups2-dev
- name: Qt installation dir
id: qt-installation-dir
run: |
#set -x
#ls -l ${{ github.workspace }}/..
echo "DIR=$(readlink -f ${{ github.workspace }}/..)" >> $GITHUB_OUTPUT
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
cache: true
version: ${{ matrix.QT_VERSION }}
host: ${{ matrix.QT_HOST }}
arch: '${{ matrix.QT_ARCH }}'
dir: '${{ steps.qt-installation-dir.outputs.DIR }}'
setup-python: 'false'
extra: '--external 7z'
modules: 'qtimageformats'
- name: Clone GH scripts
uses: actions/checkout@v6
with:
repository: pawelsalawa/gh-action-scripts
ref: main
path: gh-scripts
- name: Setup GH scripts path
shell: bash
run: |
mv gh-scripts ..
cd ..
chmod +x gh-scripts/scripts/*.sh
echo "GH_SCRIPTS=$(pwd)/gh-scripts/scripts" >> $GITHUB_ENV
echo "DEBUG=${{ inputs.DEBUG }}" >> $GITHUB_ENV
- name: Clone repo
uses: actions/checkout@v6
with:
ref: ${{ env.BRANCH_NAME }}
- name: Determine Letos version
run: |
LETOS_VERSION=$(scripts/version_from_source.sh)
echo "LETOS_VERSION=$LETOS_VERSION" >> $GITHUB_ENV
echo "PACKAGE_VERSION=${LETOS_VERSION}-linux-${{ matrix.OUTPUT_FILE_ARCH }}" >> $GITHUB_ENV
- name: Pre-download SQLite vanilla sourcecode
shell: bash
run: |
SQLITE_DOT_VERSION=$($GH_SCRIPTS/convert_int_ver.sh $SQLITE_VERSION)
echo "SQLITE_DOT_VERSION=$SQLITE_DOT_VERSION" >> $GITHUB_ENV
cd ..
curl -L https://github.com/pawelsalawa/sqlite3-letos/releases/download/v$SQLITE_DOT_VERSION/sqlite3-extensions-src-$SQLITE_VERSION.zip --output sqlite3-extensions-src-$SQLITE_VERSION.zip
mkdir ext-src
unzip sqlite3-extensions-src-$SQLITE_VERSION.zip -d ext-src
- name: Prepare ccache
if: inputs.use_ccache || false
uses: hendrikmuhs/ccache-action@v1.2.8
with:
key: lin_release
max-size: "24M"
- name: Configure ccache
if: inputs.use_ccache || false
run: |
echo "PATH=/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" >> $GITHUB_ENV
- name: Install SQLite3
run: |
cd ..
SQLITE3_ZIP=sqlite3-linux-${{ matrix.SQLITE_ARCH }}-$SQLITE_VERSION.zip
curl -L https://github.com/pawelsalawa/sqlite3-letos/releases/download/v$SQLITE_DOT_VERSION/$SQLITE3_ZIP --output $SQLITE3_ZIP
sudo rm -f /usr/lib/libsqlite* /usr/local/lib/libsqlite* /usr/include/sqlite* /usr/local/include/sqlite* /usr/lib/${{ matrix.TARGET_ARCH }}-linux-gnu/libsqlite*
sudo unzip $SQLITE3_ZIP libsqlite3.so -d /usr/local/lib
sudo unzip $SQLITE3_ZIP sqlite3.h sqlite3ext.h -d /usr/local/include
sudo ln -s /usr/local/lib/libsqlite3.so /usr/local/lib/libsqlite3.so.0
sudo ln -s /usr/local/lib/libsqlite3.so /usr/local/lib/libsqlite3.so.0.8.6
ls -l /usr/local/lib/libsqlite3*
ls -l /usr/local/include/sqlite*
- name: Get ICU headers
if: steps.cache-icu.outputs.cache-hit != 'true'
shell: bash
run: |
cd ..
curl -fsSL -o icu-src.tgz "${ICU_URL}"
tar xzf icu-src.tgz
mkdir icu-headers icu-headers/unicode
cp icu/source/common/*.h icu-headers/
cp icu/source/common/unicode/*.h icu/source/i18n/unicode/*.h icu-headers/unicode/
echo "ICU_HEADERS=$(pwd)/icu-headers" >> $GITHUB_ENV
- name: Compile additional SQLite3 extensions
shell: bash
run: |
cd ..
mkdir ext
cd ext-src
FLAGS="-ldl -O2 -fpic -shared -Imisc -I/usr/local/include -L/usr/local/lib -lsqlite3"
set -x
for f in compress; do
gcc misc/$f.c $FLAGS -lz -o ../ext/$f.so
done
for f in csv decimal eval ieee754 percentile rot13 series sqlar uint uuid zorder; do
gcc misc/$f.c $FLAGS -o ../ext/$f.so
done
for f in icu; do
gcc icu/$f.c -L$QT_ROOT_DIR/lib $FLAGS -I$ICU_HEADERS -licui18n -licuuc -licudata -o ../ext/$f.so
done
set +x
ls -l ../ext/
- name: Install Tcl
run: sudo apt-get install -qq libtcl$TCL_VERSION tcl$TCL_VERSION-dev
- name: Install other tools/dependencies
run: |
sudo apt-get install libreadline-dev libncurses5-dev patchelf
echo "${{ github.workspace }}/../Qt/${{ env.QT_VERSION }}/gcc_64/bin" >> $GITHUB_PATH
- name: Prepare output dir
run: mkdir output output/build output/build-plugins
- name: Compile Letos
working-directory: output/build
run: |
cmake ../../Letos -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH="${{ env.QT_ROOT_DIR }}" \
-DCMAKE_INSTALL_PREFIX=../Letos \
-DWITH_PORTABLE=1 \
-DWITH_UPDATER=1 \
-DBUILD_TESTING=0
cmake --build . --verbose
cmake --install . --verbose
- name: Compile Plugins
working-directory: output/build-plugins
run: |
cmake ../../Plugins -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH="${{ env.QT_ROOT_DIR }}:${{ env.Python3_ROOT_DIR }}" \
-DCMAKE_INSTALL_PREFIX=../Letos \
-DWITH_PORTABLE=1 \
-DWITH_DYNAMIC_PYTHON=1 \
-DWITH_ALL_PLUGINS=1
cmake --build . --verbose
cmake --install . --verbose
- name: Copy SQLite extensions to output dir
shell: bash
run: |
cp -R ../ext output/Letos/extensions
- name: Prepare portable dir
working-directory: output
run: |
mkdir portable portable/lib
cp -R Letos portable/
- name: Copy SQLite3 to portable dir
working-directory: ${{ env.PORTABLE_DIR }}
run: cp -P /usr/local/lib/libsqlite3.so lib/
- name: Copy Qt's libcrypto and libssl to portable dir (#4577)
run: |
wget ${{ matrix.LIBSSL_DIR_URL }}${{ matrix.LIBSSL_DEB }}
dpkg-deb -xv ${{ matrix.LIBSSL_DEB }} .
cp ./usr/lib/${{ matrix.TARGET_ARCH }}-linux-gnu/libssl.so.1.1 ${{ env.PORTABLE_DIR }}/lib/
cp ./usr/lib/${{ matrix.TARGET_ARCH }}-linux-gnu/libcrypto.so.1.1 ${{ env.PORTABLE_DIR }}/lib/
- name: Copy Qt to portable dir
working-directory: ${{ env.PORTABLE_DIR }}
run: |
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6Core.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6DBus.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6Concurrent.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6Gui.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6Network.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6PrintSupport.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6Qml.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6Wayland*Client*.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6Widgets.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6Xml.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6Svg.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6XcbQpa.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6OpenGL.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6OpenGLWidgets.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libQt6UiTools.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libicui18n.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libicuuc.so* lib/
cp -P ${{ env.QT_ROOT_DIR }}/lib/libicudata.so* lib/
- name: Copy Qt plugins to portable dir
working-directory: ${{ env.PORTABLE_DIR }}
run: |
mkdir platforms imageformats iconengines printsupport platformthemes platforminputcontexts wayland-decoration-client wayland-graphics-integration-client wayland-shell-integration tls
cp -P ${{ env.QT_ROOT_DIR }}/plugins/platforms/libqxcb.so platforms/libqxcb.so
cp -P ${{ env.QT_ROOT_DIR }}/plugins/platforms/libqwayland*.so platforms/
for f in qgif qicns qico qjpeg qsvg qtga qtiff qwbmp qwebp; do
cp -P ${{ env.QT_ROOT_DIR }}/plugins/imageformats/lib$f.so imageformats/lib$f.so
done
cp -P ${{ env.QT_ROOT_DIR }}/plugins/iconengines/libqsvgicon.so iconengines/libqsvgicon.so
cp -P ${{ env.QT_ROOT_DIR }}/plugins/printsupport/libcupsprintersupport.so printsupport/libcupsprintersupport.so
cp -P ${{ env.QT_ROOT_DIR }}/plugins/platformthemes/* platformthemes/
cp -P ${{ env.QT_ROOT_DIR }}/plugins/platforminputcontexts/libcomposeplatforminputcontextplugin.so platforminputcontexts/libcomposeplatforminputcontextplugin.so
cp -P ${{ env.QT_ROOT_DIR }}/plugins/wayland-decoration-client/*.so wayland-decoration-client/
cp -P ${{ env.QT_ROOT_DIR }}/plugins/wayland-graphics-integration-client/*.so wayland-graphics-integration-client/
cp -P ${{ env.QT_ROOT_DIR }}/plugins/wayland-shell-integration/*.so wayland-shell-integration/
cp -P ${{ env.QT_ROOT_DIR }}/plugins/tls/libqopensslbackend.so tls/
- name: Copy extra Qt dependencies to portable dir
shell: bash
working-directory: ${{ env.PORTABLE_DIR }}
run: |
libdir=/usr/lib/${{ matrix.TARGET_ARCH }}-linux-gnu
if ldd lib/libQt${QT_VERSION_MAJ}XcbQpa.so | grep -q libxcb-; then
# These are not installed by default on Xubuntu 22.04:
cp -P $libdir/libxcb-xkb.so* lib/
cp -P $libdir/libxkbcommon.so* lib/ # libxkbcommon _is_ installed by default but must match the version of
cp -P $libdir/libxkbcommon-x11.so* lib/ # libxkbcommon-x11 which is not
fi
if ldd lib/libQt${QT_VERSION_MAJ}WaylandClient.so | grep -q libwayland-; then
# These must probably match the build system
cp -P $libdir/libwayland-client.so* lib/
cp -P $libdir/libwayland-cursor.so* lib/
cp -P $libdir/libffi.so* lib/
fi
- name: Fix dependency paths
working-directory: ${{ env.PORTABLE_DIR }}
run: |
set -x
patchelf --set-rpath '$ORIGIN/../lib' platforms/*.so imageformats/*.so iconengines/*.so printsupport/*.so platformthemes/*.so plugins/*.so wayland-*/*.so tls/*.so extensions/*.so 2>&1 >/dev/null
patchelf --set-rpath '$ORIGIN' lib/libicu*.*.*
patchelf --set-rpath '$ORIGIN' lib/libcoreLetos.so lib/libguiLetos.so 2>&1 >/dev/null
patchelf --set-rpath '$ORIGIN/lib' letos 2>&1 >/dev/null
# CMake may consider manually installed SQLite as "IMPORTED", therefore linking it with a full path. We need to fix it.
patchelf --replace-needed /usr/local/lib/libsqlite3.so libsqlite3.so lib/libcoreLetos.so
- name: Final preparations for packaging
run: |
mkdir "${{ env.PORTABLE_DIR }}"/assets
cp Letos/gui/img/letos_256.png "${{ env.PORTABLE_DIR }}"/assets/appicon.png
cp Letos/gui/img/letos.svg "${{ env.PORTABLE_DIR }}"/assets/appicon.svg
- name: Final preparations for packaging
working-directory: ${{ env.PORTABLE_DIR }}
run: |
strip lib/*.so letos platforms/*.so imageformats/*.so iconengines/*.so printsupport/*.so platformthemes/*.so plugins/*.so tls/*.so
patchelf --set-rpath '$ORIGIN' \
lib/libQt6Core.so.*.*.*
- name: Assemble portable package
shell: bash
working-directory: ${{ env.PORTABLE_DIR }}/..
run: |
tar cf letos-$PACKAGE_VERSION.tar Letos
xz -z letos-$PACKAGE_VERSION.tar
pwd
ls -l
- name: Create AppImage
shell: bash
working-directory: ${{ env.PORTABLE_DIR }}/..
run: |
sudo apt-get install binutils coreutils desktop-file-utils fakeroot fuse libgdk-pixbuf2.0-dev patchelf python3-pip python3-setuptools squashfs-tools strace util-linux zsync
sudo wget ${{ matrix.APPIMAGE_URL }} -O /usr/local/bin/appimagetool
sudo chmod +x /usr/local/bin/appimagetool
mkdir Letos.AppDir
cp -R Letos Letos.AppDir/
cd Letos.AppDir
ln -s Letos/letos AppRun
cp Letos/letos_256.png letos.png
cp Letos/letos.desktop letos.desktop
cd ..
APPIMAGENAME=Letos-${LETOS_VERSION}-${{ matrix.TARGET_ARCH }}.AppImage
ARCH=${{ matrix.TARGET_ARCH }} appimagetool Letos.AppDir $APPIMAGENAME
ls -l
echo "APPIMAGENAME=$APPIMAGENAME" >> $GITHUB_ENV
- name: SHA256 checksums
shell: bash
run: |
sha256sum output/portable/letos-${{ env.PACKAGE_VERSION }}.tar.xz
sha256sum output/portable/$APPIMAGENAME
- name: Upload package artifact
uses: actions/upload-artifact@v7
with:
name: letos-${{ env.PACKAGE_VERSION }}.tar.xz
path: output/portable/letos-${{ env.PACKAGE_VERSION }}.tar.xz
- name: Upload AppImage artifact
uses: actions/upload-artifact@v7
with:
name: ${{ env.APPIMAGENAME }}
path: output/portable/${{ env.APPIMAGENAME }}
- name: Install Midnight Commander
if: >
${{
github.repository_owner == 'pawelsalawa'
&& (inputs.debug_ssh || (failure() && inputs.debug_on_failure))
}}
run: sudo apt-get install mc
- name: Setup debugging SSH
if: >
${{
github.repository_owner == 'pawelsalawa'
&& (inputs.debug_ssh || (failure() && inputs.debug_on_failure))
}}
uses: owenthereal/action-upterm@v1
with:
wait-timeout-minutes: 10