DotNET: Difference between revisions

Klinger (talk | contribs)
m Category:Languages
Railwhale (talk | contribs)
group into sections, add intro text from wikipedia
 
(8 intermediate revisions by 6 users not shown)
Line 1: Line 1:
From [https://en.wikipedia.org/wiki/.NET Wikipedia]
<blockquote>
The .NET platform (formerly named .NET Core) is a free and open-source, managed computer software framework for Windows, Linux, and macOS operating systems. It is a cross-platform successor to the .NET Framework. The project is mainly developed by Microsoft employees by way of the .NET Foundation and is today released under an MIT License.
</blockquote>
== NativeAOT ==
This is relevant for NixOS only.
[https://github.com/Mic92/nix-ld nix-ld] is needed:
<syntaxHighlight lang=nix>
{
  programs.nix-ld.enable = true;
}
</syntaxHighlight>
Now we will need a bunch of native dependencies. Here's an example of a shell:
<syntaxHighlight lang=nix>
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}";
  '';
}
</syntaxHighlight>
== Global Tools ==
Local installation of .NET global tools is fully supported and preferred when possible - more info [https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools#install-a-local-tool 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 <code>buildDotnetModule</code>. For .NET tools with no source available, or those hard to build from source, <code>buildDotnetGlobalTool</code> is available. See [https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/dotnet.section.md#dotnet-global-tools-dotnet-global-tools dotnet nixpkgs manual] for more info.
Note that Nix-packaged .NET tools use a special wrapper (toggled by <code>useDotnetFromEnv</code> option in <code>buildDotnetModule</code>) 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 <code>dotnet</code> CLI of your wanted SDK version is installed and available.
== Packaging ==
.NET packages can be built with <code>buildDotnetModule</code>
.NET packages can be built with <code>buildDotnetModule</code>


Line 4: Line 64:
Example build file:
Example build file:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix" line="1" start="1">
{ fetchFromGitHub
{
, dotnetCorePackages
  buildDotnetModule,
, buildDotnetModule
  dotnetCorePackages,
}:
}:


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


   src = fetchFromGitHub {
   src = ./.;
    owner = "some_owner";
    repo = pname;
    rev = "v${version}";
    hash = ""; # use e.g. `nix-prefetch-git`
  };


   projectFile = "SomeProject/SomeProject.csproj";
   projectFile = "Hello/Hello.csproj";
   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 = ./deps.nix; # to generate, set to `""`, then `nix-build -A fetch-deps && ./result`
   nugetDeps = ./deps.json;
 
  meta = with lib; {
    homepage = "some_homepage";
    description = "some_description";
    license = licenses.mit;
  };
}
}


</syntaxhighlight>
</syntaxhighlight>


If the <code>fetch-deps</code> script isn't working for whatever reason, you can manually run <code>nuget-to-nix</code>:
If the <code>fetch-deps</code> script isn't working for whatever reason, you can manually run <code>nuget-to-json</code>:
<syntaxhighlight lang="sh">
<syntaxhighlight lang="shell-session">
dotnet restore --packages=packageDir ./SomeProject.csproj
$ dotnet restore --packages=packageDir ./SomeProject.csproj
nuget-to-nix packageDir >deps.nix
$ nuget-to-json packageDir > deps.json
rm -r packageDir
$ rm -r packageDir
</syntaxhighlight>
</syntaxhighlight>


Remember to build and run the <code>fetch-deps</code> script after NuGet packages are updated, or building the derivation will fail.
Remember to build and run the <code>fetch-deps</code> script after NuGet packages are updated, or building the derivation will fail.


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


Keep in mind that building projects which don't use the .NET SDK (formerly the .NET Core SDK) and its <code>dotnet</code> CLI tool isn't supported.
Keep in mind that building projects which don't use the .NET SDK (formerly the .NET Core SDK) and its <code>dotnet</code> CLI tool isn't supported.
Line 52: Line 101:
Just remember to add `mono` to `buildInputs` and generate a wrapper script in `postInstall`.
Just remember to add `mono` to `buildInputs` and generate a wrapper script in `postInstall`.


== Packaging ASP.NET projects ==
=== Packaging ASP.NET projects ===


Currently building ASP.NET project as Nix package produces a website that does not work correctly out of the box because the executable can not find <code>wwwroot</code>, so all the static assets won't load with 404.
Currently building ASP.NET project as Nix package produces a website that does not work correctly out of the box because the executable can not find <code>wwwroot</code>, so all the static assets won't load with 404.
Line 117: Line 166:
See also: setting up SSL certificates using [[ACME]]
See also: setting up SSL certificates using [[ACME]]


== .NET location: Not found ==


If running a .NET-build executable you get the above error, make sure the DOTNET_ROOT environment variable is set:
== Examples ==
<syntaxHighlight lang=nix>
environment.sessionVariables = {
  DOTNET_ROOT = "${pkgs.dotnet-sdk}";
};
</syntaxHighlight>


See : https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#net-sdk-and-cli-environment-variables
=== Running Rider with dotnet & PowerShell ===
Rider has better compatibility when run in FHS mode


== TargetFramework value was not recognized ==
Rider package<syntaxhighlight lang="nix">
pkgs.jetbrains.rider
</syntaxhighlight>rider-fhs.nix<syntaxhighlight lang="nix">
{ pkgs ? import <nixpkgs> {} }:


<blockquote>
(pkgs.buildFHSEnv {
  name = "rider-env";
  targetPkgs = pkgs: (with pkgs; [
    dotnetCorePackages.dotnet_8.sdk
    dotnetCorePackages.dotnet_8.aspnetcore
    powershell
  ]);
  multiPkgs = pkgs: (with pkgs; [
  ]);
  runScript = "nohup rider &";
}).env
</syntaxhighlight>


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.
<syntaxhighlight lang="nix">
nix-shell ./rider-fhs.nix
</syntaxhighlight>


</blockquote>
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.


Wontfix: The project will build only on Windows.
<syntaxhighlight>
run-rider = "nix-shell ~/nix/rider-fhs.nix";
</syntaxhighlight>


== NativeAOT ==
=== Multi-SDK installation with local workload installation enabled ===


This is relevant for NixOS only.
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.


[https://github.com/Mic92/nix-ld nix-ld] is needed:
Please visit the [https://discourse.nixos.org/t/dotnet-maui-workload/20370/10 forum] for an example of a multi-SDK installation with workload changed to install to home directory.
<syntaxHighlight lang=nix>
{
  programs.nix-ld.enable = true;
}
</syntaxHighlight>


Now we will need a bunch of native dependencies. Here's an example of a shell:
<syntaxHighlight lang=nix>
with import <nixpkgs> {};
pkgs.mkShell rec {


  dotnetPkg =
    (with dotnetCorePackages; combinePackages [
      sdk_7_0
    ]);


  deps = [
== Troubleshooting ==
    zlib
    zlib.dev
    openssl
    dotnetPkg
  ];


  NIX_LD_LIBRARY_PATH = lib.makeLibraryPath ([
=== .NET location: Not found ===
    stdenv.cc.cc
  ] ++ deps);
  NIX_LD = "${pkgs.stdenv.cc.libc_bin}/bin/ld.so";
  nativeBuildInputs = [
  ] ++ deps;


  shellHook = ''
If running a .NET-build executable you get the above error, make sure the DOTNET_ROOT environment variable is set:
    DOTNET_ROOT="${dotnetPkg}";
<syntaxhighlight lang="nix">
  '';
environment.sessionVariables = {
}
  DOTNET_ROOT = "${pkgs.dotnet-sdk}/share/dotnet/";
</syntaxHighlight>
};
</syntaxhighlight>


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


Local installation of .NET global tools is fully supported and preferred when possible - more info [https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools#install-a-local-tool in the Microsoft docs].
=== TargetFramework value was not recognized ===


For globally installing .NET tools, search if they are available as Nix packages - they are packaged as any other normal
<blockquote>
.NET binary, using <code>buildDotnetModule</code>. For .NET tools with no source available, or those hard to build from source, <code>buildDotnetGlobalTool</code> is available. See [https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/dotnet.section.md#dotnet-global-tools-dotnet-global-tools dotnet nixpkgs manual] for more info.


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


</blockquote>


== Example: Running Rider with dotnet & PowerShell ==
Wontfix: The project will build only on Windows.


Rider package
=== Unable to find package ===


<syntaxHighlight lang=nix>
<blockquote>
pkgs.jetbrains.rider
</syntaxHighlight>


dotnet.nix
error NU1101: Unable to find package runtime.any.System.Collections. No packages exist with this id in source(s): nugetSource


<syntaxHighlight lang=nix>
</blockquote>
with import <nixpkgs> {};


mkShell {
Unsure what specific situations cause this, probably has something to do with .NET Standard libraries.
  name = "dotnet-env";
  packages = [
    (with dotnetCorePackages; combinePackages [
      sdk_6_0
      sdk_7_0
      sdk_8_0
    ])
    powershell
  ];
}
</syntaxHighlight>


To execute Rider
The workaround is modifying the bits that generate nuget-deps.nix:


<syntaxHighlight lang=bash>
<syntaxhighlight lang="sh">
nix-shell ./dotnet.nix --run 'nohup rider &'
dotnet restore --packages=packageDir --use-current-runtime ./SomeProject.csproj
</syntaxHighlight>
nuget-to-nix packageDir >deps.nix
rm -r packageDir
</syntaxhighlight>


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`
The new parameter <code>--use-current-runtime</code> requires .NET SDK 8+. I believe what it does is explicitly adding packages missing in this runtime vs .NET Standard to packageDir.


== Example: multi-SDK installation with local workload installation enabled ==
If this still does not work, it might indicate a good time to update target frameworks and dependencies.
 
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 [https://discourse.nixos.org/t/dotnet-maui-workload/20370/10 forum] for an example of a multi-SDK installation with workload changed to install to home directory.


== See also ==
== See also ==
Line 242: Line 265:
* https://learn.microsoft.com/en-us/dotnet/core/introduction
* https://learn.microsoft.com/en-us/dotnet/core/introduction


[[Category: Development]]
 
[[Category:Languages]]
[[Category:Languages]]