Skip to content

qt6 crossbuild package release #226

qt6 crossbuild package release

qt6 crossbuild package release #226

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}