NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.09k stars 14.14k forks source link

Cross compiling dotnet does not work #291773

Open blazp7 opened 8 months ago

blazp7 commented 8 months ago

Describe the bug

Cross compiling with buildDotnetModule does not work, however dotnet supports it.

Steps To Reproduce

Setup a basic environment, disable boot.binfmt.emulatedSystems = ["aarch64-linux"]; if you have it on

nix shell nixpkgs#dotnetCorePackages.sdk_8_0
mkdir /tmp/dotnet-cross-compile-test && cd /tmp/dotnet-cross-compile-test
dotnet new webapi

create flake.nix

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  outputs = { self, nixpkgs, ... }: {
    packages.x86_64-linux = {
      dotnet-cross-compile-test = nixpkgs.legacyPackages.x86_64-linux.pkgsCross.aarch64-multiplatform.callPackage ./package.nix {};
    };
  };
}

create package.nix

{
  lib,
  buildDotnetModule,
  dotnetCorePackages,
}: let
  projectName = "dotnet-cross-compile-test";
in
  buildDotnetModule {
    NIX_DEBUG = 8;
    nugetDeps = ./deps.nix;
    pname = projectName;
    version = "0.1";
    src = ./.;
    projectFile = ["${projectName}.csproj"];
    dotnet-sdk = dotnetCorePackages.sdk_8_0;
    dotnet-runtime = dotnetCorePackages.aspnetcore_8_0;
    postInstall = ''
      mkdir -p $out/bin
      cp appsettings.json $out/bin/appsettings.json
    '';
    meta = with lib; {
      description = projectName;
      license = licenses.mit;
      maintainers = [];
    };
  }

create deps.nix

{ fetchNuGet }: [
  (fetchNuGet { pname = "Microsoft.AspNetCore.OpenApi"; version = "8.0.1"; sha256 = "1728rx0n1bjzn3ymgsrv9jzv9b26fb7fvb5v44j41wlfm5p39kq3"; })
  (fetchNuGet { pname = "Microsoft.Extensions.ApiDescription.Server"; version = "6.0.5"; sha256 = "1pi2bm3cm0a7jzqzmfc2r7bpcdkmk3hhjfvb2c81j7wl7xdw3624"; })
  (fetchNuGet { pname = "Microsoft.OpenApi"; version = "1.2.3"; sha256 = "07b19k89whj69j87afkz86gp9b3iybw8jqwvlgcn43m7fb2y99rr"; })
  (fetchNuGet { pname = "Microsoft.OpenApi"; version = "1.4.3"; sha256 = "1q21vcxlnxkl6kgi2jn6bnl9nlr8bcs892qx4xbqmhhfpxxknkmy"; })
  (fetchNuGet { pname = "Swashbuckle.AspNetCore"; version = "6.4.0"; sha256 = "1jkgjnkjcb6dif0lzn7whjwwdd4fi6mzkmkdx8sfmv5cffzq4fvk"; })
  (fetchNuGet { pname = "Swashbuckle.AspNetCore.Swagger"; version = "6.4.0"; sha256 = "1wccx8ig2xc6xcfh774m5z34w6jn0hjffiwc5sq9yl63zkv01vnn"; })
  (fetchNuGet { pname = "Swashbuckle.AspNetCore.SwaggerGen"; version = "6.4.0"; sha256 = "1k58j6lfqcgrl5f7dw0xnbq6w5bvr42a9fc44vwbzl52kzjdlnh2"; })
  (fetchNuGet { pname = "Swashbuckle.AspNetCore.SwaggerUI"; version = "6.4.0"; sha256 = "1rxgf0hbkkzywh8z7asky2rrh1gpnrr514v1aj5vnmh49sa31kiz"; })
]

Expected behavior

This should work nix build .#dotnet-cross-compile-test

Because this works

dotnet build --runtime linux-arm64
file bin/Debug/net8.0/linux-arm64/dotnet-cross-compile-test
  -> ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=187ce9140e98c52d0317b17
8e0baa9a8d5658768, stripped

Errors

....
++ find -name paket.dependencies -exec sed -i 's+source .*+source /nix/store/iiyh3nrzk3a1a44mzarjladx88pjygpw-dotnet-cross-compile-test-0.1-nuget-source/lib+g' '{}' ';'++ find -name paket.lock -exec sed -i 's+remote:.*+remote: /nix/store/iiyh3nrzk3a1a44mzarjladx88pjygpw-dotnet-cross-compile-test-0.1-nuget-source/lib+g' '{}' ';'++ env dotnet tool restore --add-source /nix/store/iiyh3nrzk3a1a44mzarjladx88pjygpw-dotnet-cross-compile-test-0.1-nuget-source/lib/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 0: ^A@<F0>^B^A@8^O@!^Y^F^D@@@H^CH
^C^H^A^D<80>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 0: ^AQ<E5>td^FP<E5>td^D<B0>@<B0>@
<B0>@l^Dl^D^D^A^E<80>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 0: ^A<80>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 0: ^F: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 0: ^F^V^A^A^F: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 0: ^D: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 1: ^?ELF^B^A^A^C<B7>^A<80><80><80>^A<80><99><80><99>^A^G^D<FA><FA>^A<FA>^A^H^H^A^F<FA><FA>^B<FA>^B^F^AR<E5>td^D<FA><FA>^B<FA>^B^A^D<D8><FD>^A^A^F^B^E^E8^K8^K^A^C^D<80>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 2: ^B<80>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 3: ^E<80>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 4: ^Enn^A^D^D<F0>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 5: ^B<F0>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 6: ^E<F0>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 7: ^E: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 12: ^B^B^E^B^B^B^B^B^B^B^B^B^D^D^D^K^E^D^D^D^D^E^D^B^B^B^B^B^B^B^B^A^A<C9>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 12: ^P^A^A<E4>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 14: ^P^A^E<EF>: not found
/nix/store/46imqyv3vmkb82izx0kkm3rkcakynaiw-dotnet-sdk-aarch64-unknown-linux-gnu-8.0.101/bin/dotnet: line 22: syntax error: unexpected word (expecting ")")
+ exitHandler
+ exitCode=2

Extra context

Hopefully this is the correct setup for cross compiling, up until now i have been using qemu boot.binfmt.emulatedSystems = ["aarch64-linux"]; however i would like to transition off because it is only working on nix 23.11, not on unstable (gives segfault error)

Notify maintainers

@mdarocha , @corngood , @lilyinstarlight Got names from commit history of build-dotnet-module, sorry if you didnt want to be notified.


Add a :+1: reaction to issues you find important.

corngood commented 8 months ago

This actually does seem to work for me:

with import ./. {
  crossSystem = "aarch64-linux";
};
buildDotnetModule {
  name = "dotnet-sdk-smoke-test";
  nugetDeps = emptyDirectory;
  dotnet-sdk = buildPackages.dotnet-sdk;
  dotnet-runtime = dotnet-runtime;
  unpackPhase = ''
    runHook preUnpack
    dotnet new nugetconfig
    dotnet new console -n test -o .
    runHook postUnpack
  '';
}

Note that even if rewrite this to be called with callPackage, I have to specify buildPackages.dotnet-sdk. I think buildDotnetModule is probably doing some stuff that's incompatible with splicing.