Is a good thread for some previous discussion.
The big parts you’ve missed are “task management” and “exception handling”, as well as I/O. All of these are handled by the runtime as well, and without that, there’s no threading, there’s no printing (sort of), there’s no REPL, there’s no strings/arrays (due to allocations).
The truth of the matter is - the runtime does SO MUCH work for you in the background and enables so many different things that running without one is basically only possible in extremely limited circumstances. One such examples are the prototypical usecases in StaticCompiler, another is microcontrollers (where I am currently working on getting a tiny minimal “runtime”, consisting of nothing more than an allocator, to at least be able to have some global variables and an array). The reason there’s basically no middle ground is because the various features the runtime provides are all depending on each other - you need allocations for everything, in some form or another, to be able to even build a string you’d use in an error message. You need strings and arrays to be able to spawn a new task,and you need to be able to throw exceptions in case the task couldn’t be spawned.
And this doesn’t even get into what you need for dynamic dispatch! In general, that requires the compiler in its full capacity (though you could compile only a subset and fatally crash if you’d have to compile something new).
So in the end, either you’re programming in a very restrictive environment already (embedded) and can afford to implement things “just right”, or you’re going to need large parts of a runtime, in order to be able to use existing libraries more or less as-is in your static binary.
I’d love to also link my talk from JuliaCon about compiling some Julia code to an Arduino (which covers some of the hard parts of the extreme embedded side), but it seems something has gone wrong in the video processing pipeline and it’s not yet uploaded as a standalone video. If you want to look for it, it’s in the recording of the second day of 26-100, somewhere around the 5:30 mark if I’m not mistaken. I’ll edit the video in here once it’s standalone.
EDIT: It’s uploaded now!
The general TL;DR though is “this is just really big and complicated work, that runs into assumptions that were made in the past and edge cases of the current pipeline that are not easy to solve”.