3 ms·
As someone who is "C# curious," but haven't been able to keep up with all the horrific number of rebrands of the "new, open, .net, core, framework", what is the
by mdaniel 3y ago
As someone who is "C# curious," but haven't been able to keep up with all the horrific number of rebrands of the "new, open, .net, core, framework", what is the C# equivalent of $(for GOOS in linux darwin; do for GOARCH in amd64 arm64; do dotnet build -o thing_${GOOS}-${GOARCH}; done; done)?
- nrr 3y agoThat's spelled `dotnet publish -r ${GOOS}-${GOARCH}` with the new ahead-of-time (branded Native AOT) compilation features installed and enabled. It isn't without a whole list of caveats if you're used to Go's way of doing things though. See <https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ https://learn.microsoft.com/en-us/dotnet/core/deploying/nati...> for details.
- mdaniel 3y agoYou'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
- neonsunset 3y agoFor 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-publish#examples https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-p...
- mdaniel 3y agoYou'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
- neonsunset 3y agoYou 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).
- neonsunset 3y agoThe sibling comment pretty much sums it up. But if you want more detail, read on: Generally, there are three publishing options that each make sense depending on scenario: JIT + host runtime: by definition portable, includes slim launcher executable for convenience, the platform for which can be specified with e.g. -r osx-arm64[0]. JIT + self-contained runtime: this includes IL assemblies and runtime together, either within a single file or otherwise (so it looks like AOT, just one bin/exe). This requires specifying RID, like in the previous option, for cross-compilation. AOT: statically linked native binary, cross-OS compilation is not supported officially[1] because macOS is painful in general, and Windows<->Linux/FreeBSD is a configuration nightmare - IL AOT Compiler depends on Clang or MSVC and a native linker so it is subject to restrictions of those as a start. But it can be done and there are alternate, more focused toolchains, that offer it, like Bflat[1]. If you just want a hello world AOT application, then the shortest path to that is `dotnet new console --aot && dotnet publish -o {folder}`. Otherwise, the options above are selected based on the needs either via build properties or CLI arguments. I don't know which use case you have - let me know if you have something specific in mind ("Just like in Go" may or may not be optimal choice depending on scenario). [0] https://learn.microsoft.com/en-us/dotnet/core/rid-catalog https://learn.microsoft.com/en-us/dotnet/core/rid-catalog [1] https://github.com/bflattened/bflat https://github.com/bflattened/bflat (can also build UEFI binaries, lol)