Add .NET 10 support via NativeAOT-LLVM along side .NET 8 support#4915
Add .NET 10 support via NativeAOT-LLVM along side .NET 8 support#4915rekhoff wants to merge 144 commits into
Conversation
1) Created exception to `check_global_json_policy` to allow for .NET 8 templates to be generated. 2) Removed .NET 10 DLLs from SDK to prevent Unity issue. 3) Updated NativeAOT smoketest test include `packageSourceMapping` in `NuGet.Config`.
…SDK` for Windows builds
- Add --dotnet-version flag to build/publish/init commands for explicit .NET version control - Fix smoketests to use local SpacetimeDB.Runtime/BSATN.Runtime packages (not public NuGet) - Fix CLI binary path detection for debug vs release builds - Add NativeAOT-LLVM output paths (native/ subdirectory) to csharp.rs - Force .NET 8 for C# templates in template tests to match template TFM
…rsion `25` from `29`
…imental` can install
|
merging in master to get some new internal tests behavior (#5520) |
| $PSNativeCommandUseErrorActionPreference = $true | ||
|
|
||
| cd modules | ||
| # the sdk-manifests on windows-latest are messed up, so we need to update them |
There was a problem hiding this comment.
why was this comment removed?
| echo "Using WASI SDK at: $WASI_SDK_PATH" | ||
|
|
||
| # Remove broken global.json symlinks before regression scripts temporarily pin | ||
| # each C# module directory to the SDK version under test. |
There was a problem hiding this comment.
wait why do these symlinks get broken?
There was a problem hiding this comment.
This got added in 044d516b3053133698592a5eb0af2381fc9ab215. I don't know if @rekhoff has any recollection.
I understand that the symlinks get broken due to the "Install .NET workloads" step above.
| if [ -f sdks/csharp/examples~/regression-tests/server/global.json ] && [ ! -L sdks/csharp/examples~/regression-tests/server/global.json ]; then | ||
| echo "Restoring symlink at server/global.json" | ||
| rm -f sdks/csharp/examples~/regression-tests/server/global.json | ||
| ln -s ../../../../../global.json sdks/csharp/examples~/regression-tests/server/global.json |
There was a problem hiding this comment.
optional nit: I wonder if a git checkout HEAD -- <file> would be cleaner?
There was a problem hiding this comment.
and/or git restore which I think is the modern version
|
|
||
| - name: Override NuGet packages | ||
| env: | ||
| EXPERIMENTAL_WASM_AOT: 1 |
There was a problem hiding this comment.
why is this the only one that needs this env var set? (we have other override nuget packages steps in this file that don't get this override)
There was a problem hiding this comment.
I think here's the only place where we're targeting both .NET 8 and .NET 10. This variable is only needed in .NET 8 AOT. .NET 10 presupposes that it's AOT.
It might be outdated and not needed anymore. I'll check it.
There was a problem hiding this comment.
For my own personal tracking of all of these changes: This was added in 2d06a3d833f319253bee772886aa28d616867a15.
| } | ||
| } | ||
|
|
||
| fn temporarily_pin_project_sdk(project_path: &Path, major: u8) -> anyhow::Result<TemporaryGlobalJson> { |
There was a problem hiding this comment.
I'm surprised to see this. Why are we overriding users' global.jsons?
bfops
left a comment
There was a problem hiding this comment.
I left comments on my code-owned files.
The init, dev, and tasks::csharp subcommand changes are large enough that I find them hard to review, so I can't say that I've been super thorough with them.
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 ownglobal.jsonemitted byspacetime init.Multi-target NuGet packages instead of conditional single-target:
SpacetimeDB.Runtimenow unconditionally targetsnet8.0;net10.0SpacetimeDB.BSATN.Runtimenow unconditionally targetsnetstandard2.1;net8.0;net10.0.nupkg. NoEXPERIMENTAL_WASM_AOTenv var needed at pack timeEXPERIMENTAL_WASM_AOTdefine constant is set automatically whenTargetFramework == net10.0ILCompiler.LLVMpackage references conditioned onTargetFramework == net10.0(not env var)Centralized NativeAOT-LLVM build logic in
SpacetimeDB.Runtime.propsandSpacetimeDB.Runtime.targets:PublishTrimmed,SelfContained,WasmEnableThreadsinto.props(previously duplicated across 4+.csprojfiles).wit-strippingUseWasiRuntimeOverlayWithoutComponentWittarget into.targets(was duplicated in every server.csproj)IlcLlvmTarget=wasm32-unknown-wasip1override after ILCompiler.LLVM.targets import (previously passed as/p:arg)_InitializeWasiSdktoObtainWasiSdkBeforeTargets for .NET 10 compatibility.csprojfiles no longer need any AOT boilerplateRefactored
csharp.rsbuild logic to support three build paths viaCsharpBuildPathenum:Net8Jit: stable .NET 8 path usingwasi-experimentalworkload (Mono WASM)Net8Aot: .NET 8 NativeAOT-LLVM (opt-in via--native-aotorEXPERIMENTAL_WASM_AOT=1)Net10Aot: .NET 10 NativeAOT-LLVM (auto-detected when .NET 10 SDK is active)dotnet --version(respectsglobal.json)EXPERIMENTAL_WASM_AOT=1for AOT paths so MSBuild conditionals activatedotnet publishcommand for all paths. Build-specific config handled by props/targets/p:IlcLlvmTargetand/p:WasmEnableThreadsCLI args (now in.targets)Refactored
init.rsfor .NET version-aware scaffolding:--dotnet-versionCLI arg to explicitly select .NET 8 or 10resolve_dotnet_major()which auto-detects or prompts interactively when multiple SDKs are installed--native-aotnot required)<TargetFramework>net10.0</TargetFramework>directly (no conditional)ILCompiler.LLVM 8.0.0-*package refs gated onEXPERIMENTAL_WASM_AOT=1global.jsonper SDK version (8.0.100or10.0.100)Added
_initializecall inwasmtime_module.rs: NativeAOT-LLVM modules are WASI reactors that export_initializeto bootstrap the native runtime. This is called before preinit functions. Traditional .NET 8 WASI modules export_startinstead and are unaffected.Updated
FFI.csWasmImportLinkageAttributeguard 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.rssmoketest:Updated CLI reference docs to reflect
--native-aotbehavior change (not needed for .NET 10) and new--dotnet-versionarg.This PR addresses several issues from #4741 review:
NativeAOT-LLVM build logic was duplicated in every server
.csproj(4+ files had identicalPropertyGroupandTargetblocks). This is now centralized in the shipped.props/.targets.NuGet packages only shipped a single TFM. The env var controlled which TFM was built, meaning you needed
EXPERIMENTAL_WASM_AOT=1at pack time to get thenet10.0DLL. Now both TFMs are always included.spacetime initemitted unnecessary conditional wrappers in the generated.csprojfor .NET 10 projects. Since the project is definitively targeting .NET 10, the TFM should be unconditional.spacetime publishpassed MSBuild properties via/p:args that are now handled by centralized.targets, simplifying the CLI code.API and ABI breaking changes
global.jsonnow requires .NET 10 SDK for repo development. All developers and CI agents need .NET SDK 10.0+ installed.global.jsonspecifies.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/.targetsreduces the surface area for breaking changes (one place to update vs. N consumer projects). The.wit-stripping workaround remains necessary until dotnet/runtimelab#3144 is resolved.Testing
spacetime publishwithout--native-aot)spacetime publishwithEXPERIMENTAL_WASM_AOT=1and .NET 8 SDK)spacetime publishwith .NET 10 SDK, auto-detected)spacetime init --lang csharpgenerates correct project structure for both .NET 8 and .NET 10spacetime init --lang csharp --dotnet-version 10emitsnet10.0TFM and10.0.100inglobal.jsonspacetime init, but the tests themselves remained identical.lib/net8.0/andlib/net10.0/DLLstest_build_csharp_module_aotto work with both .NET 8 and .NET 10 SDK