diff --git a/.github/workflows/macos-build.yml b/.github/workflows/macos-build.yml index 404ace12..f8612418 100644 --- a/.github/workflows/macos-build.yml +++ b/.github/workflows/macos-build.yml @@ -35,12 +35,13 @@ jobs: (cd /tmp/gtk-mac-bundler && make install) fi - - name: Configure + - name: Configure (arm64 + x86_64) run: | set -eux PREFIX="$(brew --prefix)" - rm -rf build - meson setup build \ + rm -rf build-macos-arm64 build-macos-x86_64 + + CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson setup build-macos-arm64 \ --prefix="$PREFIX" \ -Dgtk3=true \ -Dtext-frontend=true \ @@ -49,30 +50,40 @@ jobs: -Dwith-python=python3 \ -Dauto_features=enabled - - name: Build + CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson setup build-macos-x86_64 \ + --prefix="$PREFIX" \ + -Dgtk3=true \ + -Dtext-frontend=true \ + -Dlibcanberra=disabled \ + -Dwith-perl=perl \ + -Dwith-python=python3 \ + -Dauto_features=enabled + + - name: Build (arm64 + x86_64) run: | set -eux - meson compile -C build + CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson compile -C build-macos-arm64 + CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson compile -C build-macos-x86_64 - - name: Install for bundling + - name: Install for bundling (arm64 runtime) run: | set -eux - sudo meson install -C build + sudo meson install -C build-macos-arm64 - - name: Package unsigned .app + - name: Package unsigned .app (universal binary) run: | set -eux VERSION="$(git describe --tags --always)" PREFIX="$(brew --prefix)" ENCHANT_PREFIX="$(brew --prefix enchant)" - export PREFIX ENCHANT_PREFIX + export VERSION PREFIX ENCHANT_PREFIX - sed "s/@VERSION@/${VERSION}/g" osx/Info.plist.in > osx/Info.plist - - perl -0pi -e 's|.*?|$ENV{PREFIX}|s' osx/zoitechat.bundle - perl -0pi -e 's|.*?|$ENV{ENCHANT_PREFIX}|s' osx/zoitechat.bundle - - (cd osx && ./makebundle.sh) + ( + cd osx + UNIVERSAL=1 \ + UNIVERSAL_BINARIES="../build-macos-arm64/src/fe-gtk/zoitechat ../build-macos-x86_64/src/fe-gtk/zoitechat" \ + ./makebundle.sh + ) mv osx/ZoiteChat-*.app.zip ./ - name: Upload unsigned macOS app artifact diff --git a/osx/DEBUGGING.md b/osx/DEBUGGING.md index 9b1291f8..91b036fc 100644 --- a/osx/DEBUGGING.md +++ b/osx/DEBUGGING.md @@ -130,6 +130,25 @@ meson compile -C build-macos-intel If your dependency stack supports it, build universal (`arm64` + `x86_64`) and verify with `lipo -info`. +Example with this repo's scripts: + +```bash +PREFIX="$(brew --prefix)" + +CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson setup build-macos-arm64 --prefix="$PREFIX" +CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson setup build-macos-x86_64 --prefix="$PREFIX" + +CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson compile -C build-macos-arm64 +CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson compile -C build-macos-x86_64 + +sudo meson install -C build-macos-arm64 + +cd osx +UNIVERSAL=1 \ +UNIVERSAL_BINARIES="../build-macos-arm64/src/fe-gtk/zoitechat ../build-macos-x86_64/src/fe-gtk/zoitechat" \ +./makebundle.sh +``` + ## 10) Recommended compatibility settings for macOS 11+ - Keep `LSMinimumSystemVersion` at `11.0`. diff --git a/osx/makebundle.sh b/osx/makebundle.sh index b8a79214..9d05332e 100755 --- a/osx/makebundle.sh +++ b/osx/makebundle.sh @@ -9,7 +9,15 @@ BUNDLE_DEF="zoitechat.bundle" APP_NAME="ZoiteChat.app" HOST_ARCH="$(uname -m 2>/dev/null || echo unknown)" -TARGET_ARCHES="${TARGET_ARCHES:-$HOST_ARCH}" +if [ -z "${TARGET_ARCHES+x}" ]; then + TARGET_ARCHES="$HOST_ARCH" +fi +UNIVERSAL_BINARIES="${UNIVERSAL_BINARIES:-}" +UNIVERSAL_BUILD_DIRS="${UNIVERSAL_BUILD_DIRS:-../build-macos-arm64 ../build-macos-x86_64}" + +if [ "${UNIVERSAL:-0}" = "1" ]; then + TARGET_ARCHES="arm64 x86_64" +fi # Expected prefixes for macOS GTK dependencies: # - Homebrew: /opt/homebrew (Apple Silicon) or /usr/local (Intel) @@ -97,6 +105,44 @@ fi BIN_PATH="$APP_NAME/Contents/MacOS/ZoiteChat-bin" +if [ "${UNIVERSAL:-0}" = "1" ] && [ -z "$UNIVERSAL_BINARIES" ]; then + for build_dir in $UNIVERSAL_BUILD_DIRS; do + candidate="$build_dir/src/fe-gtk/zoitechat" + if [ -f "$candidate" ]; then + UNIVERSAL_BINARIES="${UNIVERSAL_BINARIES:+$UNIVERSAL_BINARIES }$candidate" + fi + done + + if [ -z "$UNIVERSAL_BINARIES" ]; then + cat >&2 <<'MSG' +error: UNIVERSAL=1 requested, but no source binaries were found. +Set UNIVERSAL_BINARIES to one or more architecture-specific zoitechat binaries, +or place builds at: + ../build-macos-arm64/src/fe-gtk/zoitechat + ../build-macos-x86_64/src/fe-gtk/zoitechat +MSG + exit 1 + fi +fi + +if [ -n "$UNIVERSAL_BINARIES" ]; then + if ! command -v lipo >/dev/null 2>&1; then + echo "error: UNIVERSAL_BINARIES requires lipo, but lipo is unavailable" >&2 + exit 1 + fi + + for binary in $UNIVERSAL_BINARIES; do + if [ ! -f "$binary" ]; then + echo "error: universal source binary not found: $binary" >&2 + exit 1 + fi + done + + echo "Creating universal ZoiteChat-bin from: $UNIVERSAL_BINARIES" + # shellcheck disable=SC2086 + lipo -create $UNIVERSAL_BINARIES -output "$BIN_PATH" +fi + if command -v lipo >/dev/null 2>&1; then BIN_ARCHS="$(lipo -archs "$BIN_PATH" 2>/dev/null || true)" if [ -z "$BIN_ARCHS" ]; then