Commit 484f3b5
Add .NET 10 support via NativeAOT-LLVM along side .NET 8 support (#4915)
# Description of changes
Builds on #4741 to clean up and refine the NativeAOT-LLVM integration.
The major changes:
- **Standardized the repo on .NET 10 SDK** (`global.json` → `10.0.100`).
The team is migrating to .NET 10 ahead of .NET 8 EOL. End users are
unaffected as their SDK version is controlled by their own `global.json`
emitted by `spacetime init`.
- **Multi-target NuGet packages** instead of conditional single-target:
- `SpacetimeDB.Runtime` now unconditionally targets `net8.0;net10.0`
- `SpacetimeDB.BSATN.Runtime` now unconditionally targets
`netstandard2.1;net8.0;net10.0`
- NuGet packages ship both TFMs in a single `.nupkg`. No
`EXPERIMENTAL_WASM_AOT` env var needed at pack time
- `EXPERIMENTAL_WASM_AOT` define constant is set automatically when
`TargetFramework == net10.0`
- `ILCompiler.LLVM` package references conditioned on `TargetFramework
== net10.0` (not env var)
- **Centralized NativeAOT-LLVM build logic** in
`SpacetimeDB.Runtime.props` and `SpacetimeDB.Runtime.targets`:
- Moved `PublishTrimmed`, `SelfContained`, `WasmEnableThreads` into
`.props` (previously duplicated across 4+ `.csproj` files)
- Moved the `.wit`-stripping `UseWasiRuntimeOverlayWithoutComponentWit`
target into `.targets` (was duplicated in every server `.csproj`)
- Added `IlcLlvmTarget=wasm32-unknown-wasip1` override after
ILCompiler.LLVM.targets import (previously passed as `/p:` arg)
- Added `_InitializeWasiSdk` to `ObtainWasiSdk` BeforeTargets for .NET
10 compatibility
- Consumer `.csproj` files no longer need any AOT boilerplate
- **Refactored `csharp.rs` build logic** to support three build paths
via `CsharpBuildPath` enum:
- `Net8Jit` : stable .NET 8 path using `wasi-experimental` workload
(Mono WASM)
- `Net8Aot` : .NET 8 NativeAOT-LLVM (opt-in via `--native-aot` or
`EXPERIMENTAL_WASM_AOT=1`)
- `Net10Aot` : .NET 10 NativeAOT-LLVM (auto-detected when .NET 10 SDK is
active)
- Auto-detects .NET SDK version from `dotnet --version` (respects
`global.json`)
- Automatically sets `EXPERIMENTAL_WASM_AOT=1` for AOT paths so MSBuild
conditionals activate
- Unified `dotnet publish` command for all paths. Build-specific config
handled by props/targets
- Removed redundant `/p:IlcLlvmTarget` and `/p:WasmEnableThreads` CLI
args (now in `.targets`)
- **Refactored `init.rs`** for .NET version-aware scaffolding:
- Added `--dotnet-version` CLI arg to explicitly select .NET 8 or 10
- Added `resolve_dotnet_major()` which auto-detects or prompts
interactively when multiple SDKs are installed
- .NET 10 auto-enables NativeAOT-LLVM (`--native-aot` not required)
- .NET 10 template emits `<TargetFramework>net10.0</TargetFramework>`
directly (no conditional)
- .NET 8 AOT template adds `ILCompiler.LLVM 8.0.0-*` package refs gated
on `EXPERIMENTAL_WASM_AOT=1`
- Emits correct `global.json` per SDK version (`8.0.100` or `10.0.100`)
- **Added `_initialize` call in `wasmtime_module.rs`**: NativeAOT-LLVM
modules are WASI reactors that export `_initialize` to bootstrap the
native runtime. This is called before preinit functions. Traditional
.NET 8 WASI modules export `_start` instead and are unaffected.
- **Updated `FFI.cs` `WasmImportLinkageAttribute` guard** to `#if
EXPERIMENTAL_WASM_AOT && NET10_0_OR_GREATER`, ensuring the real
attribute is only used when both the AOT flag and .NET 10+ TFM are
active. The dummy shim is used for all other builds.
- **Updated `csharp_aot_module.rs` smoketest**:
- Auto-detects .NET SDK version and adjusts TFM accordingly
- .NET 8 AOT: Windows-only (ILCompiler.LLVM 8.0.0-* not published for
Linux)
- .NET 10 AOT: Windows and Linux
- Removed emscripten dependency (NativeAOT-LLVM uses WASI SDK, not
emscripten)
- **Updated CLI reference docs** to reflect `--native-aot` behavior
change (not needed for .NET 10) and new `--dotnet-version` arg.
This PR addresses several issues from #4741 review:
1. **NativeAOT-LLVM build logic was duplicated** in every server
`.csproj` (4+ files had identical `PropertyGroup` and `Target` blocks).
This is now centralized in the shipped `.props`/`.targets`.
2. **NuGet packages only shipped a single TFM**. The env var controlled
which TFM was built, meaning you needed `EXPERIMENTAL_WASM_AOT=1` at
pack time to get the `net10.0` DLL. Now both TFMs are always included.
3. **`spacetime init` emitted unnecessary conditional wrappers** in the
generated `.csproj` for .NET 10 projects. Since the project is
definitively targeting .NET 10, the TFM should be unconditional.
4. **`spacetime publish` passed MSBuild properties via `/p:` args** that
are now handled by centralized `.targets`, simplifying the CLI code.
# API and ABI breaking changes
- `global.json` now requires .NET 10 SDK for repo development. All
developers and CI agents need .NET SDK 10.0+ installed.
- End user module projects are **not affected**. They continue to use
whichever SDK their local `global.json` specifies.
- .NET 8 JIT and .NET 8 AOT paths remain functional for end users until
.NET 8 EOL.
# Expected complexity level and risk
2 - The core risk is the same as #4741: future changes in the upstream
NativeAOT-LLVM/WASI pipeline. Centralizing the build logic in
`.props`/`.targets` reduces the surface area for breaking changes (one
place to update vs. N consumer projects). The `.wit`-stripping
workaround remains necessary until
[dotnet/runtimelab#3144](dotnet/runtimelab#3144)
is resolved.
# Testing
- Ran C# module publish + client connection tests for all three build
paths:
- .NET 8 JIT (`spacetime publish` without `--native-aot`)
- .NET 8 AOT (`spacetime publish` with `EXPERIMENTAL_WASM_AOT=1` and
.NET 8 SDK)
- .NET 10 AOT (`spacetime publish` with .NET 10 SDK, auto-detected)
- Verified `spacetime init --lang csharp` generates correct project
structure for both .NET 8 and .NET 10
- Verified `spacetime init --lang csharp --dotnet-version 10` emits
`net10.0` TFM and `10.0.100` in `global.json`
- Verified C# regression tests complete successfully when ran under .NET
8 JIT, .NET 8 AOT, .NET 10 AOT
- This required making local customizations to the repo versions of the
regression tests, in order to conform to the configuration output by
`spacetime init`, but the tests themselves remained identical.
- Verified NuGet packages contain both `lib/net8.0/` and `lib/net10.0/`
DLLs
- Updated smoketest `test_build_csharp_module_aot` to work with both
.NET 8 and .NET 10 SDK
---------
Signed-off-by: Ryan <r.ekhoff@clockworklabs.io>
Co-authored-by: Jason Larabie <jason@clockworklabs.io>
Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com>
Co-authored-by: Lisandro Crespo <lisandroct@gmail.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>1 parent 3c87e69 commit 484f3b5
79 files changed
Lines changed: 2525 additions & 622 deletions
File tree
- .github/workflows
- crates
- bindings-csharp
- BSATN.Codegen
- BSATN.Runtime.Tests
- BSATN.Runtime
- Codegen.Tests
- fixtures
- diag
- snapshots
- explicitnames
- snapshots
- server
- snapshots
- Codegen
- Runtime.Tests
- Runtime
- Internal
- build
- cli/src
- subcommands
- tasks
- core/src/host/wasmtime
- guard/src
- smoketests
- src
- tests/smoketests
- testing/src
- demo/Blackholio
- client-unity/Assets/Scripts/autogen
- server-csharp
- docs
- docs
- 00100-intro
- 00200-quickstarts
- 00300-tutorials
- 00300-resources/00200-reference/00100-cli-reference
- test-csharp-snippets
- modules
- benchmarks-cs
- module-test-cs
- sdk-test-connect-disconnect-cs
- sdk-test-cs
- sdk-test-procedural-view-pk-cs
- sdk-test-procedure-cs
- sdk-test-view-pk-cs
- sdks/csharp
- examples~/regression-tests
- client
- procedure-client
- republishing
- client
- server-initial
- server-republish
- server
- tools~
- unity-meta-skeleton~
- spacetimedb.bsatn.runtime/lib
- net10.0
- spacetimedb.runtime/lib
- templates
- basic-cs/spacetimedb
- chat-console-cs
- module_bindings
- spacetimedb
- tools/ci/src
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
184 | 184 | | |
185 | 185 | | |
186 | 186 | | |
187 | | - | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
188 | 194 | | |
189 | 195 | | |
190 | 196 | | |
| |||
1075 | 1081 | | |
1076 | 1082 | | |
1077 | 1083 | | |
| 1084 | + | |
| 1085 | + | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
| 1089 | + | |
| 1090 | + | |
| 1091 | + | |
| 1092 | + | |
| 1093 | + | |
1078 | 1094 | | |
1079 | 1095 | | |
1080 | 1096 | | |
| |||
1146 | 1162 | | |
1147 | 1163 | | |
1148 | 1164 | | |
1149 | | - | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
1150 | 1168 | | |
1151 | | - | |
| 1169 | + | |
1152 | 1170 | | |
1153 | 1171 | | |
1154 | 1172 | | |
| |||
1170 | 1188 | | |
1171 | 1189 | | |
1172 | 1190 | | |
| 1191 | + | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + | |
| 1195 | + | |
| 1196 | + | |
| 1197 | + | |
| 1198 | + | |
| 1199 | + | |
| 1200 | + | |
| 1201 | + | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
1173 | 1206 | | |
1174 | 1207 | | |
1175 | 1208 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
164 | 164 | | |
165 | 165 | | |
166 | 166 | | |
167 | | - | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
168 | 171 | | |
169 | 172 | | |
170 | 173 | | |
171 | | - | |
172 | | - | |
173 | | - | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
174 | 177 | | |
175 | 178 | | |
176 | 179 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
563 | 563 | | |
564 | 564 | | |
565 | 565 | | |
566 | | - | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
567 | 573 | | |
568 | 574 | | |
569 | 575 | | |
| |||
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| |||
Lines changed: 17 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | 21 | | |
26 | 22 | | |
27 | 23 | | |
28 | 24 | | |
29 | 25 | | |
30 | 26 | | |
31 | 27 | | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
32 | 44 | | |
33 | 45 | | |
34 | 46 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
| 29 | + | |
30 | 30 | | |
31 | 31 | | |
32 | | - | |
| 32 | + | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
37 | | - | |
| 38 | + | |
| 39 | + | |
38 | 40 | | |
39 | 41 | | |
40 | | - | |
41 | | - | |
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
56 | | - | |
| 56 | + | |
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
65 | | - | |
66 | | - | |
| 65 | + | |
| 66 | + | |
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
74 | | - | |
| 74 | + | |
75 | 75 | | |
76 | 76 | | |
77 | | - | |
| 77 | + | |
78 | 78 | | |
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | | - | |
| 83 | + | |
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
90 | | - | |
91 | | - | |
| 90 | + | |
| 91 | + | |
92 | 92 | | |
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
96 | 96 | | |
97 | | - | |
| 97 | + | |
98 | 98 | | |
99 | 99 | | |
100 | 100 | | |
| |||
241 | 241 | | |
242 | 242 | | |
243 | 243 | | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
| 244 | + | |
248 | 245 | | |
249 | 246 | | |
250 | 247 | | |
| |||
332 | 329 | | |
333 | 330 | | |
334 | 331 | | |
335 | | - | |
336 | | - | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
337 | 337 | | |
338 | 338 | | |
339 | 339 | | |
| |||
345 | 345 | | |
346 | 346 | | |
347 | 347 | | |
348 | | - | |
| 348 | + | |
349 | 349 | | |
350 | 350 | | |
351 | 351 | | |
| |||
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| |||
Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 commit comments