A good source of truth for an actual executable would be Native AOT binary, which can run on Windows, Linux or macOS. Naturally, it will be much larger, having to incorporate GC, possibly ThreadPool, Console and other auxiliary code.
A good source of truth for an actual executable would be Native AOT binary, which can run on Windows, Linux or macOS. Naturally, it will be much larger, having to incorporate GC, possibly ThreadPool, Console and other auxiliary code.
But anyway, this other article [0] (shared in another comment here) about creating the smallest version of Snake (the game) was done on top of .NET Core (the new version of .NET that isn't bundled with Windows) and effectively does the same thing, but actually produces a non-.NET binary, if that's more to your taste.
[0]: https://medium.com/@MStrehovsky/building-a-self-contained-ga...
except for runtime environment initialization, JIT compilation, and execution.
I think comparing container images would be a good start. Use the most minimal base image you can get away with, or even "FROM scratch" if possible, but compare only images with the same architecture. I'd prefer 32-bit, to take things like running 32-bit on 64-bit or 64-bit with pointer compression out of the picture.
Then compare the size of the uncompressed exported tar. Probably also not completely fair, depending on what question you want to answer but it takes the obvious variances out of the equation.
EDIT: Thinking about it some more, it might even be more fair to compare maximally compressed image size to account for compression within the container. Of course you'd have to compress with the same algorithm and parameters or just add the decompressors size to the final result like they do in compression benchmarks.
Specifically about how C leverages the “free” runtime of the OS while Lisp has to bundle is own.
This idea of container runtime sizes would be an amusing thread. A good test of something like Nix or Guix to a very fine grain. “We don’t need bash or ls so we removed it. “ “The VM only simulate a single network card, so we’ll scrap all the other driver. “
Windows has only recently been moving toward providing a public run-time for C; the "Universal C Run-Time" (UCRT) that has been introduced in Windows 10.
Stdio, no. Printf, no (unless you’re an adherent of LIBCTINY[1] or one of its descendants[2] and need only a minimal set of features). Malloc, yes—MSVC’s malloc() on Win32 has always been a thin wrapper around kernel32!HeapAlloc. Strlen or memcpy or whatnot—also possibly yes, but it’s not like minimal implementations of those are large anyway.
[1] http://bytepointer.com/resources/pietrek_libctiny_1996.htm
echo "hello world"Without actually checking, the result is going to be that the output size increases slightly over time.
The size definitely gets bigger with each iteration:
$ echo text >0.txt
$ for i in {0..9}; do
gzip <$i.txt >$((i + 1)).txt
done
$ ls | sort -n | xargs -n1 wc -c
5 0.txt
25 1.txt
46 2.txt
69 3.txt
82 4.txt
105 5.txt
120 6.txt
143 7.txt
161 8.txt
184 9.txt
207 10.txt cd /tmp
echo 'echo $0' > hello\ world
chmod +x hello\ world
PATH=. hello\ worldI count 18 bytes in that program. Too long!
I left a definitive answer on Quora some years ago:
https://www.quora.com/What-programming-language-has-the-shor...
I'll just observe that there is no way to compress "hello world" below a certain size (definitely not to size 0). If you think you have, you've just "moved" it into, say, the framework/os/input/algorithm/etc.
But this fun little debate we're having here is actually connected to some deep theoretical questions, like Kolmogorov complexity, its invariance theorem, and applications to the concept of data compression [0].
Hello World
The best example I got off the top of my head is KeePass v1 [0] and KeePass v2 [1]. v1 is written in C++ with native controls, and v2 uses Windows Forms.
If you look at the menu bar and the toolbar, you'll see a difference. Most notably the drag handle on the left, and the search box on the right, in v2. The difference is often a bit easier to spot on Windows 7.
[0]: https://keepass.info/screenshots/main_big.png [1]: https://keepass.info/screenshots/keepass_2x/main_big.png
If you are talking about the base controls, then maybe. But there are .Net cross-platform frameworks such as Avalonia that can get you a modern loooking UI with theming.
https://github.com/irihitech/Semi.Avalonia
https://github.com/AvaloniaUI/Citrus.Avalonia
etc.
It's an odd annoyance that Windows developers have to deal with.
As a user, think about how annoying it is to get a message saying you need to run Windows Update before you can start an application. Totally unnecessary own-goal for the team that decided to ship their independent component in Windows Update.
It's way easier to either 1.) go self-contained, or 2.) use the on-the-fly .NET download for a framework-dependent build. I absolutely think they made the right call removing current .NET as a Windows component. The annoyance was far greater when .NET Framework was part of Windows.
correction: without some specific version of .net.
In theory: yes. In practice: mostly. There can only be one .NET Framework 4 installed at a time; the recent changes are found at https://learn.microsoft.com/en-us/dotnet/framework/whats-new.
> Which version number should I request in my ultraportable executable?
This gets tricky if you want to support more than Microsoft does. Here is the details on recent .NET Framework versions per OS: https://learn.microsoft.com/en-us/dotnet/framework/install/g... and ancient of days: https://learn.microsoft.com/en-us/archive/blogs/astebner/mai....
For example: Microsoft currently supports Windows 10+, which first included .NET Framework 4.6. However, Microsoft only currently supports v4.6.2+, and v4.8 has been "Windows Update"'d since May 2019. I personally bumped an old open source project from v3.5 to v4.8 recently because of how hard it was for myself as a returning contributor to build these days.
If you want the most "ultra-portable" executable for .NET Framework, you could choose 1.1 or 2.0. Picking 1.1 in 2023 is about as silly as picking VB6, it also won't feel just about anything like modern .NET. 2.0 feels a lot more like modern .NET (especially because that's when Generics and Generic Collections first exist), but also not really something I'd recommend in 2023. (But in theory targeting .NET Fx 2.0 gets you ultra-portable all the way back to Windows 98.)
What actually never happened, to nobody's surprise.
So now we have .Net that was renamed into .Net Framework that is legacy, .Net Core that is legacy but compatible with the modern version, and .Net that is current. Anyway, the platform never stopped being called .Net, because it's larger than just the runtime.
We also have 2 different number sequences starting from 1, and one starting from... some times 4, other times 6, depends on your point of view.
We also have a bunch of confused people without any reason, because all of this is as clear as water. But anyway, it's not the author fault that he didn't communicate the version in an adequate way.
This is not correct. .NET Framework was named Framework from 1.0. The only time something was renamed is .NET 5 which came after .NET Core 3.1.
> We also have a bunch of confused people without any reason, because all of this is as clear as water.
It's funny you say that. Do you consider yourself one of those confused people? :)
Yes. I have never took place in a conversation about versioning problems in .Net where each person wasn't talking about completely different things.
Anyway, I clearly remember nobody ever naming anything "framework" until the second or third stable version. And if there was such a thing, I would probably have heard, because MS was incredibly loud at the time.
It was retroactively renamed after it.
I remember back in the day - around 2001 - Microsoft thought it will center all their products around Web Services and call them .NET. Windows .NET Server was the supposed name for Server 2003. In the end a few things came out of it: Visual Studio .NET, .NET (the framework), VB.NET, ASP.NET.
Unless they provide feature parity, it will never happen.
A working WinForms designer for third-party controls (read: any control not provided by the framework itself or NDA-ed vendors) in Visual Studio would be nice, for example.
You can do this for any format that stores executables, for any programming framework. .jar might be interesting, .py obviously isn't. You can do this for obscure old formats, or for something very common like the standard Linux .elf.
Although .zipapp is to Python what .jar is to .py. Probably even closer to .war.
But for purely stand alone stuff, "nuitka3 /tmp/hello.py --standalone" does output a executable that can be used without the user to manually bring in the Python run time. In that case, the hello world is about 16Mb on Ubuntu.
It would be interesting to do this with MicroPython though.
That's fair though. The post is titled "the smallest .NET hello world binary", not "the smallest C# hello world binary"
Display drivers and firmware of various mcus used in the computer monitor itself?
As a matter of OS design, this is no longer obvious:
https://lwn.net/Articles/806776/
> A new mechanism to help thwart return-oriented programming (ROP) and similar attacks has recently been added to the OpenBSD kernel. It will block system calls that are not made via the C library (libc) system-call wrappers.
MacOS doesn't implement that, sure, but it could.