2024-08-01 12:58:28 +00:00
{
lib ,
runtimeShell ,
stdenvNoCC ,
callPackage ,
substituteAll ,
writeShellScript ,
makeWrapper ,
dotnetCorePackages ,
2024-09-04 04:18:07 +00:00
fetchNupkg ,
2024-08-01 12:58:28 +00:00
nuget-to-nix ,
cacert ,
unzip ,
yq ,
nix ,
2022-08-18 21:24:38 +00:00
} :
2024-08-01 00:18:03 +00:00
let
transformArgs =
finalAttrs :
{
enableParallelBuilding ? true ,
# Flags to pass to `makeWrapper`. This is done to avoid double wrapping.
makeWrapperArgs ? [ ] ,
2021-07-26 22:46:18 +00:00
2024-08-01 00:18:03 +00:00
# Flags to pass to `dotnet restore`.
dotnetRestoreFlags ? [ ] ,
# Flags to pass to `dotnet build`.
dotnetBuildFlags ? [ ] ,
# Flags to pass to `dotnet test`, if running tests is enabled.
dotnetTestFlags ? [ ] ,
# Flags to pass to `dotnet install`.
dotnetInstallFlags ? [ ] ,
# Flags to pass to `dotnet pack`.
dotnetPackFlags ? [ ] ,
# Flags to pass to dotnet in all phases.
dotnetFlags ? [ ] ,
2021-07-26 22:46:18 +00:00
2024-08-01 00:18:03 +00:00
# The path to publish the project to. When unset, the directory "$out/lib/$pname" is used.
installPath ? null ,
# The binaries that should get installed to `$out/bin`, relative to `$installPath/`. These get wrapped accordingly.
# Unfortunately, dotnet has no method for doing this automatically.
# If unset, all executables in the projects root will get installed. This may cause bloat!
executables ? null ,
# Packs a 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`.
packNupkg ? false ,
# 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 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.
# Since we are sharing them as nugets they must be added to csproj/fsproj files as `PackageReference` as well.
# For example, your project has a local dependency:
# <ProjectReference Include="../foo/bar.fsproj" />
# To enable discovery through `projectReferences` you would need to add a line:
# <ProjectReference Include="../foo/bar.fsproj" />
# <PackageReference Include="bar" Version="*" Condition=" '$(ContinuousIntegrationBuild)'=='true' "/>
projectReferences ? [ ] ,
# Libraries that need to be available at runtime should be passed through this.
# These get wrapped into `LD_LIBRARY_PATH`.
runtimeDeps ? [ ] ,
# The dotnet runtime ID. If null, fetch-deps will gather dependencies for all
# platforms in meta.platforms which are supported by the sdk.
runtimeId ? null ,
2021-07-26 22:46:18 +00:00
2024-08-22 16:05:19 +00:00
# Test filters. This gets passed to `dotnet test --filter`, concatenated using `&`.
# You may also use `disabledTests` to filter tests based on their name.
# See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test#filter-option-details for more details.
testFilters ? [ ] ,
2024-08-01 00:18:03 +00:00
# Tests to disable. This gets passed to `dotnet test --filter "FullyQualifiedName!={}"`, to ensure compatibility with all frameworks.
2024-08-22 16:05:19 +00:00
# You may also use `testFilters` to pass more generic filters to `dotnet test --filter`.
2024-08-01 00:18:03 +00:00
# See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test#filter-option-details for more details.
disabledTests ? [ ] ,
# The project file to run unit tests against. This is usually referenced in the regular project file, but sometimes it needs to be manually set.
# It gets restored and build, but not installed. You may need to regenerate your nuget lockfile after setting this.
testProjectFile ? null ,
2024-06-15 19:53:16 +00:00
2024-08-01 00:18:03 +00:00
# The type of build to perform. This is passed to `dotnet` with the `--configuration` flag. Possible values are `Release`, `Debug`, etc.
buildType ? " R e l e a s e " ,
# If set to true, builds the application as a self-contained - removing the runtime dependency on dotnet
selfContainedBuild ? false ,
# 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 enabled
useAppHost ? true ,
# The dotnet SDK to use.
dotnet-sdk ? dotnetCorePackages . sdk_6_0 ,
# The dotnet runtime to use.
dotnet-runtime ? dotnetCorePackages . runtime_6_0 ,
. . .
} @ args :
let
projectFiles = lib . optionals ( projectFile != null ) ( lib . toList projectFile ) ;
testProjectFiles = lib . optionals ( testProjectFile != null ) ( lib . toList testProjectFile ) ;
platforms =
if args ? meta . platforms then
lib . intersectLists args . meta . platforms dotnet-sdk . meta . platforms
else
dotnet-sdk . meta . platforms ;
inherit ( callPackage ./hooks { inherit dotnet-sdk dotnet-runtime ; } )
dotnetConfigureHook
dotnetBuildHook
dotnetCheckHook
dotnetInstallHook
dotnetFixupHook
;
_nugetDeps =
if ( nugetDeps != null ) then
if lib . isDerivation nugetDeps then
2024-09-04 04:18:07 +00:00
[ nugetDeps ]
else if lib . isList nugetDeps then
2024-08-01 00:18:03 +00:00
nugetDeps
else
2024-09-04 04:18:07 +00:00
assert ( lib . isPath nugetDeps ) ;
callPackage nugetDeps { fetchNuGet = fetchNupkg ; }
2024-08-01 00:18:03 +00:00
else
2024-09-04 04:18:07 +00:00
[ ] ;
2024-08-01 00:18:03 +00:00
2024-09-04 04:18:07 +00:00
nugetDepsFile = if lib . isPath nugetDeps then nugetDeps else null ;
2024-08-01 00:18:03 +00:00
inherit ( dotnetCorePackages ) systemToDotnetRid ;
in
# Not all args need to be passed through to mkDerivation
# TODO: We should probably filter out even more attrs
2024-09-04 01:49:22 +00:00
removeAttrs args [
" n u g e t D e p s "
" i n s t a l l P a t h "
" e x e c u t a b l e s "
" p r o j e c t F i l e "
" p r o j e c t R e f e r e n c e s "
" r u n t i m e D e p s "
" r u n t i m e I d "
" d i s a b l e d T e s t s "
" t e s t P r o j e c t F i l e "
" b u i l d T y p e "
" s e l f C o n t a i n e d B u i l d "
" u s e D o t n e t "
" u s e A p p H o s t "
]
2024-08-01 00:18:03 +00:00
// {
dotnetInstallPath = installPath ;
dotnetExecutables = executables ;
dotnetBuildType = buildType ;
dotnetProjectFiles = projectFiles ;
dotnetTestProjectFiles = testProjectFiles ;
2024-08-22 16:05:19 +00:00
dotnetTestFilters = testFilters ;
2024-08-01 00:18:03 +00:00
dotnetDisabledTests = disabledTests ;
dotnetRuntimeIds = lib . singleton (
if runtimeId != null then runtimeId else systemToDotnetRid stdenvNoCC . hostPlatform . system
) ;
dotnetRuntimeDeps = map lib . getLib runtimeDeps ;
dotnetSelfContainedBuild = selfContainedBuild ;
dotnetUseAppHost = useAppHost ;
2024-09-04 01:49:22 +00:00
inherit
enableParallelBuilding
dotnetRestoreFlags
dotnetBuildFlags
dotnetTestFlags
dotnetInstallFlags
dotnetPackFlags
dotnetFlags
packNupkg
useDotnetFromEnv
;
2024-09-03 19:57:51 +00:00
2024-08-01 00:18:03 +00:00
nativeBuildInputs = args . nativeBuildInputs or [ ] ++ [
dotnetConfigureHook
dotnetBuildHook
dotnetCheckHook
dotnetInstallHook
dotnetFixupHook
cacert
makeWrapper
dotnet-sdk
unzip
yq
] ;
2024-09-04 04:18:07 +00:00
buildInputs = args . buildInputs or [ ] ++ [ dotnet-sdk . packages ] ++ _nugetDeps ++ projectReferences ;
2024-08-01 00:18:03 +00:00
# Parse the version attr into a format acceptable for the Version msbuild property
# The actual version attr is saved in InformationalVersion, which accepts an arbitrary string
versionForDotnet =
if ! ( lib . hasAttr " v e r s i o n " args ) || args . version == null then
2024-08-01 12:58:28 +00:00
null
else
let
2024-08-01 00:18:03 +00:00
components = lib . pipe args . version [
lib . splitVersion
( lib . filter ( x : ( lib . strings . match " [ 0 - 9 ] + " x ) != null ) )
( lib . filter ( x : ( lib . toIntBase10 x ) < 65535 ) ) # one version component in dotnet has to fit in 16 bits
] ;
in
if ( lib . length components ) == 0 then
null
else
lib . concatStringsSep " . " (
( lib . take 4 components )
++ ( if ( lib . length components ) < 4 then lib . replicate ( 4 - ( lib . length components ) ) " 0 " else [ ] )
2024-08-01 12:58:28 +00:00
) ;
2024-08-01 00:18:03 +00:00
makeWrapperArgs = args . makeWrapperArgs or [ ] ++ [
" - - p r e f i x "
" L D _ L I B R A R Y _ P A T H "
" : "
" ${ dotnet-sdk . icu } / l i b "
] ;
2024-08-01 12:58:28 +00:00
2024-08-01 00:18:03 +00:00
# Stripping breaks the executable
dontStrip = args . dontStrip or true ;
# gappsWrapperArgs gets included when wrapping for dotnet, as to avoid double wrapping
dontWrapGApps = args . dontWrapGApps or true ;
# propagate the runtime sandbox profile since the contents apply to published
# executables
propagatedSandboxProfile = toString dotnet-runtime . __propagatedSandboxProfile ;
passthru =
{
nugetDeps = _nugetDeps ;
}
2024-09-04 04:18:07 +00:00
// lib . optionalAttrs ( nugetDeps == null || lib . isPath nugetDeps ) {
2024-08-01 00:18:03 +00:00
fetch-deps =
let
pkg = finalAttrs . finalPackage . overrideAttrs (
old :
{
2024-09-04 04:18:07 +00:00
buildInputs = lib . subtractLists _nugetDeps old . buildInputs ;
2024-08-01 00:18:03 +00:00
keepNugetConfig = true ;
}
// lib . optionalAttrs ( runtimeId == null ) {
dotnetRuntimeIds = map ( system : systemToDotnetRid system ) platforms ;
}
) ;
drv = builtins . unsafeDiscardOutputDependency pkg . drvPath ;
innerScript = substituteAll {
src = ./fetch-deps.sh ;
isExecutable = true ;
defaultDepsFile =
# Wire in the nugetDeps file such that running the script with no args
# runs it agains the correct deps file by default.
# Note that toString is necessary here as it results in the path at
# eval time (i.e. to the file in your local Nixpkgs checkout) rather
# than the Nix store path of the path after it's been imported.
2024-09-04 04:18:07 +00:00
if lib . isPath nugetDeps && ! lib . isStorePath nugetDepsFile then
2024-08-01 00:18:03 +00:00
toString nugetDepsFile
else
2024-09-13 06:12:08 +00:00
'' $( m k t e m p - t " ${ finalAttrs . pname or finalAttrs . finalPackage . name } - d e p s - X X X X X X . n i x " ) '' ;
2024-08-01 00:18:03 +00:00
nugetToNix = ( nuget-to-nix . override { inherit dotnet-sdk ; } ) ;
} ;
in
2024-09-04 01:49:22 +00:00
writeShellScript " ${ finalAttrs . finalPackage . name } - f e t c h - d e p s " ''
2024-08-01 00:18:03 +00:00
NIX_BUILD_SHELL = " ${ runtimeShell } " exec $ { nix } /bin/nix-shell \
- - pure - - run ' source " ${ innerScript } " ' " ${ drv } "
'' ;
}
// args . passthru or { } ;
meta = ( args . meta or { } ) // {
inherit platforms ;
} ;
2024-08-01 12:58:28 +00:00
} ;
2024-08-01 00:18:03 +00:00
in
fnOrAttrs :
stdenvNoCC . mkDerivation (
finalAttrs :
let
args = if lib . isFunction fnOrAttrs then fnOrAttrs ( args // finalAttrs ) else fnOrAttrs ;
in
transformArgs finalAttrs args
2024-08-01 12:58:28 +00:00
)