qt6 crossbuild package release #226
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: qt6 crossbuild package release | |
on: | |
workflow_dispatch: | |
inputs: | |
skip_rerun: | |
description: "Skip rerun?" | |
required: true | |
default: true | |
type: boolean | |
retries: | |
description: "Number of rerun retries" | |
required: true | |
default: "1" | |
type: choice | |
options: ["1", "2", "3", "4", "5", "6", "7", "8", "9"] | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
permissions: | |
contents: write | |
jobs: | |
build: | |
runs-on: ubuntu-latest | |
outputs: | |
qt_version: ${{ steps.version_info.outputs.qt_version }} | |
strategy: | |
fail-fast: false | |
matrix: | |
name: [qt6] | |
os_id: [debian, ubuntu] | |
os_codename: [bullseye, bookworm, focal, jammy, noble] | |
arch: [amd64, armhf, arm64] | |
exclude: | |
- os_id: debian | |
os_codename: focal | |
- os_id: debian | |
os_codename: jammy | |
- os_id: debian | |
os_codename: noble | |
- os_id: ubuntu | |
os_codename: bullseye | |
- os_id: ubuntu | |
os_codename: bookworm | |
name: ${{ matrix.os_id }}:${{ matrix.os_codename }} ${{ matrix.name }} ${{ matrix.arch }} | |
env: | |
opt_dir_name: "opt/local" | |
qt_short_version: "6" | |
cxx_standard: "17" | |
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" | |
steps: | |
- name: Host - Checkout action | |
uses: actions/checkout@v4 | |
# Fix this bug https://github.com/actions/runner-images/issues/7192 | |
- name: Host - phased updates | |
run: printf '%s\n' 'APT::Get::Always-Include-Phased-Updates "false";' | sudo tee /etc/apt/apt.conf.d/99-phased-updates | |
# Bootstrap Ubuntu Lunar repo so that we can install specific app we may need, like binfmt and qemu-user-static | |
- name: Host - set up lunar repo -t lunar | |
run: | | |
printf '%b\n' 'Package: *\nPin: release n=lunar\nPin-Priority: 50' | sudo tee /etc/apt/preferences | |
printf '%s\n' 'deb http://archive.ubuntu.com/ubuntu/ lunar main universe restricted' | sudo tee /etc/apt/sources.list.d/lunar.list | |
- name: Host - update | |
run: sudo apt-get update | |
# - name: Host - upgrade | |
# run: sudo apt-get -y upgrade | |
# No action or other method to bootstrap binfmt. Install from lunar and we get the latest versions and full docker support | |
- name: Host - set up qemu-user-static binfmt-support from lunar | |
run: sudo apt install -t lunar libpipeline1 qemu-user-static binfmt-support | |
# Why are we doing it like this and not using a container setup? That's how you're supposed to do it, right? | |
# qemu-user-static and binfmt-support are not part of the runner images https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2204-Readme.md | |
# We would need to modify the runner to install these before the container starts. Which you cannot do as there is no way to bootstrap the host. | |
# So we install them on the host then create/pull a custom docker image that we use to build the multiarch targets. | |
# We are always on the host runner but can use any docker image we need with the access the qemu emulation when required. | |
# | |
# We are using these pre configured toolchain images that allows me to remove 50% of the code/time from this action. | |
# | |
# https://github.com/userdocs/dcb/blob/main/Dockerfile | |
# | |
# The image does not run as root and has password-less sudo. There are two users username:1000 /home/username and github:1001 /home/github | |
# In the action it runs as 1001 /home/github and files should be available to the host. For local use, you might need -u 1000 | |
- name: Host - Create docker multiarch ${{ matrix.arch }} container | |
run: docker run --name multiarch -it -d -u 1001 -v ${{ github.workspace }}:/home/github ghcr.io/userdocs/dcb:${{ matrix.os_id }}-${{ matrix.os_codename }}-${{ matrix.arch }} | |
- name: Docker - cmake and ninja download and install | |
run: | | |
docker exec multiarch curl -sNL "https://github.com/userdocs/cmake-crossbuild/releases/latest/download/${{ matrix.os_id }}-${{ matrix.os_codename }}-cmake-${{ matrix.arch }}.deb" -o ${{ matrix.os_id }}-${{ matrix.os_codename }}-cmake-${{ matrix.arch }}.deb | |
docker exec multiarch sudo dpkg -i ${{ matrix.os_id }}-${{ matrix.os_codename }}-cmake-${{ matrix.arch }}.deb | |
- name: Docker - zlib-ng download and install | |
run: | | |
docker exec multiarch curl -sNL "https://github.com/userdocs/zlib-ng-crossbuild/releases/latest/download/${{ matrix.os_id }}-${{ matrix.os_codename }}-zlib-ng-${{ matrix.arch }}.deb" -o ${{ matrix.os_id }}-${{ matrix.os_codename }}-zlib-ng-${{ matrix.arch }}.deb | |
docker exec multiarch sudo dpkg -i ${{ matrix.os_id }}-${{ matrix.os_codename }}-zlib-ng-${{ matrix.arch }}.deb | |
- name: Docker - openssl download and install | |
run: | | |
docker exec multiarch curl -sNL "https://github.com/userdocs/openssl-crossbuild/releases/latest/download/${{ matrix.os_id }}-${{ matrix.os_codename }}-openssl-${{ matrix.arch }}.deb" -o ${{ matrix.os_id }}-${{ matrix.os_codename }}-openssl-${{ matrix.arch }}.deb | |
docker exec multiarch sudo dpkg -i ${{ matrix.os_id }}-${{ matrix.os_codename }}-openssl-${{ matrix.arch }}.deb | |
- name: Host - qt get latest release info and create env and urls | |
id: version_info | |
run: | | |
qt_version="$(git ls-remote -q -t --refs https://github.com/qt/qtbase.git | awk '/'"${qt_short_version}"'/{sub("refs/tags/v", "");sub("(.*)(-[^0-9].*)(.*)", ""); print $2 }' | awk '!/^$/' | sort -rV | head -n 1)" | |
read -ra qt_version_short_array <<< "${qt_version//\./ }" | |
qt_short_version="${qt_version_short_array[0]}.${qt_version_short_array[1]}" | |
printf '%s\n' "qt_qtbase_url=https://download.qt.io/official_releases/qt/${qt_short_version}/${qt_version}/submodules/qtbase-everywhere-src-${qt_version}.tar.xz" >> $GITHUB_ENV | |
printf '%s\n' "qt_qttools_url=https://download.qt.io/official_releases/qt/${qt_short_version}/${qt_version}/submodules/qttools-everywhere-src-${qt_version}.tar.xz" >> $GITHUB_ENV | |
printf '%s\n' "qt_short_version=${qt_short_version}" >> $GITHUB_ENV | |
printf '%s\n' "qt_version=${qt_version}" >> $GITHUB_ENV | |
printf '%s\n' "qt_version=${qt_version}" >> $GITHUB_OUTPUT | |
- name: Host - qt qtbase - curl | |
run: curl -sNL ${{ env.qt_qtbase_url }} -o qtbase.tar.xz && tar xf qtbase.tar.xz | |
- name: Docker - qt qtbase - cmake configure | |
run: > | |
docker exec -w /home/github/qtbase-everywhere-src-${{ env.qt_version }} multiarch cmake -Wno-dev -Wno-deprecated -G Ninja -B build | |
-D CMAKE_BUILD_TYPE="release" | |
-D CMAKE_CXX_FLAGS="-lstdc++fs" | |
-D CMAKE_EXE_LINKER_FLAGS="-lstdc++fs" | |
-D QT_FEATURE_optimize_full=on | |
-D FEATURE_glib=OFF | |
-D QT_FEATURE_gui=off -D QT_FEATURE_openssl_linked=on -D QT_FEATURE_dbus=off | |
-D QT_FEATURE_system_pcre2=off -D QT_FEATURE_widgets=off | |
-D FEATURE_androiddeployqt=OFF -D FEATURE_animation=OFF | |
-D QT_FEATURE_testlib=off -D QT_BUILD_EXAMPLES=off -D QT_BUILD_TESTS=off | |
-D QT_BUILD_EXAMPLES_BY_DEFAULT=OFF -D QT_BUILD_TESTS_BY_DEFAULT=OFF | |
-D QT_FEATURE_gui=OFF -D QT_FEATURE_widgets=OFF -D QT_FEATURE_dbus=OFF -D QT_FEATURE_openssl_linked=on | |
-D QT_FEATURE_system_pcre2=off -D QT_FEATURE_system_harfbuzz=off -D QT_FEATURE_system_freetype=off | |
-D CMAKE_CXX_STANDARD="${{ env.cxx_standard }}" | |
-D CMAKE_PREFIX_PATH="/${{ env.opt_dir_name }}" | |
-D CMAKE_INSTALL_PREFIX="/home/github/build/${{ env.opt_dir_name }}" | |
continue-on-error: true | |
- name: Archive logs | |
if: failure() | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ matrix.arch }}-${{ matrix.os_id }}-${{ matrix.os_codename }}-${{ matrix.name }}-cmake-logs | |
path: qtbase-everywhere-src-${{ env.qt_version }}/build/ | |
- name: Docker - qt qtbase - cmake build | |
run: docker exec -w /home/github/qtbase-everywhere-src-${{ env.qt_version }} multiarch cmake --build build | |
- name: Docker - qt qtbase - cmake install | |
run: docker exec -w /home/github/qtbase-everywhere-src-${{ env.qt_version }} multiarch cmake --install build | |
- name: Docker - qt qttools - curl | |
run: curl -sNL ${{ env.qt_qttools_url }} -o qttools.tar.xz && tar xf qttools.tar.xz | |
- name: Docker - qt qttools - cmake configure | |
run: > | |
docker exec -w /home/github/qttools-everywhere-src-${{ env.qt_version }} multiarch cmake -Wno-dev -Wno-deprecated -G Ninja -B build | |
-D CMAKE_BUILD_TYPE="release" | |
-D CMAKE_CXX_STANDARD="${{ env.cxx_standard }}" | |
-D CMAKE_PREFIX_PATH="/${{ env.opt_dir_name }}" | |
-D CMAKE_INSTALL_PREFIX="/home/github/build/${{ env.opt_dir_name }}" | |
- name: Docker - qt qttools - cmake build | |
run: docker exec -w /home/github/qttools-everywhere-src-${{ env.qt_version }} multiarch cmake --build build | |
- name: Docker - qt qttools - cmake install | |
run: docker exec -w /home/github/qttools-everywhere-src-${{ env.qt_version }} multiarch cmake --install build | |
- name: Docker - Set deb dependencies for qt | |
run: | | |
icu="$(docker exec multiarch apt-cache search --names-only libicu[0-9]+$ | sort -r | head -n1 | awk '{print $1}')" | |
double_conversion="$(docker exec multiarch apt-cache search --names-only libdouble-conversion[0-9]$ | sort -r | head -n1 | awk '{print $1}')" | |
if [[ ${{ matrix.os_codename }} =~ ^(bullseye|jammy)$ ]]; then | |
md4c_html="$(docker exec multiarch apt-cache search --names-only libmd4c-html0$ | sort -r | head -n1 | awk '{print $1}')" | |
printf '%s\n' "qt-deb-deps=zlib-ng,openssl,${icu},${double_conversion},${md4c_html}" >> $GITHUB_ENV | |
else | |
printf '%s\n' "qt-deb-deps=zlib-ng,openssl,${icu},${double_conversion}" >> $GITHUB_ENV | |
fi | |
- name: Docker - ldconfig - create /etc/ld.so.conf.d/qt6.conf | |
run: | | |
docker exec -w /home/github/build multiarch mkdir -p DEBIAN | |
docker exec -w /home/github/build/DEBIAN multiarch bash -c "printf '%b\n' '#!/usr/bin/env bash\nldconfig' > postinst" | |
docker exec -w /home/github/build/DEBIAN multiarch bash -c "chmod +x postinst" | |
docker exec -w /home/github/build multiarch mkdir -p etc/ld.so.conf.d | |
docker exec -w /home/github/build/etc/ld.so.conf.d multiarch bash -c "printf '%s\n' '/${{ env.opt_dir_name }}/lib' > qt6.conf" | |
- name: Host - Create deb packages | |
uses: jiro4989/build-deb-action@v3 | |
with: | |
package: "${{ matrix.name }}" | |
package_root: build | |
maintainer: userdocs | |
compress_type: gzip | |
version: "${{ env.qt_version }}" | |
depends: "${{ env.qt-deb-deps }}" | |
arch: "${{ matrix.arch }}" | |
desc: "${{ matrix.name }}-${{ matrix.arch }} for ${{ matrix.os_id }}-${{ matrix.os_codename }}" | |
- name: Host - Remove version from release name and use hyphens | |
run: mv -f "${{ matrix.name }}_${{ env.qt_version }}_${{ matrix.arch }}.deb" "${{ matrix.os_id }}-${{ matrix.os_codename }}-${{ matrix.name }}-${{ matrix.arch }}.deb" | |
- name: Host - upload deb packages | |
uses: actions/upload-artifact@v4 | |
with: | |
name: "${{ matrix.os_id }}-${{ matrix.os_codename }}-${{ matrix.name }}-${{ matrix.arch }}-deb" | |
path: "${{ matrix.os_id }}-${{ matrix.os_codename }}-${{ matrix.name }}-${{ matrix.arch }}.deb" | |
release: | |
name: Upload artifacts to release | |
runs-on: ubuntu-latest | |
needs: build | |
if: always() && contains(needs.*.result, 'success') && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') | |
env: | |
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" | |
qt_version: ${{ needs.build.outputs.qt_version }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Host - Download artifacts | |
uses: actions/download-artifact@v4 | |
- name: Host - artifacts organise for release | |
run: | | |
mkdir -p "releases" | |
for files in *-deb; do | |
cp -rf ${files}/* "releases/" | |
done | |
- name: Host - "Create release - tag - assets" | |
uses: ncipollo/release-action@v1 | |
with: | |
prerelease: false | |
artifacts: releases/*.deb | |
replacesArtifacts: true | |
tag: "${{ env.qt_version }}" | |
name: "qt ${{ env.qt_version }}" | |
body: "Built with cmake using v${{ env.qt_version }} from github on amd64 arm64 armhf for Debian Bullseye Bookworm and Ubuntu Focal Jammy Noble" | |
allowUpdates: true | |
rerun-on-failure: | |
if: failure() && inputs.skip_rerun == '0' | |
name: rerun-on-failure | |
needs: release | |
permissions: | |
actions: write | |
runs-on: ubuntu-latest | |
env: | |
GH_TOKEN: "${{ github.TOKEN }}" | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Trigger rerun workflow on job failures | |
run: | | |
inputs_retries="${{ inputs.retries }}" | |
gh workflow run rerun.yml -f run_id=${{ github.run_id }} -f attempts=${{ github.run_attempt }} -f retries=${inputs_retries:-1} |