[WSLC] Decide whether the shipped C# NuGet enables WSLc, and document wslcsdk.dll for Rust SDK consumers
@SohamDas2021 is already working on this.
Since Sep 4, 2026.
- Dominant language
- Rust
- Stars
- 1.3k
- Forks
- 79
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 117
Description
### Description of the task
The WSLc backend loads `wslcsdk.dll` at runtime via `libloading` — there is no static link. The **mechanism** for acquiring, staging, and locating that DLL is already implemented and works for both in-proc SDKs. What is missing is a **policy decision** about what the shipped C# NuGet package contains, plus documentation for Rust SDK consumers.
> **Note:** this issue was originally filed asserting that the runtime discovery contract was undefined and that the C# build did not stage `wslcsdk.dll`. Both claims were wrong — see "What already works" below. The body has been rewritten to describe the real remaining scope.
#### What already works
**Acquisition.** When `CARGO_FEATURE_LINK_WSLCSDK` is set (Windows only), `src/backends/wslc/common/build.rs` resolves the SDK in this order:
1. `WSLC_SDK_PATH` — a directory containing `wslcsdk.dll`, or a `native/` subdirectory containing it. Intended for offline / air-gapped builds. Taken as-is; **not** hash-verified, since it is an explicit operator escape hatch.
2. The `.nupkg` pinned to `WSLC_SDK_VERSION` (currently `2.9.9`, `build.rs:30`), downloaded from the MxcDependencies Azure Artifacts feed.
3. The vendored `.nupkg` in `external/wslc-sdk/` — a transitional fallback used only if the feed download *fails*, with a `cargo:warning`.
Both `.nupkg` paths are verified against a pinned SHA-256 before extraction, and the build panics rather than emitting a binary that cannot load the DLL.
**Staging.** `build.rs:112-119` copies `wslcsdk.dll` into the cargo profile directory, beside whatever binary is being built. Because `mxc_engine/Cargo.toml:53` propagates `wslc_common/link-wslcsdk`, a downstream crate depending on `mxc-sdk` with the `wslc` feature triggers this too.
**Discovery.** `wslc_bindings.rs:92-96` resolves the DLL **module-relative**, not exe-relative — `module_path_for_address(Self::load)` then `.parent().join("wslcsdk.dll")`. Loaded inside `mxc_ffi.dll`, it resolves beside *that* DLL, which is exactly where the C# build puts it. This is why no `NativeLibraryResolver`-style probe order was needed.
**C# packaging.** With `-p:MxcWithWslc=true`, the csproj already adds the `wslc` cargo feature, builds `-p wxc_wslc_daemon`, picks `wslcsdk.dll` up from beside the `mxc_ffi` artifact, adds it plus `wxc-wslc-daemon.exe` to the native unit, enforces the expected file count, SHA-verifies each staged file against what cargo produced, and packs the unit into `runtimes//native`. It also blocks mixed-feature multi-RID packs via a `mxc-build-features.txt` stamp.
#### The actual gaps
1. **No packaging policy, and no pack pipeline.** `MxcWithWslc` defaults to `false` (`Microsoft.Mxc.Sdk.csproj:34`) and controls a *compile-time* cargo feature. A default-built package therefore contains neither the WSLc code nor the DLL, and a consumer **cannot opt in** — enabling WSLc requires a repack, not a runtime switch. Meanwhile there is no `dotnet pack` step in any workflow or pipeline; `SDK.Dotnet.Test.Job.yml` only *builds and tests* with the switch on. So whether a published package supports WSLc is currently decided ad hoc at pack time, by whoever runs the command.
2. **`wslcsdk.dll` is undocumented for Rust SDK consumers.** There are zero mentions of `wslcsdk` or `WSLC_SDK_PATH` anywhere in `src/core/mxc-sdk/` or `src/ffi/mxc_ffi/`. The `mxc-sdk` README's WSLC section (L401-430) covers the feature flag, settings, and limitations, but never mentions that a native DLL is fetched at build time, that it lands in the profile directory, that `WSLC_SDK_PATH` exists for offline builds, or that the default path depends on access to an internal Azure Artifacts feed.
3. **`cargo install` drops the DLL.** It copies only the binary out of the profile directory, so an installed artifact cannot load WSLc. Needs either handling or an explicit documented caveat.
4. **Redistribution terms are unconfirmed.** Whether `wslcsdk.dll` may ship in a public NuGet package has not been established. This gates gap 1.
#### Proposed scope
- Decide whether the officially published `Microsoft.Mxc.Sdk` package enables WSLc, and encode that decision in a real `dotnet pack` step rather than leaving it to the packager's command line.
- Confirm redistribution terms for `wslcsdk.dll` before shipping it publicly.
- Document the native-DLL dependency for Rust SDK consumers building with the `wslc` feature: where it lands, the `WSLC_SDK_PATH` offline path, and the feed dependency.
- Decide how `cargo install` should behave, and document the outcome either way.
### Additional context
Raised by @bbonaby during review of #1064 (WSLc promotion to the stable config surface): https://github.com/microsoft/mxc/pull/1064#discussion_r3921487699
Deliberately out of scope for #1064, which only moves WSLc's *config surface* off the `--experimental` gate. That is orthogonal to the compile-time `wslc` Cargo feature and to DLL distribution, both of which are unchanged by that PR.
Relevant files:
- `src/backends/wslc/common/build.rs` — SDK acquisition and the profile-directory copy
- `src/backends/wslc/common/src/wslc_bindings.rs` — module-relative `LoadLibrary` resolution (L92-96)
- `sdk/dotnet/Microsoft.Mxc.Sdk/Microsoft.Mxc.Sdk.csproj` — `MxcWithWslc`, native-unit staging, SHA verification, `runtimes//native` packing
- `.github/workflows/SDK.Dotnet.Test.Job.yml` — builds/tests with `MxcWithWslc=true`; does not pack
- `src/core/mxc-sdk/README.md` — WSLC section that needs the DLL documentation
- `docs/wsl/wslc-sdk-bindings.md` — WSLC SDK version-bump runbook
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.