microsoft / microsoft/mxc

[WSLC] Decide whether the shipped C# NuGet enables WSLc, and document wslcsdk.dll for Rust SDK consumers

Open
#1,106 0 comments 0 reactions 1 assignee View on GitHub

@SohamDas2021 is already working on this.

Since Sep 4, 2026.

Issue-Bug Priority2
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.