mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-14 10:34:06 +02:00
Convert to building a universal Mac app (#6302)
This commit is contained in:
@@ -93,18 +93,18 @@ jobs:
|
||||
echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"}]}' >> $GITHUB_OUTPUT
|
||||
;;
|
||||
"macos")
|
||||
echo 'matrix={"include":[{"platform":"macos-15","args":"--target aarch64-apple-darwin","name":"macos-aarch64"},{"platform":"macos-15-intel","args":"--target x86_64-apple-darwin","name":"macos-x86_64"}]}' >> $GITHUB_OUTPUT
|
||||
echo 'matrix={"include":[{"platform":"macos-15","args":"--target universal-apple-darwin","name":"macos-universal"}]}' >> $GITHUB_OUTPUT
|
||||
;;
|
||||
"linux")
|
||||
echo 'matrix={"include":[{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}]}' >> $GITHUB_OUTPUT
|
||||
;;
|
||||
*)
|
||||
echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"},{"platform":"macos-15","args":"--target aarch64-apple-darwin","name":"macos-aarch64"},{"platform":"macos-15-intel","args":"--target x86_64-apple-darwin","name":"macos-x86_64"},{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}]}' >> $GITHUB_OUTPUT
|
||||
echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"},{"platform":"macos-15","args":"--target universal-apple-darwin","name":"macos-universal"},{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}]}' >> $GITHUB_OUTPUT
|
||||
;;
|
||||
esac
|
||||
else
|
||||
# For push/release events, build all platforms
|
||||
echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"},{"platform":"macos-15","args":"--target aarch64-apple-darwin","name":"macos-aarch64"},{"platform":"macos-15-intel","args":"--target x86_64-apple-darwin","name":"macos-x86_64"},{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}]}' >> $GITHUB_OUTPUT
|
||||
echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"},{"platform":"macos-15","args":"--target universal-apple-darwin","name":"macos-universal"},{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}]}' >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
build-jars:
|
||||
@@ -218,7 +218,23 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@4be9e76fd7c4901c61fb841f559994984270fce7 # stable
|
||||
with:
|
||||
toolchain: stable
|
||||
targets: ${{ (matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel') && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||
targets: ${{ matrix.platform == 'macos-15' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||
|
||||
# x86_64 JDK is set up first so the aarch64 step below can leave its
|
||||
# JAVA_HOME as the active one. The macOS universal JRE build needs
|
||||
# jmods from both arches; the x64 path is captured into the env
|
||||
# before the second setup-java overwrites JAVA_HOME.
|
||||
- name: Set up x86_64 JDK 25 (macOS universal JRE)
|
||||
if: matrix.platform == 'macos-15'
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
java-version: "25"
|
||||
distribution: "temurin"
|
||||
architecture: "x64"
|
||||
|
||||
- name: Capture x86_64 JAVA_HOME
|
||||
if: matrix.platform == 'macos-15'
|
||||
run: echo "X64_JAVA_HOME=$JAVA_HOME" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Set up JDK 25
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
@@ -234,6 +250,14 @@ jobs:
|
||||
- name: Install Task
|
||||
uses: go-task/setup-task@3be4020d41929789a01026e0e427a4321ce0ad44 # v2.0.0
|
||||
|
||||
# Build the universal JRE before desktop:prepare so the jlink:runtime
|
||||
# task short-circuits on its `test -d runtime/jre` status check.
|
||||
- name: Build universal macOS JRE
|
||||
if: matrix.platform == 'macos-15'
|
||||
env:
|
||||
AARCH64_JAVA_HOME: ${{ env.JAVA_HOME }}
|
||||
run: task desktop:jlink:universal-mac
|
||||
|
||||
- name: Prepare desktop build
|
||||
run: task desktop:prepare
|
||||
env:
|
||||
@@ -321,7 +345,7 @@ jobs:
|
||||
}
|
||||
|
||||
- name: Import Apple Developer Certificate
|
||||
if: (matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel') && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master')
|
||||
if: matrix.platform == 'macos-15' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master')
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
@@ -342,7 +366,7 @@ jobs:
|
||||
rm certificate.p12
|
||||
|
||||
- name: Verify Certificate
|
||||
if: (matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel') && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master')
|
||||
if: matrix.platform == 'macos-15' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master')
|
||||
run: |
|
||||
echo "Verifying Apple Developer Certificate..."
|
||||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||
@@ -557,7 +581,7 @@ jobs:
|
||||
# Only ship the MSI installer on Windows. The loose exe and WiX toolset exes
|
||||
# are not the user-facing installer - the MSI contains the signed inner exe.
|
||||
find . -name "*.msi" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.msi" \;
|
||||
elif [ "${{ matrix.platform }}" = "macos-15" ] || [ "${{ matrix.platform }}" = "macos-15-intel" ]; then
|
||||
elif [ "${{ matrix.platform }}" = "macos-15" ]; then
|
||||
find . -name "*.dmg" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.dmg" \;
|
||||
find . -name "*.app" -exec cp -r {} "../../../dist/Stirling-PDF-${{ matrix.name }}.app" \;
|
||||
else
|
||||
|
||||
@@ -22,8 +22,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.info.outputs.version }}
|
||||
dmg_arm64_sha256: ${{ steps.hashes.outputs.dmg_arm64_sha256 }}
|
||||
dmg_x86_64_sha256: ${{ steps.hashes.outputs.dmg_x86_64_sha256 }}
|
||||
dmg_sha256: ${{ steps.hashes.outputs.dmg_sha256 }}
|
||||
msi_sha256: ${{ steps.hashes.outputs.msi_sha256 }}
|
||||
deb_sha256: ${{ steps.hashes.outputs.deb_sha256 }}
|
||||
jar_sha256: ${{ steps.hashes.outputs.jar_sha256 }}
|
||||
@@ -63,14 +62,12 @@ jobs:
|
||||
sha256sum "$file" | awk '{print $1}'
|
||||
}
|
||||
|
||||
DMG_ARM64_SHA=$(download_sha256 "${BASE}/Stirling-PDF-macos-aarch64.dmg")
|
||||
DMG_X64_SHA=$(download_sha256 "${BASE}/Stirling-PDF-macos-x86_64.dmg")
|
||||
DMG_SHA=$(download_sha256 "${BASE}/Stirling-PDF-macos-universal.dmg")
|
||||
MSI_SHA=$(download_sha256 "${BASE}/Stirling-PDF-windows-x86_64.msi")
|
||||
DEB_SHA=$(download_sha256 "${BASE}/Stirling-PDF-linux-x86_64.deb")
|
||||
JAR_SHA=$(download_sha256 "${BASE}/Stirling-PDF-with-login.jar")
|
||||
|
||||
echo "dmg_arm64_sha256=$DMG_ARM64_SHA" >> "$GITHUB_OUTPUT"
|
||||
echo "dmg_x86_64_sha256=$DMG_X64_SHA" >> "$GITHUB_OUTPUT"
|
||||
echo "dmg_sha256=$DMG_SHA" >> "$GITHUB_OUTPUT"
|
||||
echo "msi_sha256=$MSI_SHA" >> "$GITHUB_OUTPUT"
|
||||
echo "deb_sha256=$DEB_SHA" >> "$GITHUB_OUTPUT"
|
||||
echo "jar_sha256=$JAR_SHA" >> "$GITHUB_OUTPUT"
|
||||
@@ -93,22 +90,21 @@ jobs:
|
||||
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
|
||||
path: tap
|
||||
|
||||
# Stirling-PDF now ships a single universal DMG, so the Cask should
|
||||
# have one sha256 line rather than separate on_arm/on_intel blocks.
|
||||
# We rewrite every `sha256 "..."` in the Cask to the same value so
|
||||
# the workflow keeps working through the Cask migration: pre-migration
|
||||
# both arch blocks get the universal SHA (still correct, since both
|
||||
# would resolve to the same DMG), post-migration the lone sha256 line
|
||||
# is updated.
|
||||
- name: Update Homebrew cask (Casks/stirling-pdf.rb)
|
||||
env:
|
||||
VERSION: ${{ needs.get-release-info.outputs.version }}
|
||||
ARM64_SHA: ${{ needs.get-release-info.outputs.dmg_arm64_sha256 }}
|
||||
X64_SHA: ${{ needs.get-release-info.outputs.dmg_x86_64_sha256 }}
|
||||
DMG_SHA: ${{ needs.get-release-info.outputs.dmg_sha256 }}
|
||||
run: |
|
||||
CASK="tap/Casks/stirling-pdf.rb"
|
||||
sed -i "s/version \".*\"/version \"${VERSION}\"/" "$CASK"
|
||||
awk -v arm="$ARM64_SHA" -v x64="$X64_SHA" '
|
||||
/on_arm/ { in_arm=1 }
|
||||
/on_intel/ { in_arm=0; in_intel=1 }
|
||||
/end/ { in_arm=0; in_intel=0 }
|
||||
in_arm && /sha256/ { sub(/sha256 ".*"/, "sha256 \"" arm "\"") }
|
||||
in_intel && /sha256/ { sub(/sha256 ".*"/, "sha256 \"" x64 "\"") }
|
||||
{ print }
|
||||
' "$CASK" > tmp && mv tmp "$CASK"
|
||||
sed -i "s/version \"[^\"]*\"/version \"${VERSION}\"/" "$CASK"
|
||||
sed -i "s/sha256 \"[^\"]*\"/sha256 \"${DMG_SHA}\"/g" "$CASK"
|
||||
|
||||
- name: Update Homebrew formula (Formula/stirling-pdf-server.rb)
|
||||
env:
|
||||
@@ -116,8 +112,8 @@ jobs:
|
||||
JAR_SHA: ${{ needs.get-release-info.outputs.jar_sha256 }}
|
||||
run: |
|
||||
FORMULA="tap/Formula/stirling-pdf-server.rb"
|
||||
sed -i "s/version \".*\"/version \"${VERSION}\"/" "$FORMULA"
|
||||
sed -i "s/sha256 \".*\"/sha256 \"${JAR_SHA}\"/" "$FORMULA"
|
||||
sed -i "s/version \"[^\"]*\"/version \"${VERSION}\"/" "$FORMULA"
|
||||
sed -i "s/sha256 \"[^\"]*\"/sha256 \"${JAR_SHA}\"/" "$FORMULA"
|
||||
|
||||
- name: Update Scoop stirling-pdf.json
|
||||
env:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: Build Tauri Applications
|
||||
|
||||
# Multi-OS Tauri desktop bundle build matrix (Windows / macOS arm+intel /
|
||||
# Multi-OS Tauri desktop bundle build matrix (Windows / macOS universal /
|
||||
# Linux). Called from build.yml on PRs that touch desktop sources (gated
|
||||
# via the `tauri` filter in .github/config/.files.yaml). Also runnable
|
||||
# on demand via workflow_dispatch with a per-platform selector.
|
||||
@@ -48,17 +48,16 @@ jobs:
|
||||
PLATFORM: ${{ inputs.platform }}
|
||||
run: |
|
||||
WINDOWS='{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"}'
|
||||
MACOS_ARM='{"platform":"macos-15","args":"--target aarch64-apple-darwin","name":"macos-aarch64"}'
|
||||
MACOS_INTEL='{"platform":"macos-15-intel","args":"--target x86_64-apple-darwin","name":"macos-x86_64"}'
|
||||
MACOS='{"platform":"macos-15","args":"--target universal-apple-darwin","name":"macos-universal"}'
|
||||
LINUX='{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}'
|
||||
|
||||
# Resolve requested platform — populated by either workflow_dispatch
|
||||
# or workflow_call inputs; both paths default to "all".
|
||||
case "$PLATFORM" in
|
||||
windows) ENTRIES=("$WINDOWS") ;;
|
||||
macos) ENTRIES=("$MACOS_ARM" "$MACOS_INTEL") ;;
|
||||
macos) ENTRIES=("$MACOS") ;;
|
||||
linux) ENTRIES=("$LINUX") ;;
|
||||
*) ENTRIES=("$WINDOWS" "$MACOS_ARM" "$MACOS_INTEL" "$LINUX") ;;
|
||||
*) ENTRIES=("$WINDOWS" "$MACOS" "$LINUX") ;;
|
||||
esac
|
||||
|
||||
# Drop macOS entries when Apple certificate secret is unavailable
|
||||
@@ -111,7 +110,23 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@4be9e76fd7c4901c61fb841f559994984270fce7 # stable
|
||||
with:
|
||||
toolchain: stable
|
||||
targets: ${{ (matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel') && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||
targets: ${{ matrix.platform == 'macos-15' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||
|
||||
# x86_64 JDK is set up first so the aarch64 step below can leave its
|
||||
# JAVA_HOME as the active one. The macOS universal JRE build needs
|
||||
# jmods from both arches; the x64 path is captured into the env
|
||||
# before the second setup-java overwrites JAVA_HOME.
|
||||
- name: Set up x86_64 JDK 25 (macOS universal JRE)
|
||||
if: matrix.platform == 'macos-15'
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
java-version: "25"
|
||||
distribution: "temurin"
|
||||
architecture: "x64"
|
||||
|
||||
- name: Capture x86_64 JAVA_HOME
|
||||
if: matrix.platform == 'macos-15'
|
||||
run: echo "X64_JAVA_HOME=$JAVA_HOME" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Set up JDK 25
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
@@ -126,6 +141,15 @@ jobs:
|
||||
|
||||
- name: Setup Task
|
||||
uses: go-task/setup-task@3be4020d41929789a01026e0e427a4321ce0ad44 # v2.0.0
|
||||
|
||||
# Build the universal JRE before desktop:prepare so the jlink:runtime
|
||||
# task short-circuits on its `test -d runtime/jre` status check.
|
||||
- name: Build universal macOS JRE
|
||||
if: matrix.platform == 'macos-15'
|
||||
env:
|
||||
AARCH64_JAVA_HOME: ${{ env.JAVA_HOME }}
|
||||
run: task desktop:jlink:universal-mac
|
||||
|
||||
- name: Prepare desktop build
|
||||
run: task desktop:prepare
|
||||
env:
|
||||
@@ -213,7 +237,7 @@ jobs:
|
||||
}
|
||||
|
||||
- name: Import Apple Developer Certificate
|
||||
if: (matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel') && env.APPLE_CERTIFICATE != ''
|
||||
if: matrix.platform == 'macos-15' && env.APPLE_CERTIFICATE != ''
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
@@ -234,7 +258,7 @@ jobs:
|
||||
rm certificate.p12
|
||||
|
||||
- name: Verify Certificate
|
||||
if: (matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel') && env.APPLE_CERTIFICATE != ''
|
||||
if: matrix.platform == 'macos-15' && env.APPLE_CERTIFICATE != ''
|
||||
run: |
|
||||
echo "Verifying Apple Developer Certificate..."
|
||||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||
@@ -246,7 +270,7 @@ jobs:
|
||||
echo "Certificate imported successfully."
|
||||
|
||||
- name: Check DMG creation dependencies (macOS only)
|
||||
if: matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel'
|
||||
if: matrix.platform == 'macos-15'
|
||||
run: |
|
||||
echo "🔍 Checking DMG creation dependencies on ${{ matrix.platform }}..."
|
||||
echo "hdiutil version: $(hdiutil --version || echo 'NOT FOUND')"
|
||||
@@ -373,7 +397,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Verify notarization (macOS only)
|
||||
if: matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel'
|
||||
if: matrix.platform == 'macos-15'
|
||||
run: |
|
||||
echo "🔍 Verifying notarization status..."
|
||||
cd ./frontend/src-tauri/target
|
||||
@@ -398,7 +422,7 @@ jobs:
|
||||
# Only ship the MSI installer. The loose exe and WiX toolset exes
|
||||
# are not the user-facing installer - the MSI contains the signed inner exe.
|
||||
find . -name "*.msi" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.msi" \;
|
||||
elif [ "${{ matrix.platform }}" = "macos-15" ] || [ "${{ matrix.platform }}" = "macos-15-intel" ]; then
|
||||
elif [ "${{ matrix.platform }}" = "macos-15" ]; then
|
||||
find . -name "*.dmg" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.dmg" \;
|
||||
else
|
||||
find . -name "*.deb" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.deb" \;
|
||||
@@ -491,7 +515,7 @@ jobs:
|
||||
echo "❌ No Windows executable found"
|
||||
exit 1
|
||||
fi
|
||||
elif [ "${{ matrix.platform }}" = "macos-15" ] || [ "${{ matrix.platform }}" = "macos-15-intel" ]; then
|
||||
elif [ "${{ matrix.platform }}" = "macos-15" ]; then
|
||||
echo "Checking for macOS artifacts..."
|
||||
find . -name "*.dmg" | head -5
|
||||
if [ $(find . -name "*.dmg" | wc -l) -eq 0 ]; then
|
||||
@@ -556,8 +580,7 @@ jobs:
|
||||
// Map of expected artifact names to display info
|
||||
const artifactMap = {
|
||||
'Stirling-PDF-windows-x86_64': { icon: '🪟', platform: 'Windows x64', files: '.exe, .msi' },
|
||||
'Stirling-PDF-macos-aarch64': { icon: '🍎', platform: 'macOS ARM64', files: '.dmg' },
|
||||
'Stirling-PDF-macos-x86_64': { icon: '🍎', platform: 'macOS Intel', files: '.dmg' },
|
||||
'Stirling-PDF-macos-universal': { icon: '🍎', platform: 'macOS Universal', files: '.dmg' },
|
||||
'Stirling-PDF-linux-x86_64': { icon: '🐧', platform: 'Linux x64', files: '.deb, .rpm, .AppImage' }
|
||||
};
|
||||
|
||||
|
||||
+22
-2
@@ -1,7 +1,12 @@
|
||||
version: '3'
|
||||
|
||||
vars:
|
||||
JLINK_MODULES: "java.base,java.compiler,java.desktop,java.instrument,java.logging,java.management,java.naming,java.net.http,java.prefs,java.rmi,java.scripting,java.security.jgss,java.security.sasl,java.sql,java.transaction.xa,java.xml,java.xml.crypto,jdk.crypto.ec,jdk.crypto.cryptoki,jdk.unsupported"
|
||||
# Single source of truth for the jlink module list (also read by
|
||||
# frontend/scripts/build-universal-mac-jre.sh during CI). The desktop
|
||||
# taskfile runs with dir: frontend (see Taskfile.yml), so this path
|
||||
# is relative to that directory.
|
||||
JLINK_MODULES:
|
||||
sh: tr -d '\n' < src-tauri/jlink-modules.txt
|
||||
|
||||
tasks:
|
||||
prepare:
|
||||
@@ -96,7 +101,7 @@ tasks:
|
||||
jlink
|
||||
--add-modules {{.JLINK_MODULES}}
|
||||
--strip-debug
|
||||
--compress=2
|
||||
--compress=zip-6
|
||||
--no-header-files
|
||||
--no-man-pages
|
||||
--output src-tauri/runtime/jre
|
||||
@@ -107,3 +112,18 @@ tasks:
|
||||
desc: "Remove JLink runtime and bundled JARs"
|
||||
cmds:
|
||||
- rm -rf src-tauri/libs src-tauri/runtime
|
||||
|
||||
# macOS-only. Replaces jlink:runtime's single-arch JRE with a universal
|
||||
# (arm64 + x86_64) one for the universal Tauri shell. Runs the x86_64
|
||||
# jlink under Rosetta on Apple Silicon, so it is opt-in and not part of
|
||||
# the default desktop:build flow. Requires AARCH64_JAVA_HOME and
|
||||
# X64_JAVA_HOME to point at matching JDK installations with jmods/.
|
||||
jlink:universal-mac:
|
||||
desc: "Create universal (arm64+x86_64) JRE for the macOS Tauri build"
|
||||
deps: [jlink:jar]
|
||||
platforms: [darwin]
|
||||
env:
|
||||
JLINK_MODULES: "{{.JLINK_MODULES}}"
|
||||
OUTPUT_DIR: src-tauri/runtime/jre
|
||||
cmds:
|
||||
- scripts/build-universal-mac-jre.sh
|
||||
|
||||
Executable
+108
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build a universal (arm64 + x86_64) JRE bundle for the macOS Tauri app.
|
||||
#
|
||||
# jlink can only emit a single-architecture runtime, but the Tauri shell is
|
||||
# universal-apple-darwin. Without this merge the bundled JRE would only run
|
||||
# on whichever arch the runner used. We jlink twice (once per target JDK's
|
||||
# jmods) and lipo-fatten every Mach-O file in the result.
|
||||
#
|
||||
# Inputs (env):
|
||||
# AARCH64_JAVA_HOME path to an aarch64 JDK with jmods/
|
||||
# X64_JAVA_HOME path to an x86_64 JDK with jmods/
|
||||
# JLINK_MODULES comma-separated module list (matches desktop.yml)
|
||||
# OUTPUT_DIR target directory (will be wiped); defaults to
|
||||
# frontend/src-tauri/runtime/jre
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
: "${AARCH64_JAVA_HOME:?AARCH64_JAVA_HOME must be set}"
|
||||
: "${X64_JAVA_HOME:?X64_JAVA_HOME must be set}"
|
||||
: "${JLINK_MODULES:?JLINK_MODULES must be set}"
|
||||
|
||||
OUTPUT_DIR="${OUTPUT_DIR:-frontend/src-tauri/runtime/jre}"
|
||||
|
||||
if [[ "$(uname -s)" != "Darwin" ]]; then
|
||||
echo "build-universal-mac-jre.sh only runs on macOS" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# x86_64 jlink runs under Rosetta on Apple Silicon. If Rosetta isn't
|
||||
# installed the failure mode is a cryptic "Bad CPU type" from exec, so
|
||||
# fail loudly up front when running on arm64 without it.
|
||||
if [[ "$(uname -m)" == "arm64" ]] && ! arch -x86_64 /usr/bin/true >/dev/null 2>&1; then
|
||||
echo "Rosetta 2 is required to run x86_64 jlink on Apple Silicon. Install with: softwareupdate --install-rosetta --agree-to-license" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WORK_DIR="$(mktemp -d -t universal-jre)"
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT INT TERM
|
||||
|
||||
ARM_JRE="$WORK_DIR/jre-aarch64"
|
||||
X64_JRE="$WORK_DIR/jre-x86_64"
|
||||
|
||||
# Each jlink invocation must run on the native arch of its JDK: jlink
|
||||
# stamps out launcher executables (bin/java, bin/rmiregistry, etc.)
|
||||
# matching the host binary, regardless of --module-path. So we run the
|
||||
# arm64 jlink for the arm64 JRE and the x86_64 jlink for the x86_64
|
||||
# JRE.
|
||||
run_jlink() {
|
||||
local java_home="$1"
|
||||
local out="$2"
|
||||
"$java_home/bin/jlink" \
|
||||
--module-path "$java_home/jmods" \
|
||||
--add-modules "$JLINK_MODULES" \
|
||||
--strip-debug \
|
||||
--compress=zip-6 \
|
||||
--no-header-files \
|
||||
--no-man-pages \
|
||||
--output "$out"
|
||||
}
|
||||
|
||||
echo "Building aarch64 JRE from $AARCH64_JAVA_HOME"
|
||||
run_jlink "$AARCH64_JAVA_HOME" "$ARM_JRE"
|
||||
|
||||
echo "Building x86_64 JRE from $X64_JAVA_HOME (runs under Rosetta on Apple Silicon)"
|
||||
run_jlink "$X64_JAVA_HOME" "$X64_JRE"
|
||||
|
||||
rm -rf "$OUTPUT_DIR"
|
||||
mkdir -p "$(dirname "$OUTPUT_DIR")"
|
||||
cp -R "$ARM_JRE" "$OUTPUT_DIR"
|
||||
|
||||
# Replace every Mach-O file in the copied tree with a fat binary.
|
||||
# Files that aren't Mach-O (text, modules archive, etc.) are left as-is.
|
||||
merged=0
|
||||
skipped=0
|
||||
while IFS= read -r -d '' arm_file; do
|
||||
rel="${arm_file#"$ARM_JRE"/}"
|
||||
x64_file="$X64_JRE/$rel"
|
||||
out_file="$OUTPUT_DIR/$rel"
|
||||
|
||||
if [[ ! -f "$x64_file" ]]; then
|
||||
skipped=$((skipped + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
if ! file "$arm_file" | grep -q "Mach-O"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
lipo -create "$arm_file" "$x64_file" -output "$out_file"
|
||||
merged=$((merged + 1))
|
||||
done < <(find "$ARM_JRE" -type f -print0)
|
||||
|
||||
echo "Universal JRE written to $OUTPUT_DIR (merged $merged Mach-O files, skipped $skipped arm-only files)"
|
||||
|
||||
if [[ "$merged" -eq 0 ]]; then
|
||||
echo "Refusing to ship a JRE with zero merged Mach-O binaries" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Sanity-check: the launcher must be a fat binary or the app crashes on the
|
||||
# arch we didn't lipo for. `lipo -archs` prints just the arch names space-
|
||||
# separated (avoiding fragile grep alternation across BSD/GNU grep).
|
||||
java_archs="$(lipo -archs "$OUTPUT_DIR/bin/java" 2>/dev/null || true)"
|
||||
if [[ "$java_archs" != *arm64* || "$java_archs" != *x86_64* ]]; then
|
||||
echo "bin/java is not a universal binary (archs: ${java_archs:-unknown})" >&2
|
||||
lipo -info "$OUTPUT_DIR/bin/java" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1 @@
|
||||
java.base,java.compiler,java.desktop,java.instrument,java.logging,java.management,java.naming,java.net.http,java.prefs,java.rmi,java.scripting,java.security.jgss,java.security.sasl,java.sql,java.transaction.xa,java.xml,java.xml.crypto,jdk.crypto.ec,jdk.crypto.cryptoki,jdk.unsupported
|
||||
Reference in New Issue
Block a user