summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/interop.nix88
-rw-r--r--modules/wsl-distro.nix70
2 files changed, 89 insertions, 69 deletions
diff --git a/modules/interop.nix b/modules/interop.nix
new file mode 100644
index 0000000..b7babfb
--- /dev/null
+++ b/modules/interop.nix
@@ -0,0 +1,88 @@
+{ lib, pkgs, config, ... }:
+
+with builtins; with lib;
+{
+ imports = [
+ (mkRenamedOptionModule [ "wsl" "compatibility" "interopPreserveArgvZero" ] [ "wsl" "interop" "preserveArgvZero" ])
+ ];
+
+ options.wsl.interop = with types; {
+ register = mkOption {
+ type = bool;
+ default = false; # Use the existing registration by default
+ description = "Explicitly register the binfmt_misc handler for Windows executables";
+ };
+
+ includePath = mkOption {
+ type = bool;
+ default = true;
+ description = "Include Windows PATH in WSL PATH";
+ };
+
+ preserveArgvZero = mkOption {
+ type = nullOr bool;
+ default = null;
+ description = ''
+ Register binfmt interpreter for Windows executables with 'preserves argv[0]' flag.
+
+ Default (null): autodetect, at some performance cost.
+ To avoid the performance cost, set this to true for WSL Preview 0.58 and up,
+ or to false for any older versions, including pre-Microsoft Store and Windows 10.
+ '';
+ };
+ };
+
+ config =
+ let
+ cfg = config.wsl.interop;
+ in
+ mkIf config.wsl.enable {
+
+ boot.binfmt.registrations = mkIf cfg.register {
+ WSLInterop =
+ let
+ compat = cfg.preserveArgvZero;
+
+ # WSL Preview 0.58 and up registers the /init binfmt interp for Windows executable
+ # with the "preserve argv[0]" flag, so if you run `./foo.exe`, the interp gets invoked
+ # as `/init foo.exe ./foo.exe`.
+ # argv[0] --^ ^-- actual path
+ #
+ # Older versions expect to be called without the argv[0] bit, simply as `/init ./foo.exe`.
+ #
+ # We detect that by running `/init /known-not-existing-path.exe` and checking the exit code:
+ # the new style interp expects at least two arguments, so exits with exit code 1,
+ # presumably meaning "parsing error"; the old style interp attempts to actually run
+ # the executable, fails to find it, and exits with 255.
+ compatWrapper = pkgs.writeShellScript "nixos-wsl-binfmt-hack" ''
+ /init /nixos-wsl-does-not-exist.exe
+ [ $? -eq 255 ] && shift
+ exec /init "$@"
+ '';
+
+ # use the autodetect hack if unset, otherwise call /init directly
+ interpreter = if compat == null then compatWrapper else "/init";
+
+ # enable for the wrapper and autodetect hack
+ preserveArgvZero = if compat == false then false else true;
+ in
+ {
+ magicOrExtension = "MZ";
+ fixBinary = true;
+ wrapInterpreterInShell = false;
+ inherit interpreter preserveArgvZero;
+ };
+ };
+
+ # Include Windows %PATH% in Linux $PATH.
+ environment.extraInit = mkIf cfg.includePath ''PATH="$PATH:$WSLPATH"'';
+
+ warnings =
+ let
+ registrations = config.boot.binfmt.registrations;
+ in
+ optional (!(registrations ? WSLInterop) && (length (attrNames config.boot.binfmt.registrations)) != 0) "Having any binfmt registrations without re-registering WSLInterop (wsl.interop.register) will break running .exe files from WSL2";
+ };
+
+
+}
diff --git a/modules/wsl-distro.nix b/modules/wsl-distro.nix
index 0f7d8b0..e87112a 100644
--- a/modules/wsl-distro.nix
+++ b/modules/wsl-distro.nix
@@ -28,34 +28,6 @@ with builtins; with lib;
type = attrsOf (attrsOf (oneOf [ string int bool ]));
description = "Entries that are added to /etc/wsl.conf";
};
-
- interop = {
- register = mkOption {
- type = bool;
- default = true;
- description = "Explicitly register the binfmt_misc handler for Windows executables";
- };
-
- includePath = mkOption {
- type = bool;
- default = true;
- description = "Include Windows PATH in WSL PATH";
- };
- };
-
- compatibility = {
- interopPreserveArgvZero = mkOption {
- type = nullOr bool;
- default = null;
- description = ''
- Register binfmt interpreter for Windows executables with 'preserves argv[0]' flag.
-
- Default (null): autodetect, at some performance cost.
- To avoid the performance cost, set this to true for WSL Preview 0.58 and up,
- or to false for any older versions, including pre-Microsoft Store and Windows 10.
- '';
- };
- };
};
config =
@@ -79,52 +51,12 @@ with builtins; with lib;
};
# WSL is closer to a container than anything else
- boot = {
- isContainer = true;
-
- binfmt.registrations = mkIf cfg.interop.register {
- WSLInterop =
- let
- compat = cfg.compatibility.interopPreserveArgvZero;
-
- # WSL Preview 0.58 and up registers the /init binfmt interp for Windows executable
- # with the "preserve argv[0]" flag, so if you run `./foo.exe`, the interp gets invoked
- # as `/init foo.exe ./foo.exe`.
- # argv[0] --^ ^-- actual path
- #
- # Older versions expect to be called without the argv[0] bit, simply as `/init ./foo.exe`.
- #
- # We detect that by running `/init /known-not-existing-path.exe` and checking the exit code:
- # the new style interp expects at least two arguments, so exits with exit code 1,
- # presumably meaning "parsing error"; the old style interp attempts to actually run
- # the executable, fails to find it, and exits with 255.
- compatWrapper = pkgs.writeShellScript "nixos-wsl-binfmt-hack" ''
- /init /nixos-wsl-does-not-exist.exe
- [ $? -eq 255 ] && shift
- exec /init "$@"
- '';
-
- # use the autodetect hack if unset, otherwise call /init directly
- interpreter = if compat == null then compatWrapper else "/init";
-
- # enable for the wrapper and autodetect hack
- preserveArgvZero = if compat == false then false else true;
- in
- {
- magicOrExtension = "MZ";
- fixBinary = true;
- wrapInterpreterInShell = false;
- inherit interpreter preserveArgvZero;
- };
- };
- };
+ boot.isContainer = true;
environment.noXlibs = lib.mkForce false; # override xlibs not being installed (due to isContainer) to enable the use of GUI apps
hardware.opengl.enable = true; # Enable GPU acceleration
environment = {
- # Include Windows %PATH% in Linux $PATH.
- extraInit = mkIf cfg.interop.includePath ''PATH="$PATH:$WSLPATH"'';
etc = {
"wsl.conf".text = generators.toINI { } cfg.wslConf;