From abf6081bc2aeb6746044b3528bb5f5dd5b3f0d84 Mon Sep 17 00:00:00 2001 From: mdarocha Date: Tue, 20 Jun 2023 17:19:30 +0200 Subject: [PATCH] buildDotnetModule: add useDotnetFromEnv option This causes an alternative wrapper to be used, that takes the dotnet runtime from the environment. --- doc/languages-frameworks/dotnet.section.md | 2 ++ .../dotnet/build-dotnet-module/default.nix | 7 +++++-- .../dotnet/build-dotnet-module/hooks/default.nix | 6 ++++++ .../build-dotnet-module/hooks/dotnet-fixup-hook.sh | 13 +++++++++++-- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/doc/languages-frameworks/dotnet.section.md b/doc/languages-frameworks/dotnet.section.md index b6a622875a76..cd7f2c45d8fd 100644 --- a/doc/languages-frameworks/dotnet.section.md +++ b/doc/languages-frameworks/dotnet.section.md @@ -109,6 +109,8 @@ To package Dotnet applications, you can use `buildDotnetModule`. This has simila * `runtimeDeps` is used to wrap libraries into `LD_LIBRARY_PATH`. This is how dotnet usually handles runtime dependencies. * `buildType` is used to change the type of build. Possible values are `Release`, `Debug`, etc. By default, this is set to `Release`. * `selfContainedBuild` allows to enable the [self-contained](https://docs.microsoft.com/en-us/dotnet/core/deploying/#publish-self-contained) build flag. By default, it is set to false and generated applications have a dependency on the selected dotnet runtime. If enabled, the dotnet runtime is bundled into the executable and the built app has no dependency on Dotnet. +* `useAppHost` will enable creation of a binary executable that runs the .NET application using the specified root. More info in [Microsoft docs](https://learn.microsoft.com/en-us/dotnet/core/deploying/#publish-framework-dependent). Enabled by default. +* `useDotnetFromEnv` will change the binary wrapper so that it uses the .NET from the environment. The runtime specified by `dotnet-runtime` is given as a fallback in case no .NET is installed in the user's environment. This is most useful for .NET global tools and LSP servers, which often extend the .NET CLI and their runtime should match the users' .NET runtime. * `dotnet-sdk` is useful in cases where you need to change what dotnet SDK is being used. You can also set this to the result of `dotnetSdkPackages.combinePackages`, if the project uses multiple SDKs to build. * `dotnet-runtime` is useful in cases where you need to change what dotnet runtime is being used. This can be either a regular dotnet runtime, or an aspnetcore. * `dotnet-test-sdk` is useful in cases where unit tests expect a different dotnet SDK. By default, this is set to the `dotnet-sdk` attribute. diff --git a/pkgs/build-support/dotnet/build-dotnet-module/default.nix b/pkgs/build-support/dotnet/build-dotnet-module/default.nix index bfd249a872b1..a9c49d1e526e 100644 --- a/pkgs/build-support/dotnet/build-dotnet-module/default.nix +++ b/pkgs/build-support/dotnet/build-dotnet-module/default.nix @@ -75,7 +75,10 @@ , buildType ? "Release" # If set to true, builds the application as a self-contained - removing the runtime dependency on dotnet , selfContainedBuild ? false - # Whether to explicitly enable UseAppHost when building + # Whether to use an alternative wrapper, that executes the application DLL using the dotnet runtime from the user environment. `dotnet-runtime` is provided as a default in case no .NET is installed + # This is useful for .NET tools and applications that may need to run under different .NET runtimes +, useDotnetFromEnv ? false + # Whether to explicitly enable UseAppHost when building. This is redundant if useDotnetFromEnv is enabledz , useAppHost ? true # The dotnet SDK to use. , dotnet-sdk ? dotnetCorePackages.sdk_6_0 @@ -159,7 +162,7 @@ stdenvNoCC.mkDerivation (args // { # gappsWrapperArgs gets included when wrapping for dotnet, as to avoid double wrapping dontWrapGApps = args.dontWrapGApps or true; - inherit selfContainedBuild useAppHost; + inherit selfContainedBuild useAppHost useDotnetFromEnv; passthru = { inherit nuget-source; diff --git a/pkgs/build-support/dotnet/build-dotnet-module/hooks/default.nix b/pkgs/build-support/dotnet/build-dotnet-module/hooks/default.nix index a72f0291a872..99d9644f8b70 100644 --- a/pkgs/build-support/dotnet/build-dotnet-module/hooks/default.nix +++ b/pkgs/build-support/dotnet/build-dotnet-module/hooks/default.nix @@ -1,4 +1,7 @@ { lib +, stdenv +, which +, coreutils , callPackage , makeSetupHook , makeWrapper @@ -67,6 +70,9 @@ in substitutions = { dotnetRuntime = dotnet-runtime; runtimeDeps = libraryPath; + shell = stdenv.shell; + which = "${which}/bin/which"; + dirname = "${coreutils}/bin/dirname"; }; } ./dotnet-fixup-hook.sh) { }; } diff --git a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-fixup-hook.sh b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-fixup-hook.sh index 27885238ef7b..70728e4321ed 100644 --- a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-fixup-hook.sh +++ b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-fixup-hook.sh @@ -5,13 +5,22 @@ makeWrapperArgs=( "${derivationMakeWrapperArgs[@]}" ) # First argument is the executable you want to wrap, # the second is the destination for the wrapper. wrapDotnetProgram() { + local dotnetRootFlags=() + if [ ! "${selfContainedBuild-}" ]; then - local -r dotnetRootFlag=("--set" "DOTNET_ROOT" "@dotnetRuntime@") + if [ "${useDotnetFromEnv-}" ]; then + # if dotnet CLI is available, set DOTNET_ROOT based on it. Otherwise set to default .NET runtime + dotnetRootFlags+=("--run" 'command -v dotnet &>/dev/null && export DOTNET_ROOT="$(@dirname@ "$(@dirname@ "$(@which@ dotnet)")")" || export DOTNET_ROOT="@dotnetRuntime@"') + dotnetRootFlags+=("--suffix" "PATH" ":" "@dotnetRuntime@/bin") + else + dotnetRootFlags+=("--set" "DOTNET_ROOT" "@dotnetRuntime@") + dotnetRootFlags+=("--prefix" "PATH" ":" "@dotnetRuntime@/bin") + fi fi makeWrapper "$1" "$2" \ --suffix "LD_LIBRARY_PATH" : "@runtimeDeps@" \ - "${dotnetRootFlag[@]}" \ + "${dotnetRootFlags[@]}" \ "${gappsWrapperArgs[@]}" \ "${makeWrapperArgs[@]}"