about summary refs log tree commit diff
path: root/pkgs/development/compilers/dotnet/common.nix
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/development/compilers/dotnet/common.nix')
-rw-r--r--pkgs/development/compilers/dotnet/common.nix364
1 files changed, 228 insertions, 136 deletions
diff --git a/pkgs/development/compilers/dotnet/common.nix b/pkgs/development/compilers/dotnet/common.nix
index 49f3e3be4d779..426eb848d8690 100644
--- a/pkgs/development/compilers/dotnet/common.nix
+++ b/pkgs/development/compilers/dotnet/common.nix
@@ -1,149 +1,241 @@
 # TODO: switch to stdenvNoCC
-{ stdenv
-, lib
-, writeText
-, testers
-, runCommand
-, expect
-, curl
-, installShellFiles
-}: type: args: stdenv.mkDerivation (finalAttrs: args // {
-  doInstallCheck = true;
+{
+  stdenv,
+  stdenvNoCC,
+  lib,
+  writeText,
+  testers,
+  runCommand,
+  runCommandWith,
+  expect,
+  curl,
+  installShellFiles,
+  callPackage,
+  zlib,
+  swiftPackages,
+  darwin,
+  icu,
+  lndir,
+  substituteAll,
+  nugetPackageHook,
+  xmlstarlet,
+}:
+type: args:
+stdenv.mkDerivation (
+  finalAttrs:
+  args
+  // {
+    doInstallCheck = true;
 
-  # TODO: this should probably be postInstallCheck
-  # TODO: send output to /dev/null
-  installCheckPhase = args.installCheckPhase or "" + ''
-    $out/bin/dotnet --info
-  '';
+    # TODO: this should probably be postInstallCheck
+    # TODO: send output to /dev/null
+    installCheckPhase =
+      args.installCheckPhase or ""
+      + ''
+        $out/bin/dotnet --info
+      '';
 
-  # TODO: move this to sdk section?
-  setupHook = writeText "dotnet-setup-hook" (''
-    if [ ! -w "$HOME" ]; then
-      export HOME=$(mktemp -d) # Dotnet expects a writable home directory for its configuration files
-    fi
+    setupHooks =
+      args.setupHooks or [ ]
+      ++ [
+        ./dotnet-setup-hook.sh
+      ]
+      ++ lib.optional (type == "sdk") (substituteAll {
+        src = ./dotnet-sdk-setup-hook.sh;
+        inherit lndir xmlstarlet;
+      });
 
-    export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 # Dont try to expand NuGetFallbackFolder to disk
-    export DOTNET_NOLOGO=1 # Disables the welcome message
-    export DOTNET_CLI_TELEMETRY_OPTOUT=1
-    export DOTNET_SKIP_WORKLOAD_INTEGRITY_CHECK=1 # Skip integrity check on first run, which fails due to read-only directory
-  '' + args.setupHook or "");
+    propagatedBuildInputs =
+      (args.propagatedBuildInputs or [ ])
+      ++ lib.optional (type == "sdk") nugetPackageHook;
 
-  nativeBuildInputs = (args.nativeBuildInputs or []) ++ [ installShellFiles ];
+    nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ installShellFiles ];
 
-  postInstall = ''
-    # completions snippets taken from https://learn.microsoft.com/en-us/dotnet/core/tools/enable-tab-autocomplete
-    installShellCompletion --cmd dotnet \
-      --bash ${./completions/dotnet.bash} \
-      --zsh ${./completions/dotnet.zsh} \
-      --fish ${./completions/dotnet.fish}
-  '';
+    postInstall = ''
+      # completions snippets taken from https://learn.microsoft.com/en-us/dotnet/core/tools/enable-tab-autocomplete
+      installShellCompletion --cmd dotnet \
+        --bash ${./completions/dotnet.bash} \
+        --zsh ${./completions/dotnet.zsh} \
+        --fish ${./completions/dotnet.fish}
+    '';
 
-  passthru = {
-    tests = let
-      mkDotnetTest =
-        {
-          name,
-          template,
-          usePackageSource ? false,
-          build,
-          # TODO: use correct runtimes instead of sdk
-          runtime ? finalAttrs.finalPackage,
-          runInputs ? [],
-          run ? null,
-        }:
+    passthru = {
+      tests =
         let
-          built = runCommand "dotnet-test-${name}" { buildInputs = [ finalAttrs.finalPackage ]; } (''
-            HOME=$PWD/.home
-            dotnet new nugetconfig
-            dotnet nuget disable source nuget
-          '' + lib.optionalString usePackageSource ''
-            dotnet nuget add source ${finalAttrs.finalPackage.packages}
-          '' + ''
-            dotnet new ${template} -n test -o .
-          '' + build);
-        in
-          if run == null
-            then built
-          else
-            runCommand "${built.name}-run" { src = built; nativeBuildInputs = runInputs; } (
-              lib.optionalString (runtime != null) ''
-                # TODO: use runtime here
-                export DOTNET_ROOT=${runtime}
-              '' + run);
+          mkDotnetTest =
+            {
+              name,
+              stdenv ? stdenvNoCC,
+              template,
+              usePackageSource ? false,
+              build,
+              buildInputs ? [ ],
+              # TODO: use correct runtimes instead of sdk
+              runtime ? finalAttrs.finalPackage,
+              runInputs ? [ ],
+              run ? null,
+              runAllowNetworking ? false,
+            }:
+            let
+              sdk = finalAttrs.finalPackage;
+              built = stdenv.mkDerivation {
+                name = "dotnet-test-${name}";
+                buildInputs = [ sdk ] ++ buildInputs ++ lib.optional (usePackageSource) sdk.packages;
+                # make sure ICU works in a sandbox
+                propagatedSandboxProfile = toString sdk.__propagatedSandboxProfile;
+                unpackPhase = ''
+                  mkdir test
+                  cd test
+                  dotnet new ${template} -o . --no-restore
+                '';
+                buildPhase = build;
+                dontPatchELF = true;
+              };
+            in
+            if run == null then
+              built
+            else
+              runCommand "${built.name}-run"
+                (
+                  {
+                    src = built;
+                    nativeBuildInputs = [ built ] ++ runInputs;
+                    passthru = {
+                      inherit built;
+                    };
+                  }
+                  // lib.optionalAttrs (stdenv.hostPlatform.isDarwin && runAllowNetworking) {
+                    sandboxProfile = ''
+                      (allow network-inbound (local ip))
+                      (allow mach-lookup (global-name "com.apple.FSEvents"))
+                    '';
+                    __darwinAllowLocalNetworking = true;
+                  }
+                )
+                (
+                  lib.optionalString (runtime != null) ''
+                    # TODO: use runtime here
+                    export DOTNET_ROOT=${runtime}
+                  ''
+                  + run
+                );
 
-      # Setting LANG to something other than 'C' forces the runtime to search
-      # for ICU, which will be required in most user environments.
-      checkConsoleOutput = command: ''
-        output="$(LANG=C.UTF-8 ${command})"
-        # yes, older SDKs omit the comma
-        [[ "$output" =~ Hello,?\ World! ]] && touch "$out"
-      '';
-
-    in {
-      version = testers.testVersion ({
-        package = finalAttrs.finalPackage;
-      } // lib.optionalAttrs (type != "sdk") {
-        command = "dotnet --info";
-      });
-    }
-    // lib.optionalAttrs (type == "sdk") {
-      console = mkDotnetTest {
-        name = "console";
-        template = "console";
-        build = checkConsoleOutput "dotnet run";
-      };
+          # Setting LANG to something other than 'C' forces the runtime to search
+          # for ICU, which will be required in most user environments.
+          checkConsoleOutput = command: ''
+            output="$(LANG=C.UTF-8 ${command})"
+            # yes, older SDKs omit the comma
+            [[ "$output" =~ Hello,?\ World! ]] && touch "$out"
+          '';
+        in
+        {
+          version = testers.testVersion (
+            {
+              package = finalAttrs.finalPackage;
+            }
+            // lib.optionalAttrs (type != "sdk") {
+              command = "dotnet --info";
+            }
+          );
+        }
+        // lib.optionalAttrs (type == "sdk") (
+          {
+            console = mkDotnetTest {
+              name = "console";
+              template = "console";
+              build = checkConsoleOutput "dotnet run";
+            };
 
-      publish = mkDotnetTest {
-        name = "publish";
-        template = "console";
-        build = "dotnet publish -o $out";
-        run = checkConsoleOutput "$src/test";
-      };
+            publish = mkDotnetTest {
+              name = "publish";
+              template = "console";
+              build = "dotnet publish -o $out/bin";
+              run = checkConsoleOutput "$src/bin/test";
+            };
 
-      self-contained = mkDotnetTest {
-        name = "self-contained";
-        template = "console";
-        usePackageSource = true;
-        build = "dotnet publish --use-current-runtime --sc -o $out";
-        runtime = null;
-        run = checkConsoleOutput "$src/test";
-      };
+            self-contained = mkDotnetTest {
+              name = "self-contained";
+              template = "console";
+              usePackageSource = true;
+              build = "dotnet publish --use-current-runtime --sc -o $out";
+              runtime = null;
+              run = checkConsoleOutput "$src/test";
+            };
 
-      single-file = mkDotnetTest {
-        name = "single-file";
-        template = "console";
-        usePackageSource = true;
-        build = "dotnet publish --use-current-runtime -p:PublishSingleFile=true -o $out";
-        runtime = null;
-        run = checkConsoleOutput "$src/test";
-      };
+            single-file = mkDotnetTest {
+              name = "single-file";
+              template = "console";
+              usePackageSource = true;
+              build = "dotnet publish --use-current-runtime -p:PublishSingleFile=true -o $out/bin";
+              runtime = null;
+              run = checkConsoleOutput "$src/bin/test";
+            };
 
-      web = mkDotnetTest {
-        name = "web";
-        template = "web";
-        build = "dotnet publish -o $out";
-        runInputs = [ expect curl ];
-        run = ''
-          expect <<"EOF"
-            set status 1
-            spawn $env(src)/test
-            expect_before default abort
-            expect -re {Now listening on: ([^\r]+)\r} {
-              set url $expect_out(1,string)
-            }
-            expect "Application started. Press Ctrl+C to shut down."
-            set output [exec curl -sSf $url]
-            if {$output != "Hello World!"} {
-              send_error "Unexpected output: $output\n"
-              exit 1
-            }
-            send \x03
-            catch wait result
-            exit [lindex $result 3]
-          EOF
-          touch $out
-        '';
-      };
-    } // args.passthru.tests or {};
-  } // args.passthru or {};
-})
+            web = mkDotnetTest {
+              name = "web";
+              template = "web";
+              build = "dotnet publish -o $out/bin";
+              runInputs = [
+                expect
+                curl
+              ];
+              run = ''
+                expect <<"EOF"
+                  set status 1
+                  spawn $env(src)/bin/test
+                  proc abort { } { exit 2 }
+                  expect_before default abort
+                  expect -re {Now listening on: ([^\r]+)\r} {
+                    set url $expect_out(1,string)
+                  }
+                  expect "Application started. Press Ctrl+C to shut down."
+                  set output [exec curl -sSf $url]
+                  if {$output != "Hello World!"} {
+                    send_error "Unexpected output: $output\n"
+                    exit 1
+                  }
+                  send \x03
+                  expect_before timeout abort
+                  expect eof
+                  catch wait result
+                  exit [lindex $result 3]
+                EOF
+                touch $out
+              '';
+              runAllowNetworking = true;
+            };
+          }
+          // lib.optionalAttrs finalAttrs.finalPackage.hasILCompiler {
+            aot = mkDotnetTest {
+              name = "aot";
+              stdenv = if stdenv.hostPlatform.isDarwin then swiftPackages.stdenv else stdenv;
+              template = "console";
+              usePackageSource = true;
+              buildInputs =
+                [
+                  zlib
+                ]
+                ++ lib.optional stdenv.hostPlatform.isDarwin (
+                  with darwin;
+                  with apple_sdk.frameworks;
+                  [
+                    swiftPackages.swift
+                    Foundation
+                    CryptoKit
+                    GSS
+                    ICU
+                  ]
+                );
+              build = ''
+                dotnet restore -p:PublishAot=true
+                dotnet publish -p:PublishAot=true -o $out/bin
+              '';
+              runtime = null;
+              run = checkConsoleOutput "$src/bin/test";
+            };
+          }
+        )
+        // args.passthru.tests or { };
+    } // args.passthru or { };
+  }
+)