buildDotnetModule: dont require specifing a projectFile

In a lot of cases dotnet can figure this out by itself, so we can just
invoke it without the project argument.

Changed files
+92 -55
doc
languages-frameworks
pkgs
build-support
+1 -1
doc/languages-frameworks/dotnet.section.md
···
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` takes either a path to a `deps.nix` file, or a derivation. The `deps.nix` file can be generated using the script attached to `passthru.fetch-deps`. This file can also be generated manually using `nuget-to-nix` tool, which is available in nixpkgs. If the argument is a derivation, it will be used directly and assume it has the same output as `mkNugetDeps`.
* `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.
···
To package Dotnet applications, you can use `buildDotnetModule`. This has similar arguments to `stdenv.mkDerivation`, with the following additions:
+
* `projectFile` is 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` takes either a path to a `deps.nix` file, or a derivation. The `deps.nix` file can be generated using the script attached to `passthru.fetch-deps`. This file can also be generated manually using `nuget-to-nix` tool, which is available in nixpkgs. If the argument is a derivation, it will be used directly and assume it has the same output as `mkNugetDeps`.
* `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.
+21 -12
pkgs/build-support/dotnet/build-dotnet-module/default.nix
···
, ...
} @ args:
-
assert projectFile == null -> throw "Defining the `projectFile` attribute is required. This is usually an `.csproj`, or `.sln` file.";
-
# 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 by running the `passthru.fetch-deps` script.";
···
# Because this list is rather long its put in its own store path to maintain readability of the generated script
exclusions = writeText "nuget-package-exclusions" (lib.concatStringsSep "\n" (dotnet-sdk.passthru.packages { fetchNuGet = attrs: attrs.pname; }));
-
runtimeIds = map (system: dotnet-sdk.systemToDotnetRid system) (args.meta.platforms or dotnet-sdk.meta.platforms);
-
# Derivations may set flags such as `--runtime <rid>` based on the host platform to avoid restoring/building nuget dependencies they dont have or dont need.
# This introduces an issue; In this script we loop over all platforms from `meta` and add the RID flag for it, as to fetch all required dependencies.
# The script would inherit the RID flag from the derivation based on the platform building the script, and set the flag for any iteration we do over the RIDs.
···
in
builtins.filter (flag: !(hasRid flag)) (dotnetFlags ++ dotnetRestoreFlags);
in
writeShellScript "fetch-${pname}-deps" ''
set -euo pipefail
···
export DOTNET_NOLOGO=1
export DOTNET_CLI_TELEMETRY_OPTOUT=1
for rid in "${lib.concatStringsSep "\" \"" runtimeIds}"; do
-
for project in "${lib.concatStringsSep "\" \"" ((lib.toList projectFile) ++ lib.optionals (testProjectFile != "") (lib.toList testProjectFile))}"; do
-
dotnet restore "$project" \
-
-p:ContinuousIntegrationBuild=true \
-
-p:Deterministic=true \
-
--packages "$HOME/nuget_pkgs" \
-
--runtime "$rid" \
-
${lib.optionalString (!enableParallelBuilding) "--disable-parallel"} \
-
${lib.optionalString (flags != []) (toString flags)}
done
done
···
, ...
} @ args:
# 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 by running the `passthru.fetch-deps` script.";
···
# Because this list is rather long its put in its own store path to maintain readability of the generated script
exclusions = writeText "nuget-package-exclusions" (lib.concatStringsSep "\n" (dotnet-sdk.passthru.packages { fetchNuGet = attrs: attrs.pname; }));
# Derivations may set flags such as `--runtime <rid>` based on the host platform to avoid restoring/building nuget dependencies they dont have or dont need.
# This introduces an issue; In this script we loop over all platforms from `meta` and add the RID flag for it, as to fetch all required dependencies.
# The script would inherit the RID flag from the derivation based on the platform building the script, and set the flag for any iteration we do over the RIDs.
···
in
builtins.filter (flag: !(hasRid flag)) (dotnetFlags ++ dotnetRestoreFlags);
+
runtimeIds = map (system: dotnet-sdk.systemToDotnetRid system) (args.meta.platforms or dotnet-sdk.meta.platforms);
in
writeShellScript "fetch-${pname}-deps" ''
set -euo pipefail
···
export DOTNET_NOLOGO=1
export DOTNET_CLI_TELEMETRY_OPTOUT=1
+
declare -a projectFiles=( ${toString (lib.toList projectFile)} )
+
declare -a testProjectFiles=( ${toString (lib.toList testProjectFile)} )
+
+
dotnetRestore() {
+
local -r project="''${1-}"
+
local -r rid="''${2-}"
+
+
dotnet restore ''${project-} \
+
-p:ContinuousIntegrationBuild=true \
+
-p:Deterministic=true \
+
--packages "$HOME/nuget_pkgs" \
+
--runtime "$rid" \
+
${lib.optionalString (!enableParallelBuilding) "--disable-parallel"} \
+
${lib.optionalString (flags != []) (toString flags)}
+
}
+
for rid in "${lib.concatStringsSep "\" \"" runtimeIds}"; do
+
(( ''${#projectFiles[@]} == 0 )) && dotnetRestore "" "$rid"
+
+
for project in ''${projectFiles[@]-} ''${testProjectFiles[@]-}; do
+
dotnetRestore "$project" "$rid"
done
done
+18 -12
pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-build-hook.sh
···
local -r versionFlag="-p:Version=${version-}"
fi
for project in ${projectFile[@]} ${testProjectFile[@]-}; do
-
env \
-
dotnet build "$project" \
-
-maxcpucount:$maxCpuFlag \
-
-p:BuildInParallel=$parallelBuildFlag \
-
-p:ContinuousIntegrationBuild=true \
-
-p:Deterministic=true \
-
-p:UseAppHost=true \
-
--configuration "@buildType@" \
-
--no-restore \
-
${versionFlag-} \
-
${dotnetBuildFlags[@]} \
-
${dotnetFlags[@]}
done
runHook postBuild
···
local -r versionFlag="-p:Version=${version-}"
fi
+
dotnetBuild() {
+
local -r project="${1-}"
+
env dotnet build ${project-} \
+
-maxcpucount:$maxCpuFlag \
+
-p:BuildInParallel=$parallelBuildFlag \
+
-p:ContinuousIntegrationBuild=true \
+
-p:Deterministic=true \
+
-p:UseAppHost=true \
+
--configuration "@buildType@" \
+
--no-restore \
+
${versionFlag-} \
+
${dotnetBuildFlags[@]} \
+
${dotnetFlags[@]}
+
}
+
+
(( "${#projectFile[@]}" == 0 )) && dotnetBuild
+
for project in ${projectFile[@]} ${testProjectFile[@]-}; do
+
dotnetBuild "$project"
done
runHook postBuild
+14 -8
pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-configure-hook.sh
···
local -r parallelFlag="--disable-parallel"
fi
for project in ${projectFile[@]} ${testProjectFile[@]-}; do
-
env \
-
dotnet restore "$project" \
-
-p:ContinuousIntegrationBuild=true \
-
-p:Deterministic=true \
-
--source "@nugetSource@/lib" \
-
${parallelFlag-} \
-
${dotnetRestoreFlags[@]} \
-
${dotnetFlags[@]}
done
runHook postConfigure
···
local -r parallelFlag="--disable-parallel"
fi
+
dotnetRestore() {
+
local -r project="${1-}"
+
env dotnet restore ${project-} \
+
-p:ContinuousIntegrationBuild=true \
+
-p:Deterministic=true \
+
--source "@nugetSource@/lib" \
+
${parallelFlag-} \
+
${dotnetRestoreFlags[@]} \
+
${dotnetFlags[@]}
+
}
+
+
(( "${#projectFile[@]}" == 0 )) && dotnetRestore
+
for project in ${projectFile[@]} ${testProjectFile[@]-}; do
+
dotnetRestore "$project"
done
runHook postConfigure
+38 -22
pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-install-hook.sh
···
dotnetInstallFlags+=("--no-self-contained")
fi
-
for project in ${projectFile[@]}; do
-
env \
-
dotnet publish "$project" \
-
-p:ContinuousIntegrationBuild=true \
-
-p:Deterministic=true \
-
-p:UseAppHost=true \
-
--output "$out/lib/${pname}" \
-
--configuration "@buildType@" \
-
--no-build \
-
${dotnetInstallFlags[@]} \
-
${dotnetFlags[@]}
-
done
-
if [[ "${packNupkg-}" ]]; then
for project in ${projectFile[@]}; do
-
env \
-
dotnet pack "$project" \
-
-p:ContinuousIntegrationBuild=true \
-
-p:Deterministic=true \
-
--output "$out/share" \
-
--configuration "@buildType@" \
-
--no-build \
-
${dotnetPackFlags[@]} \
-
${dotnetFlags[@]}
done
fi
runHook postInstall
···
dotnetInstallFlags+=("--no-self-contained")
fi
+
dotnetPublish() {
+
local -r project="${1-}"
+
env dotnet publish ${project-} \
+
-p:ContinuousIntegrationBuild=true \
+
-p:Deterministic=true \
+
-p:UseAppHost=true \
+
--output "$out/lib/${pname}" \
+
--configuration "@buildType@" \
+
--no-build \
+
${dotnetInstallFlags[@]} \
+
${dotnetFlags[@]}
+
}
+
dotnetPack() {
+
local -r project="${1-}"
+
env dotnet pack ${project-} \
+
-p:ContinuousIntegrationBuild=true \
+
-p:Deterministic=true \
+
--output "$out/share" \
+
--configuration "@buildType@" \
+
--no-build \
+
${dotnetPackFlags[@]} \
+
${dotnetFlags[@]}
+
}
+
+
if (( "${#projectFile[@]}" == 0 )); then
+
dotnetPublish
+
else
for project in ${projectFile[@]}; do
+
dotnetPublish "$project"
done
+
fi
+
+
if [[ "${packNupkg-}" ]]; then
+
if (( "${#projectFile[@]}" == 0 )); then
+
dotnetPack
+
else
+
for project in ${projectFile[@]}; do
+
dotnetPack "$project"
+
done
+
fi
fi
runHook postInstall