I’m trying to package and run a self-contained .NET 8 application using Nix flakes. I tried both single-file and multi-file deployments. The idea is to build a flake that will include my binary. I’m currently testing with a simple project (here is the link: GitHub - nasdvoya/test: test), but later on, I will use the “real” one. The only condition is that I can’t share the source code, so I believe buildDotnetModule is not an option.
Is it simply not possible to build a derivation for precompiled .NET binaries due to the way dynamic linking works? Or am I missing something obvious? I’ve tried pretty much every possible variation.
Single-file deployment:
dotnet publish simple.csproj --configuration Release --output ./great \
--self-contained True --runtime linux-x64 \
--verbosity minimal \
/property:PublishSingleFile=True \
/property:IncludeNativeLibrariesForSelfExtract=True \
/property:AssemblyName=simple
Multi-file deployment:
dotnet publish --configuration Release --output ./great \
--self-contained true --runtime linux-x64
Case 1: Single-file Deployment Flake
{
description = "A simple flake example for Simple";
inputs = { nixpkgs.url = "github:NixOS/nixpkgs"; };
outputs = { self, nixpkgs }: {
packages.x86_64-linux = let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
dynamicLinker = pkgs.stdenv.cc.bintools.dynamicLinker;
rpath = pkgs.lib.strings.makeLibraryPath [
pkgs.stdenv.cc.cc pkgs.icu pkgs.openssl
pkgs.zlib pkgs.libkrb5 pkgs.libunwind pkgs.libuuid
pkgs.icu pkgs.lttng-ust pkgs.lttng-ust_2_12
];
in {
simple = pkgs.stdenv.mkDerivation {
pname = "simple";
version = "1.0";
buildInputs = [
pkgs.dotnet-sdk_8 pkgs.openssl pkgs.zlib pkgs.icu
pkgs.gcc.libc pkgs.libkrb5 pkgs.stdenv.cc.cc.lib
pkgs.lttng-ust pkgs.lttng-ust_2_12
];
src = pkgs.fetchurl {
url = "https://github.com/nasdvoya/test/releases/download/v1.9.9/simple";
sha256 = "0m0bzwmy0r4pmz9w4125gswr10ijm4qlgw3w691ajlp4i4x529vp";
};
unpackPhase = "true"; # Skip unpacking
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/simple
chmod +x $out/bin/simple
'';
postFixup = ''
echo "Patching binary: $out/bin/simple"
patchelf --set-interpreter "${dynamicLinker}" \
--set-rpath '$ORIGIN:${rpath}' $out/bin/simple
'';
meta = with pkgs.lib; {
description = "Simple binary built from release";
license = licenses.mit;
platforms = platforms.linux;
};
};
};
defaultPackage.x86_64-linux = self.packages.x86_64-linux.simple;
defaultApp = { type = "app"; program = "${self.packages.x86_64-linux.simple}/bin/simple"; };
};
}
Running it produces the following output:
nix build
ldd ./result/bin/simple
./result/bin/simple
Failure processing application bundle; possible file corruption.
Arithmetic overflow while reading bundle.
A fatal error occurred while processing application bundle
Case 2: Multi-file Deployment Flake
{
description = "A simple flake example for Simple";
inputs = { nixpkgs.url = "github:NixOS/nixpkgs"; };
outputs = { self, nixpkgs }: {
packages.x86_64-linux = let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
dynamicLinker = pkgs.stdenv.cc.bintools.dynamicLinker;
rpath = pkgs.lib.strings.makeLibraryPath [
pkgs.stdenv.cc.cc pkgs.icu pkgs.openssl
pkgs.zlib pkgs.libkrb5 pkgs.libunwind pkgs.libuuid
pkgs.icu pkgs.lttng-ust pkgs.lttng-ust_2_12
];
in {
simple = pkgs.stdenv.mkDerivation {
pname = "simple";
version = "1.0";
buildInputs = [
pkgs.dotnet-sdk_8 pkgs.openssl pkgs.zlib pkgs.icu
pkgs.gcc.libc pkgs.libkrb5 pkgs.stdenv.cc.cc.lib
pkgs.lttng-ust pkgs.lttng-ust_2_12
];
src = pkgs.fetchurl {
url = "https://github.com/nasdvoya/test/releases/download/v1.9.9/simple.tar.gz";
sha256 = "0hrm0gxxzagwmgkvyp4y6qhjplm6rlpyzbhx2gs6zf0f6hnra0l6";
};
unpackPhase = ''tar -xzf $src'';
installPhase = ''
mkdir -p $out/bin
cp -r * $out/bin/
chmod +x $out/bin/simple
'';
postFixup = ''
echo "Patching binary: $out/bin/simple"
patchelf --set-interpreter "${dynamicLinker}" \
--set-rpath '$ORIGIN:${rpath}' $out/bin/simple
find $out/bin -type f \( -name "*.so" -o -name "simple" \) -exec \
patchelf --set-rpath '$ORIGIN:${rpath}' {} ';'
'';
meta = with pkgs.lib; {
description = "Simple binary built from release";
license = licenses.mit;
platforms = platforms.linux;
};
};
};
defaultPackage.x86_64-linux = self.packages.x86_64-linux.simple;
defaultApp = { type = "app"; program = "${self.packages.x86_64-linux.simple}/bin/simple"; };
};
}
Running it produces the following output:
Failed to load System.Private.CoreLib.dll (error code 0x8007000B)
Path: /nix/store/xyz-simple-1.0/bin/System.Private.CoreLib.dll
Error message: An attempt was made to load a program with an incorrect format.
(0x8007000B)
Failed to create CoreCLR, HRESULT: 0x8007000B