MacOS universal build dependencies #18
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: MacOS universal build dependencies | |
on: | |
workflow_dispatch: | |
inputs: | |
use_macports_cache: | |
description: 'Use MacPorts cache' | |
required: false | |
default: true | |
type: boolean | |
use_ccache: | |
description: 'Use ccache' | |
required: false | |
type: boolean | |
schedule: | |
- cron: '0 3 * * 0' # run at 3 AM UTC every Sunday | |
repository_dispatch: | |
types: [mac_universal_deps] | |
jobs: | |
build: | |
runs-on: macos-11 | |
strategy: | |
fail-fast: false | |
matrix: | |
binary_compatibility: | |
- "darwin_20.arm64-x86_64" # macOS 11, the earliest ARM64 version | |
include: | |
# this list is meant to be synchronized with mac_release.yml | |
- common_pkgs: | |
- brotli 1.0.9_2 | |
- dbus 1.14.6_0 | |
- double-conversion 3.3.0_0 | |
- freetype 2.12.1_0 | |
- gettext-runtime 0.21.1_0 | |
- giflib 4.2.3_0 | |
- glib2 2.76.3_0+x11 | |
- graphite2 1.3.14_0 | |
- harfbuzz 6.0.0_1 | |
- icu 73.1_1 | |
- jasper 4.0.0_1 | |
- lcms2 2.15_0 | |
- lerc 4.0.0_1 | |
- libdeflate 1.18_0 | |
- libedit 20221030-3.1_0 | |
- libffi 3.4.4_0 | |
- libiconv 1.17_0 | |
- libjpeg-turbo 2.1.5.1_0 | |
- libmng 2.0.3_1 | |
- libpng 1.6.39_0 | |
- ncurses 6.4_0 | |
- openssl3 3.1.1_0 | |
- pcre 8.45_0 | |
- pcre2 10.42_0 | |
- python39 3.9.17_0+lto+optimizations | |
- tcl 8.6.13_0+corefoundation+threads | |
- tiff 4.5.1_1 | |
- webp 1.3.0_1 | |
- xz 5.4.3_0 | |
- zstd 1.5.5_0 | |
- binary_compatibility: darwin_20.arm64-x86_64 | |
cflags: -arch arm64 -arch x86_64 | |
add_variants: "+universal" | |
dmg_postfix: "-macos11.universal" | |
qmake_flags: "" | |
pkgs: | |
- qt5-qtbase 5.15.10_0+openssl | |
- qt5-qtdeclarative 5.15.10_0 | |
- qt5-qtimageformats 5.15.10_0 | |
- qt5-qtscript 5.15.10_0 | |
- qt5-qtsvg 5.15.10_0 | |
- qt5-qttools 5.15.10_0 | |
steps: | |
- name: Restore distfiles packages cache | |
id: cache-distfiles | |
uses: actions/cache/restore@v3 | |
with: | |
path: distfiles | |
key: distfiles-${{ matrix.binary_compatibility }}-${{ github.sha }} | |
restore-keys: distfiles-${{ matrix.binary_compatibility }}- | |
- name: Fetch distfiles | |
run: | | |
mkdir -p distfiles | |
fetch_binpkg() { | |
local _compat="$1"; shift | |
while [ -n "$1" ]; do | |
local _name="$1" | |
local _postfix="$(echo "$2${{ matrix.add_variants}}" | sed 's/+x11+universal/+universal+x11/')" | |
local _url="https://packages.macports.org/$_name/$_name-$_postfix.$_compat.tbz2" | |
shift 2 | |
case " $*" in *" $_name "*_) echo "$_name: Skipping as an override follows" 1>&2; continue ;; esac | |
_file="distfiles/$(basename "$_url")" | |
if [ ! -e "$_file" ]; then | |
echo "Fetching $_url" 1>&2 | |
if ! curl -fsL -o "$_file" "$_url"; then | |
echo "Fetching $_url failed, skipping" 1>&2 | |
rm -f "$_file" | |
printf '%s @%s\n' "$_name" "$_postfix" | |
fi | |
fi | |
done | |
} | |
_distfiles_count="$(ls distfiles | wc -l)" | |
_any="no" | |
_missing="$(fetch_binpkg ${{ matrix.binary_compatibility }} ${{ join(matrix.common_pkgs, ' ') }} ${{ join(matrix.pkgs, ' ') }})" | |
[ "$(ls distfiles | wc -l)" -eq "$_distfiles_count" ] || _any=yes | |
tee -a $GITHUB_ENV <<EOF_ENV | |
UPDATE_DISTFILES_CACHE=$_any | |
MISSING_PACKAGES<<EOF_VAR | |
${_missing} | |
EOF_VAR | |
EOF_ENV | |
- name: Fetch MacPorts cache | |
# Unconditionally touch the cache to prevent its autoremoval | |
id: cache-macports | |
uses: actions/cache/restore@v3 | |
with: | |
path: ~/macports-cache | |
key: macports-${{ matrix.binary_compatibility }}-${{ github.sha }} | |
restore-keys: macports-${{ matrix.binary_compatibility }}- | |
- name: Install MacPorts | |
if: env.MISSING_PACKAGES != '' | |
run: | | |
wget https://raw.githubusercontent.com/GiovanniBussi/macports-ci/master/macports-ci | |
source ./macports-ci install | |
[ "${{ inputs.use_ccache || false }}" = false ] || source ./macports-ci ccache | |
- name: Restore MacPorts from cache | |
if: env.MISSING_PACKAGES != '' && inputs.use_macports_cache | |
run: | | |
echo "CACHE_TIMESTAMP=$(date '+%Y%m%d-%H%M%S')" >> $GITHUB_ENV | |
if [ -f ~/macports-cache/macports.tar.bz2 ]; then | |
# Remove fresh installation keeping only /opt/local/etc/macports/macports.conf, /opt/local/var/macports/sources | |
sudo cp -p /opt/local/etc/macports/macports.conf . | |
sudo rm -fr /opt/local/[a-uw-z]* | |
sudo rm -fr /opt/local/var/[a-ln-z]* | |
sudo rm -fr /opt/local/var/macports/[a-rt-z]* /opt/local/var/macports/software | |
sudo tar -C / -xjpf ~/macports-cache/macports.tar.bz2 | |
sudo cp -p macports.conf /opt/local/etc/macports/ | |
fi | |
- name: Add local ports | |
if: env.MISSING_PACKAGES != '' | |
run: | | |
set -x | |
_ports_src=$(echo /opt/local/var/macports/sources/*/macports/release/tarballs/ports) | |
_our_python="$(echo "${{join(matrix.common_pkgs, fromJSON('"\n"')) }}" | awk '/^python3/ { print $1 }')" | |
echo "OUR_PYTHON=$_our_python" >> $GITHUB_ENV | |
mkdir -p ports/aqua ports/devel ports/gnome ports/graphics | |
cd ports | |
# graphite2 universal patch: https://github.com/macports/macports-ports/pull/18070 | |
cp -rp $_ports_src/graphics/graphite2 graphics/ | |
curl -L https://github.com/macports/macports-ports/commit/c305ea5333bb4f3c3bca1dae70c74d63231e68ea.diff \ | |
| patch -p1 | |
# Make clang-16 a non-dependency of qt5-qttools to let us skip rebuilding it as universal | |
cp -rp $_ports_src/aqua/qt5 aqua/ | |
sed -i '' 's,"port:clang-\${llvm_version}","",' \ | |
aqua/qt5/Portfile | |
# Make python311 a non-dependency of qt5-qtdeclarative | |
sed -i '' "s/python311/$_our_python/g;s/3\\.11/3.${_our_python#python3}/g" \ | |
aqua/qt5/Portfile | |
# Make python311 a non-dependency of glib2 | |
cp -rp $_ports_src/devel/glib2 devel/ | |
sed -i '' "s/^set py_ver .*/set py_ver 3.${_our_python#python3}/" \ | |
devel/glib2/Portfile | |
# Make python311 a non-dependency of meson | |
cp -rp $_ports_src/devel/meson devel/ | |
sed -i '' "s/^python\\.default_version.*/python.default_version ${_our_python#python}/" \ | |
devel/meson/Portfile | |
# Make python311 a non-dependency of ninja | |
cp -rp $_ports_src/devel/ninja devel/ | |
sed -i '' "s/^set py_ver .*/set py_ver 3.${_our_python#python3}/" \ | |
devel/ninja/Portfile | |
# Make python311 a non-dependency of gobject-introspection | |
cp -rp $_ports_src/gnome/gobject-introspection gnome/ | |
sed -i '' "s/^set py_ver .*/set py_ver 3.${_our_python#python3}/" \ | |
gnome/gobject-introspection/Portfile | |
# Make python310 a non-dependency of fontconfig | |
cp -rp $_ports_src/graphics/fontconfig graphics/ | |
sed -i '' "s/port:python310/port:$_our_python/" \ | |
graphics/fontconfig/Portfile | |
cd .. | |
source ./macports-ci localports $(pwd)/ports | |
- name: Install missing packages except Qt | |
if: env.MISSING_PACKAGES != '' | |
run: | | |
set -x | |
# Try to install what's possible to install from binary packages | |
sudo port -Nkv install "$OUR_PYTHON" +universal | |
sudo port -Nkv install python_select python3_select | |
sudo port select --set python "$OUR_PYTHON" | |
sudo port select --set python3 "$OUR_PYTHON" | |
case "$MISSING_PACKAGES" in *glib2*) | |
sudo port -Nkv install glib2 +universal # our and cairo's dependency, needs +universal, +x11 is the default | |
;; | |
esac | |
case "$MISSING_PACKAGES" in *harfbuzz*) | |
sudo port -Nk install python310 # fontconfig seems to need it badly but -universal is ok | |
sudo port -Nkv install cairo -x11 +universal # skip x11 dependencies | |
;; | |
esac | |
_the_rest="$(echo "$MISSING_PACKAGES" | grep -v '^qt5-')" | |
[ -z "$_the_rest" ] || sudo port -Nkv install $_the_rest | |
- name: Install missing Qt packages except qt5-qttools | |
if: env.MISSING_PACKAGES != '' | |
run: | | |
set -x | |
_the_rest="$(echo "$MISSING_PACKAGES" | grep '^qt5-' | grep -v '^qt5-qttools' || true)" | |
[ -z "$_the_rest" ] || sudo port -Nkv install $_the_rest | |
- name: Install missing qt5-qttools | |
if: env.MISSING_PACKAGES != '' | |
run: | | |
set -x | |
universalize_clang_lib() { | |
local _lib="$1" | |
local _lib_path="opt/local/libexec/llvm-16/lib/$_lib" | |
local _current_lib_archs="$(lipo "/$_lib_path" -info | awk -F ': ' '{print $3}')" | |
local _other=${{ matrix.binary_compatibility }} | |
case "$_current_lib_archs" in | |
x86_64) _other="${_other%.*}.arm64" ;; | |
arm64) _other="${_other%.*}.x86_64" ;; | |
*" "*) return 0 ;; # already universal | |
esac | |
local _clang_dist_name="$(port installed | awk '$1 == "clang-16" && $3 == "(active)" {sub(/@/, "-"); sub(/\+universal/, ""); print $1 $2}').$_other.tbz2" | |
if [ ! -e "distfiles/$_clang_dist_name" ]; then | |
curl -fsL -o "distfiles/$_clang_dist_name" "https://packages.macports.org/clang-16/$_clang_dist_name" | |
echo "UPDATE_DISTFILES_CACHE=yes" >> "$GITHUB_ENV" | |
fi | |
tar -xjf "distfiles/$_clang_dist_name" "$_lib_path" | |
lipo {,/}"$_lib_path" -create -output "$_lib" | |
sudo install -S "$_lib" "/$_lib_path" | |
} | |
case "$MISSING_PACKAGES" in *qt5-qttools*) | |
# Don't build clang-16 as universal (~12 hours) | |
if ! port installed | grep -q clang-16; then | |
sudo port -Nkv install clang-16 -universal | |
fi | |
universalize_clang_lib libc++.1.0.dylib | |
universalize_clang_lib libc++.a | |
universalize_clang_lib libclang.dylib | |
sudo port -Nkv install qt5-qttools +universal | |
;; | |
esac | |
- name: Prepare distfiles cache | |
if: always() && env.MISSING_PACKAGES != '' | |
run: | | |
set -x | |
# Save any new wanted distfiles | |
_any="" | |
while read -r _package _version; do | |
_package_path="/opt/local/var/macports/software/$_package/$_package-${_version#@}" | |
[ -n "$(ls $_package_path.*.tbz2 2>/dev/null)" ] || continue | |
cp $_package_path.*.tbz2 distfiles/ | |
_any=1 | |
done <<EOF | |
$MISSING_PACKAGES | |
EOF | |
[ -z "$_any" ] || echo "UPDATE_DISTFILES_CACHE=yes" >> $GITHUB_ENV | |
- name: Prepare MacPorts cache | |
if: always() && env.MISSING_PACKAGES != '' && inputs.use_macports_cache | |
run: | | |
set -x | |
sudo rm -fr /opt/local/var/macports/{build,logs,sources}/* | |
rm -fr ~/macports-cache && mkdir ~/macports-cache | |
sudo tar -cjpf ~/macports-cache/macports.tar.bz2 /opt/local || true | |
- name: Save distfiles cache | |
if: always() && env.UPDATE_DISTFILES_CACHE == 'yes' | |
uses: actions/cache/save@v3 | |
with: | |
path: distfiles | |
key: ${{ steps.cache-distfiles.outputs.cache-primary-key }}-${{ env.CACHE_TIMESTAMP }} | |
- name: Save MacPorts cache | |
if: always() && env.MISSING_PACKAGES != '' && inputs.use_macports_cache | |
uses: actions/cache/save@v3 | |
with: | |
path: ~/macports-cache | |
key: macports-${{ matrix.binary_compatibility }}-${{ github.sha }}-${{ env.CACHE_TIMESTAMP }} |