ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

SpacetimeDB C 模块使用 NativeAOT-LLVM 编译实战指南:从 .NET 8 到 .NET 10 的 WASM 原生编译完整配置

SpacetimeDB C 模块使用 NativeAOT-LLVM 编译实战指南:从 .NET 8 到 .NET 10 的 WASM 原生编译完整配置 SpacetimeDB C# 模块使用 NativeAOT-LLVM 编译实战指南从 .NET 8 到 .NET 10 的 WASM 原生编译完整配置【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB本文以 SpacetimeDB 官方文档 NATIVEAOT-LLVM.md 为核心骨架结合仓库中 CLI 与 C# Runtime 的真实源码系统讲解如何为 C# SpacetimeDB 模块启用 NativeAOT-LLVM 编译将 C# 代码直接编译为原生 WebAssemblyWASM以提升性能。读完本文你将掌握 .NET 8Windows与 .NET 10Windows/Linux两套 AOT 构建目标的完整项目配置、spacetime init/spacetime publish/spacetime.json三种激活方式、WASI SDK 自动下载机制以及常见构建故障的排查方法。[!WARNING] NativeAOT-LLVM 目前仍处于实验阶段用于生产环境前请充分评估与测试。概述C# 模块的三种构建路径SpacetimeDB 为 C# 模块提供三种构建目标区别在于 .NET 版本、目标平台与运行方式构建目标.NET 版本支持平台说明JITMono.NET 8.0Windows、Linux、macOS使用 Mono 运行时解释执行默认路径NativeAOT-LLVM.NET 8.0仅 Windows将 C# 编译为原生 WASMNativeAOT-LLVM.NET 10.0Windows、Linux将 C# 编译为原生 WASM[!NOTE] .NET 8.0 的 NativeAOT-LLVM 仅支持 Windows原因在于runtime.linux-x64.Microsoft.DotNet.ILCompiler.LLVM从未发布到 dotnet-experimental feedLinux 用户必须使用 .NET 10 才能获得 NativeAOT 支持。这一限制在 CLI 源码中有明确校验。crates/cli/src/common_args.rs中的nativeaot_unsupported_on_host函数直接编码了平台约束macOS 上任何版本都拒绝启用Linux 上仅在 .NET 10 时放行ensure_nativeaot_supported_on_host在不满足条件时会直接报错pub(crate) const NATIVEAOT_UNSUPPORTED_MESSAGE: str NativeAOT-LLVM in only supported on Windows and Linux (.NET 10).; pub(crate) fn nativeaot_unsupported_on_host(os: str, dotnet_version: Optionu8) - bool { os macos || (os linux dotnet_version Some(8)) }见 crates/cli/src/common_args.rsNativeAOT-LLVM 的构建原理从 IL 到原生 WASM理解 NativeAOT-LLVM 之前先看 SpacetimeDB 如何组织 C# 构建路径。crates/cli/src/tasks/csharp.rs中定义了CsharpBuildPath枚举清晰地划分出三条路径enum CsharpBuildPath { /// .NET 8 JIT via the wasi-experimental workload (Mono WASM). Net8Jit, /// .NET 8 NativeAOT-LLVM (opt-in via --native-aot). Net8Aot, /// .NET 10 NativeAOT-LLVM (auto-detected, only available path for .NET 10). Net10Aot, }见 crates/cli/src/tasks/csharp.rs路径选择的核心逻辑如下.NET 10无条件走 NativeAOT-LLVM即使不带--native-aot标志也如此此时 CLI 会提示 Note: --native-aot is not needed with .NET 10.NET 8 --native-aot走 .NET 8 的 ILCompiler.LLVM 包路径.NET 8 不带标志走原有wasi-experimentalworkload 的 Mono JIT 路径。关键在于EXPERIMENTAL_WASM_AOT环境变量。CLI 在构建前会设置或移除它见 crates/cli/src/tasks/csharp.rs对Net8Aot/Net10Aot必须设置EXPERIMENTAL_WASM_AOT1——因为SpacetimeDB.Runtime.targets中的 ILCompiler.LLVM 导入逻辑以该环境变量为开关未设置时dotnet只会产出托管 DLL 而不是.wasm对Net8Jit必须移除该变量——防止 CI 等环境中全局设置导致 JIT 构建被错误切到 NativeAOT 模式。从 MSBuild 侧看crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets是这套机制的落地文件其中包含几个关键设计条件导入 ILCompiler.LLVM.targets仅当EXPERIMENTAL_WASM_AOT 1且存在包时才导入.NET 10 自动检测_UseNativeAotLlvm属性在TargetFramework.StartsWith(net10.)时自动为true这就是 .NET 10 无需任何标志的原因固定 WASI 目标为 Preview 1强制IlcLlvmTarget为wasm32-unknown-wasip1并关闭IsWasiProject、WasmGenerateAppBundle。SpacetimeDB 宿主只支持 WASI Preview 1wasip1因此 targets 中还会剥离.wit文件防止 NativeAOT-LLVM 生成 WebAssembly Component Modelwasip2导出导致运行失败声明宿主导入表通过WasmImport列出spacetime_10.0~spacetime_10.5各版本模块宿主函数table_id_from_name、datastore_insert_bsatn、console_log、procedure_start_mut_tx等AOT 模式使用NativeLibrary绑定bindings.cJIT 模式改用NativeFileReference。见 crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets前置条件启用 NativeAOT-LLVM 前需要准备.NET SDK 8.0或.NET SDK 10.0WASI SDK首次 AOT 构建时自动下载可选Binaryenwasm-opt用于 WASM 优化WASI SDK自动下载机制WASI SDK 是 NativeAOT-LLVM 编译的必需工具链。它由构建流程自动下载默认存放位置如下平台下载位置Windows%USERPROFILE%\.wasi-sdk\wasi-sdk-29Linux/macOS~/.wasi-sdk/wasi-sdk-29下载与解压逻辑由SpacetimeDB.Runtime.targets中的ObtainWasiSdk目标实现见 SpacetimeDB.Runtime.targets几个值得注意的实现细节版本按目标框架选择.NET 10目标使用wasi-sdk-29而.NET 8目标使用wasi-sdk-24按架构/系统拼装下载 URL自动区分x86_64/arm64与 Windows/Linux/macOS环境变量优先如果WASI_SDK_PATH已设置且指向的bin/clangWindows 下为clang.exe存在则跳过下载直接使用跨平台解压依赖 Windows 10 与各 Linux 发行版内置的tar完成解压抑制 .NET 10 的硬编码版本检查.NET 10 的WasiApp.targets要求精确的 wasi-sdk 版本25.0这里主动覆盖该检查以支持更新的 SDK。如需覆盖默认位置可用WASI_SDK_PATH环境变量# Windows $env:WASI_SDK_PATHC:\Tools\wasi-sdk # Linux/macOS export WASI_SDK_PATH/opt/wasi-sdk构建目标一.NET 8.0 NativeAOT-LLVM仅 Windows面向希望在 Windows 上使用 .NET 8.0 SDK 获得 NativeAOT-LLVM 编译能力的用户。需求清单.NET SDK 8.0Windows 操作系统配置了 dotnet-experimental feed 的 NuGet.Config项目配置.csproj.csproj必须包含条件化的 LLVM 包引用。注意Condition$(EXPERIMENTAL_WASM_AOT) 1这一开关它保证只有在启用 AOT 时才会引入 ILCompiler 相关包Project SdkMicrosoft.NET.Sdk PropertyGroup TargetFrameworknet8.0/TargetFramework RuntimeIdentifierwasi-wasm/RuntimeIdentifier /PropertyGroup ItemGroup PackageReference IncludeSpacetimeDB.Runtime Version2.2.* / /ItemGroup !-- Required for .NET 8 AOT builds -- ItemGroup Condition$(EXPERIMENTAL_WASM_AOT) 1 PackageReference IncludeMicrosoft.DotNet.ILCompiler.LLVM Version8.0.0-* / PackageReference Includeruntime.$(NETCoreSdkPortableRuntimeIdentifier).Microsoft.DotNet.ILCompiler.LLVM Version8.0.0-* / /ItemGroup /Project其中RuntimeIdentifier固定为wasi-wasm这与 NativeAOT-LLVM 面向 WASI 目标的定位一致对应wasm32-unknown-wasip1目标三元组。NuGet.Configdotnet-experimental feedMicrosoft.DotNet.ILCompiler.LLVM属于 .NET 官方实验性软件包必须通过 dotnet-experimental 源获取。NuGet.Config需要同时配置包源与包源映射packageSourceMapping确保 ILCompiler 相关包只从实验源解析其余包仍走 nuget.org?xml version1.0 encodingutf-8? configuration packageSources clear / add keydotnet-experimental valuehttps://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json / add keynuget.org valuehttps://api.nuget.org/v3/index.json / /packageSources packageSourceMapping packageSource keydotnet-experimental package patternMicrosoft.DotNet.ILCompiler.LLVM / package patternruntime.* / /packageSource packageSource keynuget.org package pattern* / /packageSource /packageSourceMapping /configuration激活 NativeAOT-LLVM.NET 8共有三种方式启用 .NET 8 的 NativeAOT-LLVM 编译三者本质相同——最终都是设置EXPERIMENTAL_WASM_AOT环境变量——但使用体验不同。方式一init时指定--native-aotspacetime init --lang csharp --native-aot --dotnet-version 8 my-project这种方式会创建出已按方式三配置好spacetime.json的项目后续发布时始终采用 NativeAOT-LLVM体验最一致。方式二publish时指定--native-aotspacetime publish --native-aot my-database-name方式三spacetime.json配置{ module: my-module, native-aot: true }native-aot与dotnet-version都是模块级配置键由spacetime publish命令的配置合并逻辑解析见 crates/cli/src/subcommands/publish.rs。CLI 在发布时会读取配置中的native_aot布尔值并写入publish_entry的native-aot: true字段。手动dotnet build时的开关NativeAOT-LLVM 依赖EXPERIMENTAL_WASM_AOT标志。调用spacetime publish时 CLI 会内部处理该变量但如果想手动构建需要显式传递dotnet build -f net8.0 -p:EXPERIMENTAL_WASM_AOT1[!IMPORTANT] 若不设置该变量.csproj中的条件包引用不会生效产物将是普通托管 DLL 而非.wasm。另外CLI 在 .NET 8 AOT 构建前会删除缓存的project.assets.json强制重新 restore——因为此前若在未设置EXPERIMENTAL_WASM_AOT时 restore 过缓存里缺少 ILCompiler 包会导致dotnet publish悄悄回退到 Mono wasi-experimental 路径见 crates/cli/src/tasks/csharp.rs。构建目标二.NET 10.0 NativeAOT-LLVMWindows 与 Linux面向希望在 Windows或 Linux上获得 NativeAOT-LLVM 编译能力的用户。需求清单.NET SDK 10.0Windows 或 Linux 操作系统配置了 dotnet-experimental feed 的 NuGet.Config项目配置.csproj.NET 10 的项目配置更简单——无需条件包引用。ILCompiler.LLVM 依赖对net10.0是无条件的CLI 源码注释也指出 .NET 10 路径不需要删除project.assets.json强制重存见 crates/cli/src/tasks/csharp.rsProject SdkMicrosoft.NET.Sdk PropertyGroup TargetFrameworknet10.0/TargetFramework RuntimeIdentifierwasi-wasm/RuntimeIdentifier /PropertyGroup ItemGroup PackageReference IncludeSpacetimeDB.Runtime Version2.2.* / /ItemGroup /ProjectNuGet.Config 配置与 .NET 8 相同?xml version1.0 encodingutf-8? configuration packageSources clear / add keydotnet-experimental valuehttps://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json / add keynuget.org valuehttps://api.nuget.org/v3/index.json / /packageSources packageSourceMapping packageSource keydotnet-experimental package patternMicrosoft.DotNet.ILCompiler.LLVM / package patternruntime.* / /packageSource packageSource keynuget.org package pattern* / /packageSource /packageSourceMapping /configurationglobal.json按需配置如果 .NET 10 不是系统默认 SDK需要创建global.json锁定版本{ sdk: { version: 10.0.100, rollForward: latestMinor } }使用spacetime init时若指定--dotnet-version 10CLI 会自动生成该文件。构建时 CLI 会校验实际活动的 SDK 主版本与目标一致若不一致会提示创建/更新global.json见 crates/cli/src/tasks/csharp.rs。激活 NativeAOT-LLVM.NET 10.NET 10 下 NativeAOT-LLVM 是默认且唯一的构建路径无需额外标志即自动启用。也可以显式指定方式一init时指定 .NET 10推荐spacetime init --lang csharp --dotnet-version 10 my-project方式二使用--native-aot标志spacetime init --lang csharp --native-aot my-project方式三spacetime.json配置{ module: my-module, native-aot: true }[!NOTE]--dotnet-version参数只接受8或10其他值如9会被 CLI 直接拒绝并提示 Unsupported --dotnet-version。省略该参数时CLI 会按默认 10macOS 或仅装有 .NET 8 时回退到 8的策略自动探测见 crates/cli/src/common_args.rs 与 crates/cli/src/subcommands/init.rs。发布模块配置完成后照常发布即可spacetime publish my-database-nameCLI 会打印当前使用的构建路径便于确认输出Using NativeAOT-LLVM compilation (experimental)→ 正在使用 AOT 构建输出标准信息 → 正在使用 JITMono构建。发布时控制 .NET 版本如需在发布时显式指定 .NET 版本# 强制 .NET 8 构建AOT 必须配合 --native-aot spacetime publish --dotnet-version 8 --native-aot my-database-name # 强制 .NET 10 构建自动使用 AOT spacetime publish --dotnet-version 10 my-database-name故障排查问题一找不到 WASI SDK报错error : Could not find wasi-sdk. Either set $(WASI_SDK_PATH), or use workloads to get the sdk.排查步骤WASI SDK 应在首次 AOT 构建时自动下载确认~/.wasi-sdk或%USERPROFILE%\.wasi-sdk下是否有对应版本目录若自动下载失败可从 wasi-sdk 官方 GitHub Releases 手动下载对应版本.NET 8 对应 24、.NET 10 对应 29解压到任意目录设置WASI_SDK_PATH环境变量指向该目录该目录下需存在bin/clang或bin/clang.exeSpacetimeDB.Runtime.targets会据此判定 SDK 是否有效重启终端 / IDE使环境变量生效。问题二.NET 8 AOT 在 Linux 上失败报错缺少runtime.linux-x64.Microsoft.DotNet.ILCompiler.LLVM原因.NET 8 的 NativeAOT-LLVM 相关包只发布了 Windows 版本Linux 上无法获取。解决方案改用 .NET 10 进行 Linux 下的 NativeAOT 构建spacetime init --lang csharp --dotnet-version 10 my-project问题三.NET 8 AOT 遇到 JsonSerializerContext 构建失败报错NativeAOT-LLVM 抛出含义不明的错误例如EXEC : error : Object reference not set to an instance of an object. ...原因当模块定义了使用[JsonSourceGenerationOptions(PropertyNameCaseInsensitive true)]的JsonSerializerContext时.NET 8 的 NativeAOT-LLVM 工具链可能失败。最新版 .NET 8 NativeAOT-LLVM 包停留在 2023 年 10 月存在已知缺陷。解决方案按优先级优先迁移到 .NET 10NativeAOT-LLVMspacetime init --lang csharp --dotnet-version 10 my-project若必须停留在 .NET 8改用默认的 JIT 构建路径不要使用--native-aot作为兼容性 workaround从JsonSourceGenerationOptions中移除PropertyNameCaseInsensitive true改为在调用点传入大小写不敏感选项var result JsonSerializer.DeserializeT( json, new JsonSerializerOptions { PropertyNameCaseInsensitive true } );[!WARNING] 上述 workaround 可以编译并运行但并非万无一失。在裁剪后的 AOT 构建中该方案依赖反射可能会产生IL2026警告。请将其视为可能的兼容性方案而非所有模块的保证修复。问题四JIT 构建报错——缺少 wasi-experimental workload仅对 JIT 构建有效NativeAOT 不适用需要安装wasi-experimentalworkloaddotnet workload install wasi-experimentalNativeAOT-LLVM 构建不使用该 workload而是使用 WASI SDK。CLI 在 JIT 路径下会主动检查dotnet workload list输出中是否包含wasi-experimental缺失时尝试自动安装若因权限失败则给出提示见 crates/cli/src/tasks/csharp.rs。问题五Code generation failed若出现 Code generation failed for method 类错误按以下顺序检查确认NuGet.Config已包含dotnet-experimentalfeed对 .NET 8确认.csproj中存在EXPERIMENTAL_WASM_AOT条件包引用且构建时设置了EXPERIMENTAL_WASM_AOT1对 .NET 10确认TargetFramework为net10.0若 .NET 10 不是默认 SDK检查项目根目录是否存在内容正确的global.json。问题六重复的 PackageReference 警告NU1504.NET 8AOT 构建中出现 NU1504重复包引用警告属于预期行为不阻塞构建可忽略。总结NativeAOT-LLVM 为 SpacetimeDB C# 模块提供了将托管代码直接编译为原生 WASM 的路径省去了 Mono 运行时解释开销。本文覆盖的完整决策链可归纳为选 .NET 10推荐Windows 与 Linux 均支持配置最简无需条件包引用NativeAOT 默认启用且无 JsonSerializerContext 工具链缺陷选 .NET 8仅限 Windows需要--native-aot显式激活、条件包引用与EXPERIMENTAL_WASM_AOT环境变量三件套配合其余情况macOS 用户、Linux .NET 8 用户只能使用 JITMono路径CLI 会在启用 AOT 时直接报错拦截。更深入的实现细节可继续阅读仓库中的相关文件CLI 构建任务与路径选择、平台校验与参数解析、publish 子命令的配置合并、init 子命令的参数定义以及控制 MSBuild 行为的 SpacetimeDB.Runtime.targets。【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表