fix(backend): embed the kernel static archive into published K/N klibs (#941) - #942
Merged
Merged
Conversation
The static archive libskainet_kernels.a was attached to the K/N targets
via binaries.all { linkerOpts(...) }, which applies only to this
project's own binaries. Published -linuxx64/-linuxarm64 klibs therefore
carried cinterop bindings but no machine code: any downstream K/N
consumer failed to link with unresolved skainet_* symbols. Nobody hit
it because no external K/N consumer exists yet — the #920 mobile-kernel
work makes this the foundation everything else stands on.
The archive is now embedded into the cinterop klib via
-staticLibrary/-libraryPath, passed per target from Gradle (paths are
machine-specific and don't belong in the .def). Embedding is gated on a
correct-architecture ELF archive being available:
- linuxX64: Linux host CMake build, or injected -PskainetKernelsX64Dir
- linuxArm64: -PcrossArm64 cross build, or -PskainetKernelsArm64Dir
The injection properties exist for the release workflow: the publish
host is macOS, whose CMake build emits Mach-O that must not be embedded
into linux klibs. publish.yml's ubuntu leg now also cross-builds
(gcc-aarch64-linux-gnu) and uploads both linux static archives, and the
publish job resolves them and passes the properties — failing loudly if
either is missing, since bindings-only klibs are the bug this prevents.
When embedding is active the old linkerOpts wiring is dropped, so the
in-repo K/N test binaries link purely from the embedded klib code —
every test run now exercises exactly the consumer-link scenario.
Bindings-only builds keep linkerOpts for project-local binaries and the
cinterop task warns loudly instead of today's silence. Cinterop tasks
gained dependencies on the CMake build tasks (the archive must exist at
cinterop time, not just link time).
Verified on a Linux host:
- linuxX64Test green with linkerOpts removed (links from embedded klib)
- linuxArm64Test under qemu-aarch64 with -PcrossArm64: 23/23 green,
archive embedded at default/targets/linux_arm64/included/
- publishLinuxX64PublicationToMavenLocal: the published
-cinterop-skainetKernels.klib contains
default/targets/linux_x64/included/libskainet_kernels.a
- jvmTest green (FFM/resources path untouched)
Closes #941
Refs #920
aharakal
approved these changes
Aug 10, 2026
This was referenced Aug 10, 2026
Merged
michalharakal
added a commit
to MacOS/SKaiNET
that referenced
this pull request
Aug 11, 2026
Bump VERSION_NAME 0.38.0 -> 0.39.0 and update all version-carrying docs: - CHANGELOG: consolidate [Unreleased] under [0.39.0] with a headline summary (includes the SKaiNET-developers#947 AAR-publishing CI entry, now merged to develop). - README: BOM snippet -> 0.39.0, What's New in 0.39.0, Contributors (0.39.0). - docs/antora.yml: skainet_version attribute 0.38.0 -> 0.39.0 (used in the docs' dependency snippets). - kernel-support-matrix.adoc: regenerated via generateKernelMatrix — the Android column now shows native-jni for Q8_0/Q4_0/Q4_K/Q5_K/Q6_K (the new JNI backend), replacing panama-vector; version stamp -> 0.39.0. 0.39.0 headline: on-device AI on Android becomes real — the skainet-backend-jni-cpu JNI NEON backend (~24 tok/s SmolLM2-135M Q8_0 on a Pixel 8a vs ~3.8 scalar), plus Android streaming GGUF loads (SKaiNET-developers#922), linkable K/N kernel klibs (SKaiNET-developers#942), the Q4_0 NEON kernel (SKaiNET-developers#939), GGUF loader fail-fast (SKaiNET-developers#919), and a tensor-storage correctness pass (SKaiNET-developers#927-SKaiNET-developers#931). Local prep only — not pushed/tagged. Cut off develop after SKaiNET-developers#947 merged, so the branch already carries the AAR-publishing workflow + pinned NDK.
michalharakal
added a commit
that referenced
this pull request
Aug 11, 2026
…ed kernel archives (#959) iosArm64 + iosSimulatorArm64 + macosArm64 join the module through the existing wireSkainetKernels cinterop/embedding seam (#941/#942). Three Apple CMake lanes (macOS host only; CMake first-class iOS support, no toolchain file) produce the Mach-O static archives — device: iphoneos SDK, min iOS 12.0; simulator: iphonesimulator SDK, min 14.0; macOS: arm64, min 11.0, static-only. No -march is passed: the #958 runtime FEAT_DotProd dispatch serves A12 through M-series from one archive. Archive-dir precedence mirrors the Linux pair: injected -PskainetKernelsIosArm64Dir / -PskainetKernelsIosSimulatorArm64Dir / -PskainetKernelsMacosArm64Dir > macOS-host heuristic > bindings-only with a loud cinterop warning. The shared nativeTest parity suites gain iosSimulatorArm64Test / macosArm64Test on macOS hosts; the multiarch macos-14 PR lane runs both. On non-macOS hosts the whole Apple task family is disabled — module build + root assemble verified green on Linux with the targets declared. Refs #920
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Full analysis in #941 — flagged as the highest-risk item in #920's iOS track, and a latent bug for today's linux artifacts.
The bug
libskainet_kernels.awas attached viabinaries.all { linkerOpts(...) }, which applies only to this project's own binaries. Published-linuxx64/-linuxarm64klibs carried cinterop bindings but no machine code — any downstream K/N consumer fails to link with unresolvedskainet_*symbols. Unhit so far only because no external K/N consumer exists yet.The fix
-staticLibrary/-libraryPathpassed per target from Gradle; paths are machine-specific so they don't belong in the.def).-PskainetKernelsX64Dir); linuxArm64 under-PcrossArm64(or-PskainetKernelsArm64Dir). A macOS host's Mach-O archives are never embedded into linux klibs — those builds keep the old project-local linking and the cinterop task warns loudly that the klib is bindings-only, replacing today's silence.publish.yml: the ubuntu leg additionally cross-builds (gcc-aarch64-linux-gnuvia apt) and uploads both linux ELF archives; the macOS publish job resolves them and passes the injection properties — failing loudly if either is missing.Verified (Linux host)
linuxX64Testgreen withlinkerOptsremoved — the test binary got its machine code from the kliblinuxArm64Test -PcrossArm64=trueunder qemu-aarch64: 23/23 green; archive present atdefault/targets/linux_arm64/included/publishLinuxX64PublicationToMavenLocal: the published-cinterop-skainetKernels.klibcontainsdefault/targets/linux_x64/included/libskainet_kernels.a(39.8 KB) — the artifact consumers resolve now carries the codejvmTestgreen (FFM/resources path untouched)Needs a maintainer eye: the
publish.ymlchanges can only be fully validated by a real release run (or a tag on a fork). The Gradle-side mechanics are fully verified locally.This is the prerequisite for publishing usable
iosArm64klibs in #920's Apple track — the same embedding path will carry the iOS archives.Closes #941
Refs #920