DotNET

From NixOS Wiki
Revision as of 08:58, 14 February 2023 by imported>WhiteBlackGoose (Added a workaround for declarative global .net tool installations)

.NET packages can be built with buildDotnetPackage

Example build file:

/*
some_program/default.nix
nix-build -E 'with import <nixpkgs> { }; callPackage ./default.nix { }'
*/

{ lib
, stdenv
, fetchFromGitHub
, buildDotnetPackage
, dotnetPackages
, pkg-config
}:

buildDotnetPackage rec {
  pname = "some_program";
  baseName = pname; # workaround for "called without baseName"
  version = "some_version";
  src = fetchFromGitHub {
    owner = "some_owner";
    repo = pname;
    rev = "v${version}";
    sha256 = ""; # todo
  };
  projectFile = ["path/to/some_project.csproj"];
  propagatedBuildInputs = [
  ];
  buildInputs = [
    # unit tests
    dotnetPackages.NUnit
    dotnetPackages.NUnitRunners
  ];
  nativeBuildInputs = [
    pkg-config
  ];
  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.

Workaround: in buildPhase, replace xbuild with msbuild

{ lib
# ...
, msbuild
}:

buildDotnetPackage rec {
  # ...
  projectFile = "path/to/some_project.csproj";
  # ...
  buildInputs = [
    msbuild
  ];
  buildPhase = ''
    runHook preBuild
    msbuild /p:Configuration=Release ${projectFile}
    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}";
};

See : https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#net-sdk-and-cli-environment-variables

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

As workaround, 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](https://github.com/dotnet/sdk/issues/30546).

[Here](https://github.com/WhiteBlackGoose/dotfiles/blob/3f7d1b508f75ea87b8f36f3e2be0e2db1f4241c1/envs/dotnet-tool.nix) 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