From 8e11dcca482a3ed7d3107bd5b60af89f8cb58a73 Mon Sep 17 00:00:00 2001 From: IvarWithoutBones Date: Mon, 22 Nov 2021 02:12:42 +0100 Subject: [PATCH] buildDotnetModule: add passthru.fetch-deps --- doc/languages-frameworks/dotnet.section.md | 7 +++- .../build-dotnet-module/default.nix | 41 +++++++++++++++++-- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/doc/languages-frameworks/dotnet.section.md b/doc/languages-frameworks/dotnet.section.md index 94d97a970dbb..159347008e80 100644 --- a/doc/languages-frameworks/dotnet.section.md +++ b/doc/languages-frameworks/dotnet.section.md @@ -72,7 +72,7 @@ The `dotnetCorePackages.sdk` contains both a runtime and the full sdk of a given To package Dotnet applications, you can use `buildDotnetModule`. This has similar arguments to `stdenv.mkDerivation`, with the following additions: * `projectFile` has to be used for specifying the dotnet project file relative to the source root. These usually have `.sln` or `.csproj` file extensions. This can be an array of multiple projects as well. -* `nugetDeps` has to be used to specify the NuGet dependency file. Unfortunately, these cannot be deterministically fetched without a lockfile. This file should be generated using `nuget-to-nix` tool, which is available in nixpkgs. +* `nugetDeps` has to be used to specify the NuGet dependency file. Unfortunately, these cannot be deterministically fetched without a lockfile. A script to fetch these is available as `passthru.fetch-deps`. This file can also be generated manually using `nuget-to-nix` tool, which is available in nixpkgs. * `packNupkg` is used to pack project as a `nupkg`, and installs it to `$out/share`. If set to `true`, the derivation can be used as a dependency for another dotnet project by adding it to `projectReferences`. * `projectReferences` can be used to resolve `ProjectReference` project items. Referenced projects can be packed with `buildDotnetModule` by setting the `packNupkg = true` attribute and passing a list of derivations to `projectReferences`. Since we are sharing referenced projects as NuGets they must be added to csproj/fsproj files as `PackageReference` as well. For example, your project has a local dependency: @@ -99,6 +99,8 @@ To package Dotnet applications, you can use `buildDotnetModule`. This has simila * `dotnetPackFlags` can be used to pass flags to `dotnet pack`. Used only if `packNupkg` is set to `true`. * `dotnetFlags` can be used to pass flags to all of the above phases. +When packaging a new application, you need to fetch it's dependencies. You can set `nugetDeps` to an empty string to make the derivation temporarily evaluate, and then run `nix-build -A package.passthru.fetch-deps` to generate it's dependency fetching script. After running the script, you should have the location of the generated lockfile printed to the console. This can be copied to a stable directory. Note that if either `projectFile` or `nugetDeps` are unset, this script cannot be generated! + Here is an example `default.nix`, using some of the previously discussed arguments: ```nix { lib, buildDotnetModule, dotnetCorePackages, ffmpeg }: @@ -112,7 +114,8 @@ in buildDotnetModule rec { src = ./.; projectFile = "src/project.sln"; - nugetDeps = ./deps.nix; # File generated with `nuget-to-nix path/to/src > deps.nix`. + nugetDeps = ./deps.nix; # File generated with `nix-build -A package.passthru.fetch-deps`. + projectReferences = [ referencedProject ]; # `referencedProject` must contain `nupkg` in the folder structure. dotnet-sdk = dotnetCorePackages.sdk_3_1; diff --git a/pkgs/build-support/build-dotnet-module/default.nix b/pkgs/build-support/build-dotnet-module/default.nix index 7e56e70bf8b9..93077f438bff 100644 --- a/pkgs/build-support/build-dotnet-module/default.nix +++ b/pkgs/build-support/build-dotnet-module/default.nix @@ -1,4 +1,4 @@ -{ lib, stdenvNoCC, linkFarmFromDrvs, makeWrapper, fetchurl, xml2, dotnetCorePackages, dotnetPackages, cacert }: +{ lib, stdenvNoCC, linkFarmFromDrvs, nuget-to-nix, writeScript, makeWrapper, fetchurl, xml2, dotnetCorePackages, dotnetPackages, cacert }: { name ? "${args.pname}-${args.version}" , enableParallelBuilding ? true @@ -28,7 +28,7 @@ # The packages project file, which contains instructions on how to compile it. This can be an array of multiple project files as well. , projectFile ? null # The NuGet dependency file. This locks all NuGet dependency versions, as otherwise they cannot be deterministically fetched. -# This can be generated using the `nuget-to-nix` tool. +# This can be generated by running the `passthru.fetch-deps` script. , nugetDeps ? null # A list of derivations containing nupkg packages for local project references. # Referenced derivations can be built with `buildDotnetModule` with `packNupkg=true` flag. @@ -63,7 +63,7 @@ assert projectFile == null -> throw "Defining the `projectFile` attribute is req # TODO: Automatically generate a dependency file when a lockfile is present. # This file is unfortunately almost never present, as Microsoft recommands not to push this in upstream repositories. -assert nugetDeps == null -> throw "Defining the `nugetDeps` attribute is required, as to lock the NuGet dependencies. This file can be generated using the `nuget-to-nix` tool."; +assert nugetDeps == null -> throw "Defining the `nugetDeps` attribute is required, as to lock the NuGet dependencies. This file can be generated by running the `passthru.fetch-deps` script."; let _nugetDeps = linkFarmFromDrvs "${name}-nuget-deps" (import nugetDeps { @@ -113,6 +113,41 @@ let DOTNET_NOLOGO = true; # This disables the welcome message. DOTNET_CLI_TELEMETRY_OPTOUT = true; + passthru.fetch-deps = args.passthru.fetch-deps or writeScript "fetch-${args.pname}-deps" '' + set -euo pipefail + cd "$(dirname "''${BASH_SOURCE[0]}")" + + export HOME=$(mktemp -d) + deps_file="/tmp/${args.pname}-deps.nix" + + store_src="${package.src}" + src="$(mktemp -d /tmp/${args.pname}.XXX)" + cp -rT "$store_src" "$src" + chmod -R +w "$src" + + trap "rm -rf $src $HOME" EXIT + pushd "$src" + + export DOTNET_NOLOGO=1 + export DOTNET_CLI_TELEMETRY_OPTOUT=1 + + mkdir -p "$HOME/nuget_pkgs" + + for project in "${lib.concatStringsSep "\" \"" (lib.toList projectFile)}"; do + ${dotnet-sdk}/bin/dotnet restore "$project" \ + ${lib.optionalString (!enableParallelBuilding) "--disable-parallel"} \ + -p:ContinuousIntegrationBuild=true \ + -p:Deterministic=true \ + --packages "$HOME/nuget_pkgs" \ + "''${dotnetRestoreFlags[@]}" \ + "''${dotnetFlags[@]}" + done + + echo "Writing lockfile..." + ${nuget-to-nix}/bin/nuget-to-nix "$HOME/nuget_pkgs" > "$deps_file" + echo "Succesfully wrote lockfile to: $deps_file" + ''; + configurePhase = args.configurePhase or '' runHook preConfigure