-
Notifications
You must be signed in to change notification settings - Fork 15
270 lines (244 loc) · 12.6 KB
/
Copy pathpublish.yml
File metadata and controls
270 lines (244 loc) · 12.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
name: release
# Tag-triggered Maven Central release.
#
# Two-phase flow so the published JAR for skainet-backend-native-cpu
# carries every supported native lib (.so / .dylib / .dll) regardless
# of which OS hosts the publish step:
#
# 1. build-native — matrix job: each runner builds its own host's
# libskainet_kernels via CMake, uploads the resulting binary as
# an artifact named `native-<arch>`. fail-fast stays on so a
# missing arch aborts the release rather than shipping a partial
# fat JAR.
#
# 2. publish — runs on macOS (signing tooling is wired up there),
# downloads every native artifact, stages them into the native
# module's resources tree (`build/native/resources/native/<arch>/`),
# then runs `./gradlew publish`. Gradle's own CMake step rebuilds
# for the macOS host into native/macos-arm64/; the pre-staged libs
# for the other arches sit in their own subdirs and survive.
# resources.srcDir(nativeResourcesRoot) on jvmMain picks them all
# up into the published JAR.
#
# The publish job also builds and publishes the skainet-backend-jni-cpu AAR
# (Android JNI kernel provider). Its native .so's are cross-compiled by the
# NDK during `./gradlew publish`, so the publish runner sets up the Android
# SDK + a pinned NDK (see the publish job) — independent of the build-native
# matrix above, which only produces the FFM shared libs.
#
# Linux ARM64 is intentionally absent: Kotlin/Native plugin 2.3.21
# doesn't support `linux aarch64` as a HOST target ("Unknown host
# target" — see SKaiNET PR #577). Linux ARM64 consumers fall back
# cleanly to the Panama priority-50 provider.
on:
push:
tags:
- '**'
# Set default permission for all jobs to none. Publishing authenticates to Maven
# Central and signs with GPG through repository secrets, which are independent of
# GITHUB_TOKEN — nothing here needs write access to the repository itself.
permissions: {}
jobs:
build-native:
name: native ${{ matrix.arch_label }}
strategy:
fail-fast: true
matrix:
include:
- os: ubuntu-latest
arch_label: linux-x86_64
lib_name: libskainet_kernels.so
- os: macos-14
arch_label: macos-arm64
lib_name: libskainet_kernels.dylib
- os: windows-latest
arch_label: windows-x86_64
lib_name: skainet_kernels.dll
runs-on: ${{ matrix.os }}
timeout-minutes: 30
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up JDK 25
uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c # v6.0.0
with:
distribution: 'zulu'
java-version: 25
- name: Verify cmake
run: cmake --version
- name: Build native lib (Unix)
if: runner.os != 'Windows'
env:
GRADLE_OPTS: -Dorg.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8
run: |
./gradlew --no-daemon --stacktrace --no-configuration-cache \
:skainet-backends:skainet-backend-native-cpu:packageNativeKernels
- name: Build native lib (Windows)
if: runner.os == 'Windows'
shell: pwsh
env:
GRADLE_OPTS: -Dorg.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8
run: |
.\gradlew.bat --no-daemon --stacktrace --no-configuration-cache `
:skainet-backends:skainet-backend-native-cpu:packageNativeKernels
- name: Upload native artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: native-${{ matrix.arch_label }}
path: skainet-backends/skainet-backend-native-cpu/build/native/resources/native/${{ matrix.arch_label }}/${{ matrix.lib_name }}
if-no-files-found: error
retention-days: 14
# K/N klib embedding (#941): the linux ELF static archives are produced
# only on the ubuntu leg — x64 from the host CMake build above, arm64 via
# the -PcrossArm64 cross build — and injected into the publish job so the
# linux klibs carry their machine code (the publish host is macOS, whose
# CMake build emits Mach-O and must not be embedded into linux klibs).
- name: Cross-build aarch64 static archive (Linux only)
if: matrix.arch_label == 'linux-x86_64'
env:
GRADLE_OPTS: -Dorg.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8
run: |
sudo apt-get update -q && sudo apt-get install -y -q gcc-aarch64-linux-gnu
./gradlew --no-daemon --stacktrace --no-configuration-cache -PcrossArm64=true \
:skainet-backends:skainet-backend-native-cpu:buildNativeKernelsArm64
- name: Upload K/N static archives (Linux only)
if: matrix.arch_label == 'linux-x86_64'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: native-static-linux
path: |
skainet-backends/skainet-backend-native-cpu/build/native/cmake-build/libskainet_kernels.a
skainet-backends/skainet-backend-native-cpu/build/native/cmake-build-arm64/libskainet_kernels.a
if-no-files-found: error
retention-days: 14
# K/N klib embedding for the Apple targets (#959, iOS kernel track of
# #920): the three Mach-O static archives are built on the mac leg with
# the platform SDKs and injected into the publish job, mirroring the
# linux pair above. The `nm | grep sdot` check guards against clang
# silently ignoring an unknown target-feature string in the #958
# dispatch attribute (that failure mode is a warning, not an error).
- name: Build Apple K/N static archives (macOS only)
if: matrix.arch_label == 'macos-arm64'
env:
GRADLE_OPTS: -Dorg.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8
run: |
./gradlew --no-daemon --stacktrace --no-configuration-cache \
:skainet-backends:skainet-backend-native-cpu:buildNativeKernelsIosArm64 \
:skainet-backends:skainet-backend-native-cpu:buildNativeKernelsIosSimulatorArm64 \
:skainet-backends:skainet-backend-native-cpu:buildNativeKernelsMacosArm64
BASE=skainet-backends/skainet-backend-native-cpu/build/native
for d in cmake-build-ios-arm64 cmake-build-ios-sim-arm64 cmake-build-macos-arm64; do
nm "$BASE/$d/libskainet_kernels.a" | grep -q . || { echo "empty archive: $d" >&2; exit 1; }
objdump -d "$BASE/$d/libskainet_kernels.a" | grep -qw sdot \
|| { echo "no sdot in $d — dotprod dispatch body missing (#958)" >&2; exit 1; }
done
- name: Upload Apple K/N static archives (macOS only)
if: matrix.arch_label == 'macos-arm64'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: native-static-apple
path: |
skainet-backends/skainet-backend-native-cpu/build/native/cmake-build-ios-arm64/libskainet_kernels.a
skainet-backends/skainet-backend-native-cpu/build/native/cmake-build-ios-sim-arm64/libskainet_kernels.a
skainet-backends/skainet-backend-native-cpu/build/native/cmake-build-macos-arm64/libskainet_kernels.a
if-no-files-found: error
retention-days: 14
publish:
name: Release build and publish
needs: build-native
runs-on: macOS-latest
permissions:
contents: read
steps:
- name: Check out code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up JDK 25
uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c # v6.0.0
with:
distribution: 'zulu'
java-version: 25
# `./gradlew publish` now includes skainet-backend-jni-cpu (an Android
# library whose AAR carries NDK-built .so's). The publish runner therefore
# needs the Android SDK + a pinned NDK; without it the AAR's native build
# fails and the release ships no JNI artifact. The NDK version must match
# gradle/libs.versions.toml `android-ndk`.
- name: Set up Android SDK
uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
- name: Install pinned NDK
run: |
NDK_VERSION="$(grep -E '^android-ndk[[:space:]]*=' gradle/libs.versions.toml | sed -E 's/.*"([^"]+)".*/\1/')"
echo "Installing NDK ${NDK_VERSION}"
yes | sdkmanager "ndk;${NDK_VERSION}" >/dev/null
- name: Validate signing configuration
run: |
if ! grep -Eq '^[[:space:]]*signAllPublications[[:space:]]*=[[:space:]]*true[[:space:]]*$' gradle.properties; then
echo "signAllPublications must be set to true in gradle.properties to publish." >&2
echo "Current setting:" >&2
grep -n 'signAllPublications' gradle.properties || echo "No signAllPublications property found" >&2
exit 1
fi
- name: Download cross-arch native artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: native-artifacts
# All artifacts named `native-*` from the build-native matrix.
pattern: native-*
merge-multiple: false
- name: Stage cross-arch native libs into module resources
run: |
set -euo pipefail
DEST="skainet-backends/skainet-backend-native-cpu/build/native/resources/native"
for arch in linux-x86_64 macos-arm64 windows-x86_64; do
src_dir="native-artifacts/native-${arch}"
if [ ! -d "$src_dir" ]; then
echo "Missing native artifact for ${arch}" >&2
exit 1
fi
mkdir -p "${DEST}/${arch}"
cp -v "${src_dir}"/* "${DEST}/${arch}/"
done
echo "--- Staged tree ---"
find "$DEST" -type f
# K/N klib embedding (#941): resolve the linux ELF static archive dirs
# from the ubuntu leg's artifact and hand them to Gradle, so the
# linuxX64/linuxArm64 klibs embed real machine code even though the
# publish host is macOS. Fail loudly if the archives are missing —
# publishing bindings-only klibs is the bug this step exists to prevent.
- name: Resolve K/N static archive paths
run: |
set -euo pipefail
BASE="$PWD/native-artifacts/native-static-linux"
X64_DIR="$BASE/cmake-build"
ARM64_DIR="$BASE/cmake-build-arm64"
test -f "$X64_DIR/libskainet_kernels.a" || { echo "Missing linux-x64 static archive" >&2; exit 1; }
test -f "$ARM64_DIR/libskainet_kernels.a" || { echo "Missing linux-arm64 static archive" >&2; exit 1; }
echo "SKAINET_KERNELS_X64_DIR=$X64_DIR" >> "$GITHUB_ENV"
echo "SKAINET_KERNELS_ARM64_DIR=$ARM64_DIR" >> "$GITHUB_ENV"
# Apple archives (#959): same verified-artifact-or-fail contract.
# Injection also suppresses a redundant local rebuild on this macOS
# host (injected dirs skip the cinterop -> CMake task dependency).
APPLE="$PWD/native-artifacts/native-static-apple"
IOS_DIR="$APPLE/cmake-build-ios-arm64"
IOS_SIM_DIR="$APPLE/cmake-build-ios-sim-arm64"
MACOS_DIR="$APPLE/cmake-build-macos-arm64"
test -f "$IOS_DIR/libskainet_kernels.a" || { echo "Missing ios-arm64 static archive" >&2; exit 1; }
test -f "$IOS_SIM_DIR/libskainet_kernels.a" || { echo "Missing ios-sim-arm64 static archive" >&2; exit 1; }
test -f "$MACOS_DIR/libskainet_kernels.a" || { echo "Missing macos-arm64 static archive" >&2; exit 1; }
echo "SKAINET_KERNELS_IOS_DIR=$IOS_DIR" >> "$GITHUB_ENV"
echo "SKAINET_KERNELS_IOS_SIM_DIR=$IOS_SIM_DIR" >> "$GITHUB_ENV"
echo "SKAINET_KERNELS_MACOS_DIR=$MACOS_DIR" >> "$GITHUB_ENV"
- name: Publish to MavenCentral
run: |
./gradlew publish --no-configuration-cache --stacktrace \
-PskainetKernelsX64Dir="$SKAINET_KERNELS_X64_DIR" \
-PskainetKernelsArm64Dir="$SKAINET_KERNELS_ARM64_DIR" \
-PskainetKernelsIosArm64Dir="$SKAINET_KERNELS_IOS_DIR" \
-PskainetKernelsIosSimulatorArm64Dir="$SKAINET_KERNELS_IOS_SIM_DIR" \
-PskainetKernelsMacosArm64Dir="$SKAINET_KERNELS_MACOS_DIR"
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_PRIVATE_KEY }}
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }}