- systemd-user environment generator and appsandbox-gpu wrapper both
append /usr/lib/wsl/lib to LD_LIBRARY_PATH. ldconfig has the .so.1
entries cached, but the 9P mount is read-only so the unversioned
symlinks ldconfig wants to create can't be written. dlopen() of
unversioned names (libcuda.so, libnvidia-encode.so, libnvcuvid.so)
needs the path on LD_LIBRARY_PATH — without it ffmpeg's h264_nvenc /
h264_cuvid plugins fail with 'Cannot load libcuda.so.1'.
- setup.sh: symlink /usr/lib/wsl/lib/nvidia-smi to /usr/local/bin so
the bare command works without env tweaks. Created unconditionally
because the symlink target is resolved at exec time — the file
appears under the agent's 9P mount on first boot regardless of when
the symlink was created.
Ubuntu 26.04 LTS guest end-to-end:
- cidata-driven autoinstall pipeline (subiquity user-data + nested
cloud-init bootcmd) in disk_util.c. Static NAT IP, ssh-via-vsock
marker, serial-debug kernel cmdline injected into ESP grub.cfg by
iso-patch.exe. Five separate firstboot pipeline fixes get the VM
to GDM unattended on Hyper-V Gen 2.
- Linux guest stack under tools/linux/:
- appsandbox-agent (vsock :1 control + clipboard helper spawn)
- appsandbox-audio (snd-aloop -> vsock :4)
- appsandbox-display (KMS framebuffer capture -> vsock :2)
- appsandbox-input (uinput injection <- vsock :3)
- appsandbox-clipboard (XCB selection bridge <-> vsock :5/:6)
Helper binaries staged via release/resources/linux/.
- asb_drm DRM module: virtual single-CRTC display sink the host
captures over vsock. Platform-bus, DRIVER_GEM/MODESET/ATOMIC/RENDER,
linear shmem framebuffers. asb-evict-simpledrm.service unbinds the
EFI simple-framebuffer before display-manager so mutter binds
asb_drm as the sole DRM card.
- dxgkrnl vendored byte-identical from microsoft/WSL2-Linux-Kernel
linux-msft-wsl-6.18.y with our DKMS/out-of-tree shim (dxgkrnl_compat.h
+ Kbuild + dkms.conf). Autoinstall late-commands dkms-builds against
every /target/lib/modules/<kver> so kernel-version drift between ISO
and post-update reboot still leaves a working .ko.
- wsl-mesa custom build (Mesa 25.3 + d3d12 gallium + microsoft-
experimental dzn Vulkan). Installs to /opt/wsl-mesa parallel to
Ubuntu's stock Mesa. Prebuilt tarball for ubuntu-26.04-amd64
shipped under tools/linux/wsl-mesa/prebuilt/ (21 MB).
- Per-VM GPU acceleration policy:
- /etc/systemd/user-environment-generators/50-appsandbox-gpu
emits GALLIUM_DRIVER=d3d12 + LD_LIBRARY_PATH + VK_DRIVER_FILES
into the user@1000 systemd-user environment when /dev/dxg and
/opt/wsl-mesa are present. Inherited by every app-*.scope a
.desktop launch creates.
- /etc/systemd/user/org.gnome.Shell@.service.d/no-gpu.conf
UnsetEnvironment= strips these for the compositor — mutter
stays on llvmpipe so asb_drm scanout works (the d3d12 pipe has
no GBM compatibility with asb_drm).
- /usr/local/bin/appsandbox-gpu wrapper for terminal-launched
opt-in GPU acceleration (probes /dev/dxg; no-op on no-GPU VMs).
- Host changes:
- vm_display_idd.c, vm_clipboard.c, vm_agent.c, vm_ssh_proxy.c,
asb_display.c: hcs_service_guid(os_type, port) so the same code
paths reach the per-OS service identifiers (HV_GUID for Windows,
vsock template for Linux).
- asb_core.c: linux_create_thread builds an empty VHDX, cidata
ISO with extras (agent ELFs, dxgkrnl src, asb_drm src, wsl-mesa
tarball, wsl-deps libs), and boots the desktop ISO + cidata.
- hcs_vm.c: HostLxssLib Plan9 share appended for Linux VMs;
VideoMonitor + ComPorts retained for serial debug.
- gpu_enum.c/h: gpu_append_lxsslib_share helper.
- vm_clipboard.c file-drop support (CF_HDROP / x-special/gnome-
copied-files round-trip).
- vm_display_idd.c: 32-bit S32_LE PCM audio path matches the
Linux daemon's snd-aloop capture format.
- iso-patch.c gains a patch_ubuntu_esp_grub_for_debug pass that
rewrites /EFI/ubuntu/grub.cfg via the FAT32 ESP, plus a qcow2->
vhdx converter with a RFC 1951 DEFLATE inflater for compressed
cluster handling.
- wsl-deps: Microsoft's libd3d12.so / libd3d12core.so / libdxcore.so
fetched on demand from the public NuGet feed
pkgs.dev.azure.com/shine-oss/wsl (no auth). Staged at
/opt/appsandbox/wsl-deps on the guest and put on /etc/ld.so.conf.d
rather than /usr/lib/wsl/lib (which is overlaid by the agent's
9P mount).
UI: web/{app.js,index.html} expose Linux VM creation + GPU selection,
distribution dropdown for cached Ubuntu ISOs, and the ISO picker for
custom images.
Every PostBuildEvent xcopy command ended a quoted path with a trailing
backslash (e.g. "$(OutDir)resources\"). cmd.exe / CommandLineToArgvW
interpret the \" as an escaped literal quote, so xcopy receives a path
with an embedded " and an unclosed quote state - works fine when no
quotes are needed (no spaces in the path) but fails the moment the
parent path contains a space.
Drop the trailing backslash on each destination; xcopy /I infers
"directory" without it. For the bare "$(OutDir)" case, append a . so
the closing quote isn't preceded by a backslash.
Move Windows app shell (main.c, ui.c, webview2_bridge) into src/app_win
and macOS app shell into src/app_mac. Move Xcode project to repo root
alongside the Visual Studio .sln. Both platforms now follow the same
structure:
src/app_win/ Windows app shell
src/app_mac/ macOS app shell
src/backend_win/ Windows HCS engine
src/backend_mac/ macOS VZ engine
src/core/ shared types and backend vtable
Moves every existing Windows-only backend source under src/backend_win/
and extracts a shared src/core/ layer: backend.h defines a BackendVtbl
abstraction, vm_types.h defines CoreVmConfig/CoreVmInfo/CoreVmEvent so
core code never touches platform types directly. backend_win.c is the
Windows implementation that wires the existing HCS code into the vtable.
Also adds tools/check-sources.py to detect drift between src/core/ on
disk and what the Windows .vcxproj and macOS .xcodeproj reference.
bugs fixed: the agent -> host messaging passing was unreliable
The NAT IP address failed to automatically set on first boot for VMs created from ISO.
SSH doesn't require internet which is cool, goes over Hyper-V sockets.
set nat as default network, set IP address automatically when in NAT mode, don't open the rdp display on win11 home, fix a bug where display would open again at shutdown if it was closed