DotNET
.NET packages can be built with buildDotnetPackage
Example build file:
{ lib
, stdenv
, fetchFromGitHub
, buildDotnetPackage
, dotnetPackages
, pkg-config
}:
buildDotnetPackage rec {
pname = "some_program";
version = "some_version";
src = fetchFromGitHub {
owner = "some_owner";
repo = pname;
rev = "v${version}";
sha256 = "";
};
xBuildFiles = [
"SomeProject/SomeProject.csproj"
];
nativeBuildInputs = [
pkg-config
];
buildInputs = [
];
propagatedBuildInputs = [
];
checkInputs = [
dotnetPackages.NUnit
dotnetPackages.NUnitRunners
];
meta = with lib; {
homepage = "some_homepage";
description = "some_description";
license = licenses.mit;
};
}
XML namespace error
xbuild tool is deprecated and will be removed in future updates, use msbuild instead
The default XML namespace of the project must be the MSBuild XML namespace. If the project is authored in the MSBuild 2003 format, please add xmlns="http://schemas.microsoft.com/developer/msbuild/2003" to the <Project> element. If the project has been authored in the old 1.0 or 1.2 format, please convert it to MSBuild 2003 format.
Fix: in buildPhase
, replace xbuild
with msbuild
{ # ...
, msbuild
}:
let
arrayToShell = (a: toString (map (lib.escape (lib.stringToCharacters "\\ ';$`()|<>\t") ) a));
in
buildDotnetPackage rec {
# ...
msBuildFiles = [
"SomeProject/SomeProject.csproj"
];
nativeBuildInputs = [
pkg-config
msbuild
];
msBuildFlags = [
"/p:Configuration=Release"
];
# based on https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/dotnet/build-dotnet-package/default.nix
buildPhase = ''
runHook preBuild
echo Building dotNET packages...
# Probably needs to be moved to fsharp
if pkg-config FSharp.Core
then
export FSharpTargetsPath="$(dirname $(pkg-config FSharp.Core --variable=Libraries))/Microsoft.FSharp.Targets"
fi
ran=""
for msBuildFile in ${arrayToShell msBuildFiles} ''${msBuildFilesExtra}
do
ran="yes"
msbuild ${arrayToShell msBuildFlags} ''${msBuildFlagsArray} $msBuildFile
done
[ -z "$ran" ] && msbuild ${arrayToShell msBuildFlags} ''${msBuildFlagsArray}
runHook postBuild
'';
}
MSBuild reference: https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-command-line-reference?view=vs-2022
.NET location: Not found
set DOTNET_ROOT Environment Variable
environment.sessionVariables = {
DOTNET_ROOT = "${pkgs.dotnet-sdk}";
};
No .NET SDKs were found
Fix:
nativeBuildInputs = [
# ...
dotnet-sdk
];
TargetFramework value was not recognized
error NETSDK1013: The TargetFramework value 'net6.0-windows' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly.
Wontfix: The project will build only on Windows.
Missing NuGet packages
Example error:
error : This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is ../../packages/Microsoft.Bcl.Build.1.0.21/build/Microsoft.Bcl.Build.targets.
These are upstream bugs
Fix: patch all *.csproj
files, to remove all XML tags that contain the "missing file" paths, for example
<Import Project="..\..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
See also https://stackoverflow.com/questions/32254439/nuget-packages-are-missing
NativeAOT
This is relevant for NixOS only.
nix-ld is needed:
{
programs.nix-ld.enable = true;
}
Now we will need a bunch of native dependencies. Here's an example of a shell:
with import <nixpkgs> {};
pkgs.mkShell rec {
dotnetPkg =
(with dotnetCorePackages; combinePackages [
sdk_7_0
]);
deps = [
zlib
zlib.dev
openssl
dotnetPkg
];
NIX_LD_LIBRARY_PATH = lib.makeLibraryPath ([
stdenv.cc.cc
] ++ deps);
NIX_LD = "${pkgs.stdenv.cc.libc_bin}/bin/ld.so";
nativeBuildInputs = [
] ++ deps;
shellHook = ''
DOTNET_ROOT="${dotnetPkg}";
'';
}
Global Tools
There is currently no mechanism to install them globally, and regular (mutable) installation does not work.
Here is a proof of concept of how .NET tools could be used declaratively.
Here's an example of using that package:
packages =
let dotnetPkg =
(with dotnetCorePackages; combinePackages [
sdk_7_0
sdk_6_0
]);
dotnetTools = (callPackage ./dotnet-tool.nix {}); # dotnet-tool.nix is the file from the link above
in [
vim
firefox
dotnetPkg
dotnetTools.combineTools dotnetPkg (with dotnetTools.tools; [
# ^^^^^^^^^ here we specify the dotnet package
# that will be invoked for this tool
# Ideally, something like dotnetPkg.withTools
# should be there
fsautocomplete # these are tools from dotnetTools.tools;
csharp-ls # if a package is missing, it can be declared
dotnet-repl # manually, see the sources of dotnet-tools.nix
])
];
See also
- dotnet in the nixpkgs manual
- nixpkgs/pkgs/top-level/dotnet-packages.nix → look for "SOURCE PACKAGES"
- buildDotnetPackage implementation
- buildDotnetPackage references in nixpkgs
- The journey of packaging a .NET app on Nix
- https://en.wikipedia.org/wiki/.NET_Framework
- https://en.wikipedia.org/wiki/List_of_CLI_languages: C#, F#, Visual Basic, ...
- https://en.wikipedia.org/wiki/Mono_(software) is the open source implementation of the DotNET compiler and runtime