DotNET: Difference between revisions

From NixOS Wiki
imported>Milahu
m fixup NETSDK1013, project will build only on Windows
imported>Milahu
m fixup NETSDK1013, project will build only on Windows
Line 126: Line 126:


See : https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#net-sdk-and-cli-environment-variables
See : https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#net-sdk-and-cli-environment-variables
== No .NET SDKs were found ==
Fix:
<syntaxHighlight lang=nix>
  nativeBuildInputs = [
    # ...
    dotnet-sdk
  ];
</syntaxHighlight>


== TargetFramework value was not recognized ==
== TargetFramework value was not recognized ==

Revision as of 15:55, 24 April 2023

.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}";
};

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

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