mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 19:33:11 +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
|
echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"}]}' >> $GITHUB_OUTPUT
|
||||||
;;
|
;;
|
||||||
"macos")
|
"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")
|
"linux")
|
||||||
echo 'matrix={"include":[{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}]}' >> $GITHUB_OUTPUT
|
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
|
esac
|
||||||
else
|
else
|
||||||
# For push/release events, build all platforms
|
# 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
|
fi
|
||||||
|
|
||||||
build-jars:
|
build-jars:
|
||||||
@@ -218,7 +218,23 @@ jobs:
|
|||||||
uses: dtolnay/rust-toolchain@4be9e76fd7c4901c61fb841f559994984270fce7 # stable
|
uses: dtolnay/rust-toolchain@4be9e76fd7c4901c61fb841f559994984270fce7 # stable
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
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
|
- name: Set up JDK 25
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||||
@@ -234,6 +250,14 @@ jobs:
|
|||||||
- name: Install Task
|
- name: Install Task
|
||||||
uses: go-task/setup-task@3be4020d41929789a01026e0e427a4321ce0ad44 # v2.0.0
|
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
|
- name: Prepare desktop build
|
||||||
run: task desktop:prepare
|
run: task desktop:prepare
|
||||||
env:
|
env:
|
||||||
@@ -321,7 +345,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
- name: Import Apple Developer Certificate
|
- 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:
|
env:
|
||||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||||
@@ -342,7 +366,7 @@ jobs:
|
|||||||
rm certificate.p12
|
rm certificate.p12
|
||||||
|
|
||||||
- name: Verify Certificate
|
- 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: |
|
run: |
|
||||||
echo "Verifying Apple Developer Certificate..."
|
echo "Verifying Apple Developer Certificate..."
|
||||||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
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
|
# 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.
|
# are not the user-facing installer - the MSI contains the signed inner exe.
|
||||||
find . -name "*.msi" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.msi" \;
|
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 "*.dmg" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.dmg" \;
|
||||||
find . -name "*.app" -exec cp -r {} "../../../dist/Stirling-PDF-${{ matrix.name }}.app" \;
|
find . -name "*.app" -exec cp -r {} "../../../dist/Stirling-PDF-${{ matrix.name }}.app" \;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
version: ${{ steps.info.outputs.version }}
|
version: ${{ steps.info.outputs.version }}
|
||||||
dmg_arm64_sha256: ${{ steps.hashes.outputs.dmg_arm64_sha256 }}
|
dmg_sha256: ${{ steps.hashes.outputs.dmg_sha256 }}
|
||||||
dmg_x86_64_sha256: ${{ steps.hashes.outputs.dmg_x86_64_sha256 }}
|
|
||||||
msi_sha256: ${{ steps.hashes.outputs.msi_sha256 }}
|
msi_sha256: ${{ steps.hashes.outputs.msi_sha256 }}
|
||||||
deb_sha256: ${{ steps.hashes.outputs.deb_sha256 }}
|
deb_sha256: ${{ steps.hashes.outputs.deb_sha256 }}
|
||||||
jar_sha256: ${{ steps.hashes.outputs.jar_sha256 }}
|
jar_sha256: ${{ steps.hashes.outputs.jar_sha256 }}
|
||||||
@@ -63,17 +62,15 @@ jobs:
|
|||||||
sha256sum "$file" | awk '{print $1}'
|
sha256sum "$file" | awk '{print $1}'
|
||||||
}
|
}
|
||||||
|
|
||||||
DMG_ARM64_SHA=$(download_sha256 "${BASE}/Stirling-PDF-macos-aarch64.dmg")
|
DMG_SHA=$(download_sha256 "${BASE}/Stirling-PDF-macos-universal.dmg")
|
||||||
DMG_X64_SHA=$(download_sha256 "${BASE}/Stirling-PDF-macos-x86_64.dmg")
|
|
||||||
MSI_SHA=$(download_sha256 "${BASE}/Stirling-PDF-windows-x86_64.msi")
|
MSI_SHA=$(download_sha256 "${BASE}/Stirling-PDF-windows-x86_64.msi")
|
||||||
DEB_SHA=$(download_sha256 "${BASE}/Stirling-PDF-linux-x86_64.deb")
|
DEB_SHA=$(download_sha256 "${BASE}/Stirling-PDF-linux-x86_64.deb")
|
||||||
JAR_SHA=$(download_sha256 "${BASE}/Stirling-PDF-with-login.jar")
|
JAR_SHA=$(download_sha256 "${BASE}/Stirling-PDF-with-login.jar")
|
||||||
|
|
||||||
echo "dmg_arm64_sha256=$DMG_ARM64_SHA" >> "$GITHUB_OUTPUT"
|
echo "dmg_sha256=$DMG_SHA" >> "$GITHUB_OUTPUT"
|
||||||
echo "dmg_x86_64_sha256=$DMG_X64_SHA" >> "$GITHUB_OUTPUT"
|
echo "msi_sha256=$MSI_SHA" >> "$GITHUB_OUTPUT"
|
||||||
echo "msi_sha256=$MSI_SHA" >> "$GITHUB_OUTPUT"
|
echo "deb_sha256=$DEB_SHA" >> "$GITHUB_OUTPUT"
|
||||||
echo "deb_sha256=$DEB_SHA" >> "$GITHUB_OUTPUT"
|
echo "jar_sha256=$JAR_SHA" >> "$GITHUB_OUTPUT"
|
||||||
echo "jar_sha256=$JAR_SHA" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
update-homebrew-and-scoop:
|
update-homebrew-and-scoop:
|
||||||
needs: get-release-info
|
needs: get-release-info
|
||||||
@@ -93,22 +90,21 @@ jobs:
|
|||||||
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
|
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
|
||||||
path: tap
|
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)
|
- name: Update Homebrew cask (Casks/stirling-pdf.rb)
|
||||||
env:
|
env:
|
||||||
VERSION: ${{ needs.get-release-info.outputs.version }}
|
VERSION: ${{ needs.get-release-info.outputs.version }}
|
||||||
ARM64_SHA: ${{ needs.get-release-info.outputs.dmg_arm64_sha256 }}
|
DMG_SHA: ${{ needs.get-release-info.outputs.dmg_sha256 }}
|
||||||
X64_SHA: ${{ needs.get-release-info.outputs.dmg_x86_64_sha256 }}
|
|
||||||
run: |
|
run: |
|
||||||
CASK="tap/Casks/stirling-pdf.rb"
|
CASK="tap/Casks/stirling-pdf.rb"
|
||||||
sed -i "s/version \".*\"/version \"${VERSION}\"/" "$CASK"
|
sed -i "s/version \"[^\"]*\"/version \"${VERSION}\"/" "$CASK"
|
||||||
awk -v arm="$ARM64_SHA" -v x64="$X64_SHA" '
|
sed -i "s/sha256 \"[^\"]*\"/sha256 \"${DMG_SHA}\"/g" "$CASK"
|
||||||
/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"
|
|
||||||
|
|
||||||
- name: Update Homebrew formula (Formula/stirling-pdf-server.rb)
|
- name: Update Homebrew formula (Formula/stirling-pdf-server.rb)
|
||||||
env:
|
env:
|
||||||
@@ -116,8 +112,8 @@ jobs:
|
|||||||
JAR_SHA: ${{ needs.get-release-info.outputs.jar_sha256 }}
|
JAR_SHA: ${{ needs.get-release-info.outputs.jar_sha256 }}
|
||||||
run: |
|
run: |
|
||||||
FORMULA="tap/Formula/stirling-pdf-server.rb"
|
FORMULA="tap/Formula/stirling-pdf-server.rb"
|
||||||
sed -i "s/version \".*\"/version \"${VERSION}\"/" "$FORMULA"
|
sed -i "s/version \"[^\"]*\"/version \"${VERSION}\"/" "$FORMULA"
|
||||||
sed -i "s/sha256 \".*\"/sha256 \"${JAR_SHA}\"/" "$FORMULA"
|
sed -i "s/sha256 \"[^\"]*\"/sha256 \"${JAR_SHA}\"/" "$FORMULA"
|
||||||
|
|
||||||
- name: Update Scoop stirling-pdf.json
|
- name: Update Scoop stirling-pdf.json
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
name: Build Tauri Applications
|
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
|
# Linux). Called from build.yml on PRs that touch desktop sources (gated
|
||||||
# via the `tauri` filter in .github/config/.files.yaml). Also runnable
|
# via the `tauri` filter in .github/config/.files.yaml). Also runnable
|
||||||
# on demand via workflow_dispatch with a per-platform selector.
|
# on demand via workflow_dispatch with a per-platform selector.
|
||||||
@@ -48,17 +48,16 @@ jobs:
|
|||||||
PLATFORM: ${{ inputs.platform }}
|
PLATFORM: ${{ inputs.platform }}
|
||||||
run: |
|
run: |
|
||||||
WINDOWS='{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64"}'
|
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='{"platform":"macos-15","args":"--target universal-apple-darwin","name":"macos-universal"}'
|
||||||
MACOS_INTEL='{"platform":"macos-15-intel","args":"--target x86_64-apple-darwin","name":"macos-x86_64"}'
|
|
||||||
LINUX='{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}'
|
LINUX='{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64"}'
|
||||||
|
|
||||||
# Resolve requested platform — populated by either workflow_dispatch
|
# Resolve requested platform — populated by either workflow_dispatch
|
||||||
# or workflow_call inputs; both paths default to "all".
|
# or workflow_call inputs; both paths default to "all".
|
||||||
case "$PLATFORM" in
|
case "$PLATFORM" in
|
||||||
windows) ENTRIES=("$WINDOWS") ;;
|
windows) ENTRIES=("$WINDOWS") ;;
|
||||||
macos) ENTRIES=("$MACOS_ARM" "$MACOS_INTEL") ;;
|
macos) ENTRIES=("$MACOS") ;;
|
||||||
linux) ENTRIES=("$LINUX") ;;
|
linux) ENTRIES=("$LINUX") ;;
|
||||||
*) ENTRIES=("$WINDOWS" "$MACOS_ARM" "$MACOS_INTEL" "$LINUX") ;;
|
*) ENTRIES=("$WINDOWS" "$MACOS" "$LINUX") ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Drop macOS entries when Apple certificate secret is unavailable
|
# Drop macOS entries when Apple certificate secret is unavailable
|
||||||
@@ -111,7 +110,23 @@ jobs:
|
|||||||
uses: dtolnay/rust-toolchain@4be9e76fd7c4901c61fb841f559994984270fce7 # stable
|
uses: dtolnay/rust-toolchain@4be9e76fd7c4901c61fb841f559994984270fce7 # stable
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
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
|
- name: Set up JDK 25
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||||
@@ -126,6 +141,15 @@ jobs:
|
|||||||
|
|
||||||
- name: Setup Task
|
- name: Setup Task
|
||||||
uses: go-task/setup-task@3be4020d41929789a01026e0e427a4321ce0ad44 # v2.0.0
|
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
|
- name: Prepare desktop build
|
||||||
run: task desktop:prepare
|
run: task desktop:prepare
|
||||||
env:
|
env:
|
||||||
@@ -213,7 +237,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
- name: Import Apple Developer Certificate
|
- 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:
|
env:
|
||||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||||
@@ -234,7 +258,7 @@ jobs:
|
|||||||
rm certificate.p12
|
rm certificate.p12
|
||||||
|
|
||||||
- name: Verify Certificate
|
- 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: |
|
run: |
|
||||||
echo "Verifying Apple Developer Certificate..."
|
echo "Verifying Apple Developer Certificate..."
|
||||||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||||
@@ -246,7 +270,7 @@ jobs:
|
|||||||
echo "Certificate imported successfully."
|
echo "Certificate imported successfully."
|
||||||
|
|
||||||
- name: Check DMG creation dependencies (macOS only)
|
- name: Check DMG creation dependencies (macOS only)
|
||||||
if: matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel'
|
if: matrix.platform == 'macos-15'
|
||||||
run: |
|
run: |
|
||||||
echo "🔍 Checking DMG creation dependencies on ${{ matrix.platform }}..."
|
echo "🔍 Checking DMG creation dependencies on ${{ matrix.platform }}..."
|
||||||
echo "hdiutil version: $(hdiutil --version || echo 'NOT FOUND')"
|
echo "hdiutil version: $(hdiutil --version || echo 'NOT FOUND')"
|
||||||
@@ -373,7 +397,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Verify notarization (macOS only)
|
- name: Verify notarization (macOS only)
|
||||||
if: matrix.platform == 'macos-15' || matrix.platform == 'macos-15-intel'
|
if: matrix.platform == 'macos-15'
|
||||||
run: |
|
run: |
|
||||||
echo "🔍 Verifying notarization status..."
|
echo "🔍 Verifying notarization status..."
|
||||||
cd ./frontend/src-tauri/target
|
cd ./frontend/src-tauri/target
|
||||||
@@ -398,7 +422,7 @@ jobs:
|
|||||||
# Only ship the MSI installer. The loose exe and WiX toolset exes
|
# 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.
|
# are not the user-facing installer - the MSI contains the signed inner exe.
|
||||||
find . -name "*.msi" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.msi" \;
|
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 "*.dmg" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.dmg" \;
|
||||||
else
|
else
|
||||||
find . -name "*.deb" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.deb" \;
|
find . -name "*.deb" -exec cp {} "../../../dist/Stirling-PDF-${{ matrix.name }}.deb" \;
|
||||||
@@ -491,7 +515,7 @@ jobs:
|
|||||||
echo "❌ No Windows executable found"
|
echo "❌ No Windows executable found"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
elif [ "${{ matrix.platform }}" = "macos-15" ] || [ "${{ matrix.platform }}" = "macos-15-intel" ]; then
|
elif [ "${{ matrix.platform }}" = "macos-15" ]; then
|
||||||
echo "Checking for macOS artifacts..."
|
echo "Checking for macOS artifacts..."
|
||||||
find . -name "*.dmg" | head -5
|
find . -name "*.dmg" | head -5
|
||||||
if [ $(find . -name "*.dmg" | wc -l) -eq 0 ]; then
|
if [ $(find . -name "*.dmg" | wc -l) -eq 0 ]; then
|
||||||
@@ -556,8 +580,7 @@ jobs:
|
|||||||
// Map of expected artifact names to display info
|
// Map of expected artifact names to display info
|
||||||
const artifactMap = {
|
const artifactMap = {
|
||||||
'Stirling-PDF-windows-x86_64': { icon: '🪟', platform: 'Windows x64', files: '.exe, .msi' },
|
'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-universal': { icon: '🍎', platform: 'macOS Universal', files: '.dmg' },
|
||||||
'Stirling-PDF-macos-x86_64': { icon: '🍎', platform: 'macOS Intel', files: '.dmg' },
|
|
||||||
'Stirling-PDF-linux-x86_64': { icon: '🐧', platform: 'Linux x64', files: '.deb, .rpm, .AppImage' }
|
'Stirling-PDF-linux-x86_64': { icon: '🐧', platform: 'Linux x64', files: '.deb, .rpm, .AppImage' }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+22
-2
@@ -1,7 +1,12 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
vars:
|
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:
|
tasks:
|
||||||
prepare:
|
prepare:
|
||||||
@@ -96,7 +101,7 @@ tasks:
|
|||||||
jlink
|
jlink
|
||||||
--add-modules {{.JLINK_MODULES}}
|
--add-modules {{.JLINK_MODULES}}
|
||||||
--strip-debug
|
--strip-debug
|
||||||
--compress=2
|
--compress=zip-6
|
||||||
--no-header-files
|
--no-header-files
|
||||||
--no-man-pages
|
--no-man-pages
|
||||||
--output src-tauri/runtime/jre
|
--output src-tauri/runtime/jre
|
||||||
@@ -107,3 +112,18 @@ tasks:
|
|||||||
desc: "Remove JLink runtime and bundled JARs"
|
desc: "Remove JLink runtime and bundled JARs"
|
||||||
cmds:
|
cmds:
|
||||||
- rm -rf src-tauri/libs src-tauri/runtime
|
- 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