DotNET: Difference between revisions

From NixOS Wiki
Lostmsu (talk | contribs)
m Undo revision 13402 by Lostmsu (talk)
Tag: Undo
Lostmsu (talk | contribs)
nuget-to-nix is much more straightforward to use than fetch-deps script
Line 24: Line 24:
   dotnet-sdk = dotnetCorePackages.sdk_8_0;
   dotnet-sdk = dotnetCorePackages.sdk_8_0;
   dotnet-runtime = dotnetCorePackages.runtime_8_0;
   dotnet-runtime = dotnetCorePackages.runtime_8_0;
   nugetDeps = null; # only if there are NuGet dependencies, real file will be genned later
   nugetDeps = ./nuget-deps.nix; # only if there are NuGet dependencies, real file will be genned later


   meta = with lib; {
   meta = with lib; {
Line 35: Line 35:
</syntaxhighlight>
</syntaxhighlight>


Note that the above package will not build the first time. After adding the above definition to `all-packages.nix`, you
To generate <code>nuget-deps.nix</code> file you can run
can run the package-specific `fetch-deps` script, which will generate a file containing all the nuget dependencies of the
package. Build the script with <code>nix-build -A some-package.fetch-deps</code>, might need to run <code>./result deps.nix</code>, copy that generated file (the location will be printed by the script) and set the <code>nugetDeps</code> attribute in <code>buildDotnetModule</code> to point to that generated file (ie. <code>nugetDeps = ./deps.nix</code>).


After that the package will build normally. Remember to re-run <code>fetch-deps</code> every time the package is updated.
<code>dotnet restore --packages=packageDir SomeProject.csproj && nuget-to-nix packageDir >nuget-deps.nix; rm -rf packageDir</code>
 
After that the package will build normally. Remember to re-run nuget-to-nix every time the package is updated.


== Building non-.NET Core packages ==
== Building non-.NET Core packages ==

Revision as of 06:57, 24 June 2024

.NET packages can be built with buildDotnetModule

More information about buildDotnetModule can be found in the nixpkgs manual Example build file:

{ fetchFromGitHub
, dotnetCorePackages
, buildDotnetModule
}:

buildDotnetModule rec {
  pname = "some_program";
  version = "some_version";

  src = fetchFromGitHub {
    owner = "some_owner";
    repo = pname;
    rev = "v${version}";
    sha256 = ""; # can be figured out from the first build attempt
  };

  projectFile = "SomeProject/SomeProject.csproj";
  dotnet-sdk = dotnetCorePackages.sdk_8_0;
  dotnet-runtime = dotnetCorePackages.runtime_8_0;
  nugetDeps = ./nuget-deps.nix; # only if there are NuGet dependencies, real file will be genned later

  meta = with lib; {
    homepage = "some_homepage";
    description = "some_description";
    license = licenses.mit;
  };
}

To generate nuget-deps.nix file you can run

dotnet restore --packages=packageDir SomeProject.csproj && nuget-to-nix packageDir >nuget-deps.nix; rm -rf packageDir

After that the package will build normally. Remember to re-run nuget-to-nix every time the package is updated.

Building non-.NET Core packages

Keep in mind that building non-.NET Core projects (ie. projects that don't build using the dotnet CLI tool) is not well supported. For those projects, you have to work on a custom derivation or override the buildDotnetModule build steps.

.NET location: Not found

If running a .NET-build executable you get the above error, make sure the DOTNET_ROOT environment variable is set:

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.

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

Local installation of .NET global tools is fully supported and preferred when possible - more info in the Microsoft docs.

For globally installing .NET tools, search if they are available as Nix packages - they are packaged as any other normal .NET binary, using buildDotnetModule. For .NET tools with no source available, or those hard to build from source, buildDotnetGlobalTool is available. See dotnet nixpkgs manual for more info.

Note that Nix-packaged .NET tools use a special wrapper (toggled by useDotnetFromEnv option in buildDotnetModule) that automatically picks up .NET install from the user environment. If you want to use a different SDK version with a Nix-packaged .NET tools than the default, make sure the dotnet CLI of your wanted SDK version is installed and available.


Example: Running Rider with dotnet & PowerShell

Rider package

pkgs.jetbrains.rider

dotnet.nix

with import <nixpkgs> {};

mkShell {
  name = "dotnet-env";
  packages = [
    (with dotnetCorePackages; combinePackages [
      sdk_6_0
      sdk_7_0
      sdk_8_0
    ])
    powershell
  ];
}

To execute Rider

nix-shell ./dotnet.nix --run 'nohup rider &'

This can be added as an alias to your shell if you update the reference to an absolute address, such as location within your home directory. e.g. `~/nix/dotnet.nix`

Example: multi-SDK installation with local workload installation enabled

By default, workload installation will fail on NixOS, as dotnet will attempt to save it to $DOTNET_ROOT, which is inside the read-only Nix store.

Please visit the forum for an example of a multi-SDK installation with workload changed to install to home directory.

See also