Skip to content

Commit 96f89f3

Browse files
committed
ci: fix JNI builds on Linux ARM64 + Windows ARM64, add GraalVM release
- Install Android SDK on ubuntu-24.04-arm so com.android.library configures cleanly (SDK is preinstalled on ubuntu-latest but not on ARM images). - build-windows.bat always calls vcvarsall.bat with the requested arch, using amd64_arm64 when cross-compiling ARM64 from an x64 host. Previously a preexisting x64 cl.exe on PATH prevented the arm64 env from being set and caused LNK2019 unresolved external errors on the ARM64 DLL. - Simplify Maven coordinate from dev.nucleusframework.pdf:pdfium to dev.nucleusframework:pdfium, update README snippet accordingly. - Add release-graalvm.yaml: on every v* tag, build GraalVM native-image packages for Linux x64/arm64, macOS arm64/intel, Windows x64 and upload .deb/.dmg/.exe to a GitHub Release.
1 parent 301a829 commit 96f89f3

5 files changed

Lines changed: 188 additions & 26 deletions

File tree

.github/workflows/build-natives.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ jobs:
2727
- name: Install clang++
2828
run: sudo apt-get update && sudo apt-get install -y clang
2929

30+
# ubuntu-24.04-arm has no Android SDK preinstalled; com.android.library
31+
# needs one at configuration time. ubuntu-latest x86-64 already ships with it.
32+
- name: Setup Android SDK
33+
if: matrix.arch == 'aarch64'
34+
uses: android-actions/setup-android@v3
35+
3036
- name: Setup Gradle
3137
uses: gradle/actions/setup-gradle@v5
3238

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
name: Release GraalVM Native Image (Example Desktop App)
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: write
11+
12+
concurrency:
13+
group: release-graalvm-${{ github.ref }}
14+
cancel-in-progress: false
15+
16+
jobs:
17+
build-natives:
18+
uses: ./.github/workflows/build-natives.yaml
19+
20+
build:
21+
needs: build-natives
22+
name: GraalVM - ${{ matrix.name }}
23+
runs-on: ${{ matrix.os }}
24+
timeout-minutes: 60
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
include:
29+
- name: Linux x64
30+
os: ubuntu-latest
31+
arch: amd64
32+
- name: Linux ARM64
33+
os: ubuntu-24.04-arm
34+
arch: arm64
35+
- name: macOS ARM64
36+
os: macos-latest
37+
arch: arm64
38+
- name: macOS Intel
39+
os: macos-15-intel
40+
arch: amd64
41+
- name: Windows x64
42+
os: windows-latest
43+
arch: amd64
44+
45+
steps:
46+
- name: Checkout repo
47+
uses: actions/checkout@v4
48+
with:
49+
fetch-depth: 0
50+
51+
- name: Download PDFium JNI natives
52+
uses: actions/download-artifact@v4
53+
with:
54+
path: pdfium/src/jvmMain/resources/pdfium/native/
55+
pattern: 'pdfium-jni-*'
56+
merge-multiple: true
57+
58+
- name: Select Xcode 26 (macOS)
59+
if: runner.os == 'macOS'
60+
run: sudo xcode-select -s /Applications/Xcode_26.0.app/Contents/Developer
61+
62+
- name: Setup Liberica NIK (GraalVM)
63+
uses: graalvm/setup-graalvm@v1
64+
with:
65+
distribution: 'liberica'
66+
java-version: '25'
67+
68+
- name: Setup MSVC (Windows)
69+
if: runner.os == 'Windows'
70+
uses: ilammy/msvc-dev-cmd@v1
71+
72+
- name: Setup Android SDK (Linux ARM64)
73+
if: matrix.os == 'ubuntu-24.04-arm'
74+
uses: android-actions/setup-android@v3
75+
76+
- name: Setup Gradle
77+
uses: gradle/actions/setup-gradle@v5
78+
79+
- name: Build GraalVM native package
80+
shell: bash
81+
run: |
82+
set -euo pipefail
83+
case "$RUNNER_OS" in
84+
Linux) TASK=packageGraalvmDeb ;;
85+
macOS) TASK=packageGraalvmDmg ;;
86+
Windows) TASK=packageGraalvmNsis ;;
87+
esac
88+
./gradlew ":example:$TASK" -PnativeMarch=compatibility --no-daemon --stacktrace
89+
90+
- name: Upload GraalVM artifact
91+
uses: actions/upload-artifact@v4
92+
with:
93+
name: graalvm-${{ runner.os }}-${{ matrix.arch }}
94+
path: |
95+
example/build/compose/binaries/**/graalvm-*/**
96+
if-no-files-found: error
97+
98+
publish:
99+
name: Publish GitHub Release
100+
needs: build
101+
if: ${{ !cancelled() && needs.build.result == 'success' }}
102+
runs-on: ubuntu-latest
103+
timeout-minutes: 15
104+
env:
105+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
106+
steps:
107+
- name: Download all GraalVM artifacts
108+
uses: actions/download-artifact@v4
109+
with:
110+
path: artifacts
111+
pattern: graalvm-*
112+
113+
- name: Determine version
114+
shell: bash
115+
run: |
116+
set -euo pipefail
117+
TAG="${GITHUB_REF_NAME}"
118+
VERSION="${TAG#v}"
119+
echo "TAG=$TAG" >> "$GITHUB_ENV"
120+
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
121+
if [[ "$VERSION" == *"-alpha"* ]] || [[ "$VERSION" == *"-beta"* ]]; then
122+
echo "PRERELEASE=true" >> "$GITHUB_ENV"
123+
else
124+
echo "PRERELEASE=false" >> "$GITHUB_ENV"
125+
fi
126+
127+
- name: Collect release assets
128+
shell: bash
129+
run: |
130+
set -euo pipefail
131+
mkdir -p release-assets
132+
find artifacts -type f \( -name '*.deb' -o -name '*.dmg' -o -name '*.exe' \) -exec cp {} release-assets/ \;
133+
ls -lh release-assets/
134+
135+
- name: Upload to GitHub Release
136+
shell: bash
137+
run: |
138+
set -euo pipefail
139+
REPO="${{ github.repository }}"
140+
if [ -z "$(ls -A release-assets/)" ]; then
141+
echo "::error::No release assets found"
142+
exit 1
143+
fi
144+
if ! gh release view "$TAG" -R "$REPO" > /dev/null 2>&1; then
145+
ARGS=(release create "$TAG" --title "$TAG" --generate-notes -R "$REPO")
146+
if [ "$PRERELEASE" = "true" ]; then
147+
ARGS+=(--prerelease)
148+
fi
149+
gh "${ARGS[@]}"
150+
fi
151+
gh release upload "$TAG" release-assets/* --clobber -R "$REPO"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Published to Maven Central. Requires Gradle 8.10+ and Kotlin 2.3.20+. The
4444
kotlin {
4545
sourceSets {
4646
commonMain.dependencies {
47-
implementation("dev.nucleusframework.pdf:pdfium:0.1.0")
47+
implementation("dev.nucleusframework:pdfium:149.0.7802.0")
4848
}
4949
}
5050
}

pdfium/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ val publishVersion: String =
3232
?.removePrefix("refs/tags/v")
3333
?: "0.1.0"
3434

35-
group = "dev.nucleusframework.pdf"
35+
group = "dev.nucleusframework"
3636
version = publishVersion
3737

3838
val pdfiumVersion = libs.versions.pdfium.bblanchon.get()
@@ -564,7 +564,7 @@ tasks.register<JavaExec>("smokeTest") {
564564
// ---------- Maven Central publication ----------
565565

566566
mavenPublishing {
567-
coordinates("dev.nucleusframework.pdf", "pdfium", publishVersion)
567+
coordinates("dev.nucleusframework", "pdfium", publishVersion)
568568

569569
pom {
570570
name.set("Nucleus PDF — PDFium")

pdfium/src/jvmMain/native/build-windows.bat

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,35 @@ if "%PDFIUM_LIB%"=="" (echo PDFIUM_LIB unset & exit /b 1)
1111
if "%OUT_DIR%"=="" (echo OUT_DIR unset & exit /b 1)
1212
if "%JAVA_HOME%"=="" (echo JAVA_HOME unset & exit /b 1)
1313

14-
REM Bring MSVC into the environment if cl.exe is not already on PATH.
15-
where cl.exe >nul 2>&1
14+
REM Always call vcvarsall.bat with the target arch. Even when cl.exe is already on
15+
REM PATH (e.g. GitHub runners with ilammy/msvc-dev-cmd default x64), we still need
16+
REM to reconfigure the env for the requested %ARCH% so cross-compiles like arm64
17+
REM link against the right libraries.
18+
set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
19+
if not exist "!VSWHERE!" set "VSWHERE=%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe"
20+
if not exist "!VSWHERE!" (
21+
echo ERROR: vswhere.exe not found. Install Visual Studio Build Tools.
22+
exit /b 1
23+
)
24+
for /f "usebackq tokens=*" %%i in (`"!VSWHERE!" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSINSTALL=%%i"
25+
if "!VSINSTALL!"=="" (
26+
echo ERROR: No Visual Studio installation with C++ tools detected by vswhere.
27+
exit /b 1
28+
)
29+
set "VCVARS=!VSINSTALL!\VC\Auxiliary\Build\vcvarsall.bat"
30+
if not exist "!VCVARS!" (
31+
echo ERROR: vcvarsall.bat not found at !VCVARS!
32+
exit /b 1
33+
)
34+
REM For arm64 target on an x64 host, vcvarsall needs the cross-compile variant.
35+
set "VCVARS_ARCH=%ARCH%"
36+
if /I "%ARCH%"=="arm64" (
37+
if /I not "%PROCESSOR_ARCHITECTURE%"=="ARM64" set "VCVARS_ARCH=amd64_arm64"
38+
)
39+
call "!VCVARS!" %VCVARS_ARCH%
1640
if errorlevel 1 (
17-
set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
18-
if not exist "!VSWHERE!" set "VSWHERE=%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe"
19-
if not exist "!VSWHERE!" (
20-
echo ERROR: cl.exe not on PATH and vswhere.exe not found. Install Visual Studio Build Tools or run from a Native Tools prompt.
21-
exit /b 1
22-
)
23-
for /f "usebackq tokens=*" %%i in (`"!VSWHERE!" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSINSTALL=%%i"
24-
if "!VSINSTALL!"=="" (
25-
echo ERROR: No Visual Studio installation with C++ tools detected by vswhere.
26-
exit /b 1
27-
)
28-
set "VCVARS=!VSINSTALL!\VC\Auxiliary\Build\vcvarsall.bat"
29-
if not exist "!VCVARS!" (
30-
echo ERROR: vcvarsall.bat not found at !VCVARS!
31-
exit /b 1
32-
)
33-
call "!VCVARS!" %ARCH%
34-
if errorlevel 1 (
35-
echo ERROR: vcvarsall.bat %ARCH% failed.
36-
exit /b 1
37-
)
41+
echo ERROR: vcvarsall.bat %VCVARS_ARCH% failed.
42+
exit /b 1
3843
)
3944

4045
if not exist "%OUT_DIR%" mkdir "%OUT_DIR%"

0 commit comments

Comments
 (0)