diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6ae69a01cd3..e4007ba8422 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -869,11 +869,41 @@ jobs:
exit 1
}
+ # NativeAOT-LLVM smoketest runs on Windows because runtime.linux-x64.Microsoft.DotNet.ILCompiler.LLVM
+ # does not have 8.0.0 versions available on the dotnet-experimental NuGet feed.
+ csharp-aot-smoketest:
+ needs: [lints]
+ runs-on: windows-latest
+ timeout-minutes: 15
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Setup dotnet
+ uses: actions/setup-dotnet@v3
+ with:
+ global-json-file: global.json
+
+ - name: Install emscripten (Windows)
+ shell: pwsh
+ run: |
+ git clone https://github.com/emscripten-core/emsdk.git $env:USERPROFILE\emsdk
+ cd $env:USERPROFILE\emsdk
+ .\emsdk install 4.0.21
+ .\emsdk activate 4.0.21
+
- name: Smoketest C# AOT build (NativeAOT-LLVM)
+ shell: pwsh
run: |
- cd modules/sdk-test-cs
- EXPERIMENTAL_WASM_AOT=1 dotnet publish -c Release
- test -f bin/Release/net8.0/wasi-wasm/publish/StdbModule.wasm
+ $env:EXPERIMENTAL_WASM_AOT = "1"
+ if (Test-Path "$env:USERPROFILE\emsdk\emsdk_env.ps1") {
+ & "$env:USERPROFILE\emsdk\emsdk_env.ps1" | Out-Null
+ }
+ dotnet publish -c Release modules/sdk-test-cs
+ if (-not (Test-Path "modules/sdk-test-cs/bin/Release/net8.0/wasi-wasm/publish/StdbModule.wasm")) {
+ Write-Error "StdbModule.wasm not found"
+ exit 1
+ }
internal-tests:
name: Internal Tests
diff --git a/crates/bindings-csharp/NATIVEAOT-LLVM.md b/crates/bindings-csharp/NATIVEAOT-LLVM.md
new file mode 100644
index 00000000000..362289af8b4
--- /dev/null
+++ b/crates/bindings-csharp/NATIVEAOT-LLVM.md
@@ -0,0 +1,124 @@
+# Converting a SpacetimeDB 2.0.x project to use NativeAOT-LLVM
+
+This guide provides instructions on taking an existing C# module that targets the public-released SpacetimeDB CLI, and guides you through the necessary steps to enable `NativeAOT-LLVM` use.
+
+## Overview
+In order to use `NativeAOT-LLVM` on a C# module, we'll need to set the `EXPERIMENTAL_WASM_AOT` environment variable to `1` which SpacetimeDB will check during publishing of a module.
+For the module to work, we'll also need the `NuGet.Config` and `.csproj` files with the required package sources and references.
+
+### Prerequisites:
+- **.NET SDK 8.x** (same version used by SpacetimeDB)
+- **Emscripten SDK (EMSDK)** installed (must contain `upstream/emscripten/emcc.bat`)
+- **(Optional) Binaryen (wasm-opt)** installed and on `PATH` (recommended: `version_116`)
+
+## Steps
+
+1. **Install EMSDK**
+ - Download and extract the `https://github.com/emscripten-core/emsdk` release.
+ - Example path: `D:\Tools\emsdk`
+
+2. **Set environment variables**
+
+ ```powershell
+ $env:EXPERIMENTAL_WASM_AOT=1
+ $env:EMSDK="D:\Tools\emsdk"
+ ```
+
+3. **Ensure NuGet feed is configured**
+ NativeAOT-LLVM packages currently come from **dotnet-experimental**:
+ - Add the `dotnet-experimental` feed to a project-local `NuGet.Config`
+ ```xml
+
+ ```
+ This should be a `NuGet.Config` placed in the root directory of your module folder (next to the `.csproj`). You can simply add the above line to the `packageSources` of your existing file, or if you need to create a minimal one, you can use:
+
+ ```xml
+
+
+
+
+
+
+
+
+ ```
+
+4. **Ensure NativeAOT emits a `.wasm` output**
+ - For LLVM AOT builds, the CLI currently accepts `dotnet.wasm` under `bin/Release/net8.0/wasi-wasm/publish/`.
+ - In the module `.csproj`, ensure the AOT package references include:
+
+ ```xml
+
+
+
+
+
+ ```
+
+ The contents of your `.csproj` should look something like this:
+
+ ```xml
+
+
+ net8.0
+ wasi-wasm
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+ ```
+
+ - **NU1504 warning**: Because the runtime targets also add these LLVM packages, you may see a duplicate PackageReference warning. It is non-blocking.
+
+5. **(Optional) Install wasm-opt (Binaryen)**
+ This step is optional, but provides performance improvements, and therefore is recommended.
+ - Download Binaryen `https://github.com/WebAssembly/binaryen/releases/tag/version_116` for Windows and extract it, e.g. `D:\Tools\binaryen`.
+ - Add `D:\Tools\binaryen\bin` to `PATH`.
+ - Verify:
+
+ ```powershell
+ wasm-opt --version
+ ```
+
+6. **Publish module**
+ - Use the SpacetimeDB CLI to publish from the module directory.
+ - With `EXPERIMENTAL_WASM_AOT=1`, publish should attempt LLVM AOT.
+ - Ensure the local server is running if publishing to `local`.
+
+## Troubleshooting
+
+### Package source mapping enabled
+If you have **package source mapping** enabled in `NuGet.Config`, you must add mappings for the LLVM packages or restores will fail.
+Place the following in `NuGet.Config` inside the `configuration` section:
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### wasi-experimental workload install fails
+If the CLI cannot install the `wasi-experimental` workload automatically, install it manually:
+
+```powershell
+dotnet workload install wasi-experimental
+```
diff --git a/crates/bindings-csharp/Runtime/Runtime.csproj b/crates/bindings-csharp/Runtime/Runtime.csproj
index 1e5e0f8531a..12db5ab4150 100644
--- a/crates/bindings-csharp/Runtime/Runtime.csproj
+++ b/crates/bindings-csharp/Runtime/Runtime.csproj
@@ -12,6 +12,7 @@
true
SpacetimeDB
true
+ https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json;$(RestoreAdditionalProjectSources)
@@ -25,6 +26,13 @@
+
+
+
+
+
+
+
diff --git a/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets b/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets
index aa412113b31..5f183e0e040 100644
--- a/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets
+++ b/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets
@@ -1,5 +1,9 @@
+
+
@@ -42,10 +46,6 @@
-
-
-
-
diff --git a/modules/sdk-test-cs/sdk-test-cs.csproj b/modules/sdk-test-cs/sdk-test-cs.csproj
index d4caede5ffa..09cf1192bb7 100644
--- a/modules/sdk-test-cs/sdk-test-cs.csproj
+++ b/modules/sdk-test-cs/sdk-test-cs.csproj
@@ -9,5 +9,9 @@
-
+
+
+
+
+
diff --git a/sdks/csharp/tools~/write-nuget-config.sh b/sdks/csharp/tools~/write-nuget-config.sh
index 9997cd219ff..69286284ad8 100755
--- a/sdks/csharp/tools~/write-nuget-config.sh
+++ b/sdks/csharp/tools~/write-nuget-config.sh
@@ -15,6 +15,8 @@ cat >NuGet.Config <
+
+
@@ -30,6 +32,11 @@ cat >NuGet.Config <
+
+
+
+
+
@@ -43,6 +50,8 @@ cat >"${SPACETIMEDB_REPO_PATH}/NuGet.Config" <
+
+
@@ -58,6 +67,11 @@ cat >"${SPACETIMEDB_REPO_PATH}/NuGet.Config" <
+
+
+
+
+