Skip to content

feat: Native AOT support - #11

Merged
unsafePtr merged 3 commits into
masterfrom
feat/nativeaot
Aug 19, 2026
Merged

feat: Native AOT support#11
unsafePtr merged 3 commits into
masterfrom
feat/nativeaot

Conversation

@unsafePtr

@unsafePtr unsafePtr commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Adds Native AOT support, and the CI to keep it honest.

Native AOT

PublishAot is opt-in per publish, so ordinary builds stay on the JIT. aot-tests.yml publishes the suite natively for linux-x64 (default baseline and x86-64-v3), linux-arm64, osx-arm64 and win-x64, asserts the library emits no trim/AOT warnings, and runs the binary.

The per-baseline legs aren't redundant. ILC resolves Vector256/Vector128.IsHardwareAccelerated at build time against an instruction-set baseline rather than the live CPU, so the default x64 baseline compiles the Vector128 kernel even on AVX2 hardware. The x86-64-v3 legs guarantee AVX2, so between them the matrix compiles both. The scalar fallback stays JIT-only, since SSE2 and AdvSimd are architectural baselines IlcInstructionSet cannot drop — which is why VectorInstructionSetTests skips itself in a native run.

xunit packaging

Running under AOT needs xunit v3 4.0.0 and source-generated discovery; before that the runner resolved the test assembly through Assembly.Location, which is empty in a native image.

The .aot package is now selected only when PublishAot=true. It also pulls xunit.v3.assert.aot, whose reflection-free formatter renders every object as Box { ... } and obsoletes Assert.Equivalent — a cost that landed on ordinary JIT runs, where the failure message is the whole point.

Swapping the package opens a silent gap, since a test the generator cannot see yields no test rather than an error. aot-tests.yml now compares the native and JIT test counts on the linux-x64 leg.

CI coverage

tests.yml is new: the JIT suite on linux-x64, linux-arm64, win-x64 and osx-arm64, every push and PR, no path filter. Previously the only JIT run lived in publish-nuget.yml, filtered to src/Base58Encoding/** and pinned to an arm64 runner, so a test-only change ran nothing and every x64 execution in CI came out of ILC. That mattered most for VectorInstructionSetTests, which drives its coverage through DOTNET_EnableAVX2 and DOTNET_EnableHWIntrinsic: ILC bakes past both and arm64 ignores the first, so the Vector128 and scalar fallbacks never actually ran anywhere.

publish-nuget.yml is narrowed to v*.*.* tags and workflow_dispatch, keeping a test step scoped to the publishing path — tests.yml never runs on a tag, because a branches: filter does not match refs/tags/*.

Also

SimpleBase 5.6.2 → 5.6.4, lifting the pin from 32613b3.

Verification

JIT reports 141 tests on each of 4 platforms, the native binary reports 141 on each of 5, and the parity step prints native discovered 141, JIT discovered 141. The counts differ only in Skipped (1 vs 3 — the two VectorInstructionSetTests cases that skip natively).

@unsafePtr
unsafePtr merged commit 2f662f4 into master Aug 19, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant