Hacker News .hnnew | past | comments | ask | show | jobs | submitlogin

You're very kind, thank you

For others wanting to play along at home:

  $ docker run --name net8 --rm -it mcr.microsoft.com/dotnet/sdk:8.0-jammy-arm64v8 bash -c '
  cd /root
  dotnet new -d -o console0 console
  cd console0
  dotnet publish --nologo --self-contained -v d -r osx-arm64 -o console0-darwin-arm64
  sleep 600
  '
although it didn't shake out

  $ docker cp net8:/root/console0/console0-darwin-arm64/console0 ./console0
  $ ./console0
  Killed: 9
I tried with and without --self-contained and the biggest difference was that self-contained emitted a bazillion .dll files and without just emitted the binary. I case the context isn't obvious, $(dotnet new console) is a skeleton for the infamous WriteLine("Hello, World") without doing crazy whacko stuff


For simple JIT-based but fully self-contained binaries, without adding any properties to .csproj, the command is a bit mouthful and is as follows

    dotnet publish -p:PublishSingleFile=true -p:PublishTrimmed=true -o {folder}
(you can put -p: arguments in .csproj too as XML attrs in <PropertyGroup>...)

This will give you JIT-based "trimmed" binary (other languages call it tree shaking). You don't need to specify RID explicitly unless it's different from the one you are currently using.

For simple applications, publishing as AOT (without opting in the csproj for that) is

    dotnet publish -p:PublishAot=true -o {folder}
Add -p:OptimizationPreference=Speed and -p:IlcInstructionSet=native to taste.

Official docs: https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-p...


You're also very kind, and I realized that it's possible there were a bazillion "watch out"s on the docs and was just trying the <PublishAot>true trick when I saw your comment

However, it seems this brings my docker experiment to an abrupt halt, and is going to be some Holy Fucking Shit to re-implement that $(for GOOS) loop in any hypothetical CI system given the resulting explosion

  /usr/bin/sh: 2: /tmp/MSBuildTemproot/tmp194e0a13157b47889b36abb0ce96cd2d.exec.cmd: xcodebuild: not found


You need an OS for which you are building to be able to compile an AOT binary - it depends on OS-provided tooling (MSVC on Windows, Clang on macOS and Linux, and a system-provided linker from each respective system). In fact, once ILC is done compiling IL to .a or .lib, the native linker will just link together the csharp static lib, a GC, then runtime/PAL/misc and a couple of system dependencies into a final executable (you can also make a native library with this).

Cross-architecture compilation is, however, supported (but requires the same extra dependencies as e.g. Rust).

If you just want to publish for every target from a single docker container (you can't easily do that with e.g. Rust as noted), then you can go with JIT+single-file using the other command.

Keep in mind that Go makes concessions in order for cross-compile to work, and invested extra engineering effort in that, while .NET makes emitting "canonical" native binaries using specific system environment a priority and also cares a lot about JIT instead (there aren't that many people working on .NET compiler infrastructure, so it effectively punches above its weight bypassing Go and Java and matching C++ if optimized).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: