I don't know about Go, but Rust doesn't promote it. Rust compiles a whole binary at once (for full program optimisation), but that binary can be a dynamic library or executable. How you then build the operating system on top of that is up to you.
Recently, ripgrep was on the frontpage. It says "Linux binaries are static executables" [0]. If I run ldd on cargo, it spits out the usually glibc dependencies, but Rust libraries are statically linked. It seems to be the default behavior of cargo? I would describe that as "promote static linking".
Personally, I don't judge this as good or bad. There is no simple answer. Static linking has clear disadvantage wrt security patches. On the other hand, it makes little sense to dynamically link tiny libraries, e.g. a queue data structure.
> It says "Linux binaries are static executables" [0].
They are. Running `ldd` on cargo doesn't confirm or deny this. You need to run `ldd` on the binary distributed:
$ curl -sLO 'https://github.com/BurntSushi/ripgrep/releases/download/0.2.1/ripgrep-0.2.1-x86_64-unknown-linux-musl.tar.gz'
$ tar xf ripgrep-0.2.1-x86_64-unknown-linux-musl.tar.gz
$ ldd ./ripgrep-0.2.1-x86_64-unknown-linux-musl/rg
not a dynamic executable
By default, Rust statically links all Rust code. However, glibc isn't usually statically linked, so Rust doesn't either. You can use musl instead of glibc to get 100% statically linked binaries.
The problem here is that the choice is one extreme or the other, never the happy medium.
The extremes are statically linked everything and dynamically linked everything.
Bryan Cantrill deplores this part of the design of Go. He decries the fact that rather than sitting on top of a HLL-function-call binary interface, with the portability layer being HLL function calls like read(), write(), close(), socket(), execve(), Go produces executables that hardwire one specific instruction set's kernel system call traps.
GCC allows one to selectively statically link various libraries in an otherwise dynamically linked executable. (clang had yet to achieve this functionality, last that I checked a year or so ago.)
Bryan would have to elaborate an awful lot on the evilness of using system calls to make that a more general argument. (we're not supposed to use the kernel now for some reason?) It looks like it was just kind of a pain in the ass for the Joyent guys because of what they were doing specifically, which was pretty specialized.
(there's a mean and almost clinically insane blog post about Go by one of the other Joyent guys, who retired a week or two after writing it, which also doesn't shed much light but is funnier. You've got to wonder what their deal is with the Go guys, exactly...)
Yeah, on Linux, the system call interface is the supported interface for interacting with the kernel. Of course we are going to use it since 1) it's supported, 2) it's stable, more stable than e.g. glibc has ever been, not to mention we're not locked to a particular libc vendor, it just works on embedded systems which don't use glibc, 3) it allows us to make system calls without going through all the cgo machinery and without having to switch stacks.
On Solaris, the system call interface is not a supported public interface, so I made the Solaris port use libc through cgo.
Solaris made the decision that the supported public interface is through libc. That's a fine decision to make if you are the sole vendor of libc. But, that doesn't mean there's anything wrong with different operating systems making different decisions.
On Linux we use the Linux rules, and on Solaris we use the Solaris rules.
I will tell you this though, having done numerous Go ports and having written many Go compiler targets several times, it's much, much simpler to port Go if your target is something that allows static executables and making system calls.
Having done linux/arm64 and solaris/sparc64, I know exactly how much harder is one versus the other.
A lot -- maybe not a majority, but a sizeable number of people -- think dynamic linking is potentially exploitable due to its complexity, has real-life deployment problems (e.g. due to applications depending on a specific version of a library, or simply due to complacency in building and distribution) and that the advantages it offered twenty years ago are offset by larger hard drives, better and faster network connectivity, and better updating systems.
In other words, that its cost is no longer as easy to justify as it was back in the 1990s.
I have not studied the problem enough to be able to comment on it in its entirety, but there is at least some merit to a few of these claims:
* Static linking was a huge nuisance back when Unices introduced dynamic linking because keeping a system up to date was a very different affair. There was no apt-get update, apt-get upgrade. The OS vendor (often the hardware manufacturer) would keep his system up to date. For third-party software, you often depended on building programs from source (oh, yes: no autotools/cmake/whatever to deal with junk Makefiles, either, although this was partly offset by the fact that a lot of developers still knew how to write a makefile). An update in a single library could mean a bunch of manual rebuilds, sometimes followed by manual deployment. This is no longer the case, really. It is a little schizophrenic that we do daily builds for continuous integration, but insist that there's no frickin' way we're going to be able to rebuild packages that depend on a library and distribute them on time. The problem is certainly tractable, albeit at higher resource expense (imagine what an update in glibc would entail).
* On the other hand, it's not like dynamic libraries have fulfilled the promise of never using an out-of-date version ever again. It's not at all uncommon for programs to bundle their own version of shared libraries. A while back, when I first came across material discussing this problem, it turned out that a lot of programs of my system did it -- OpenOffice is the one I most distinctly remember, but there were others, too. As for other operating systems where package managers are less common (cough Windows cough), this situation is pretty much the norm when it comes to any library that Windows Update doesn't take care of.
* The linking process is extremely complex, and it has been found to be vulnerable. The vulnerabilities were patched, however. There is always a degree of uncertainty in affirming that vulnerability is inherent to complexity. Plus, if it is, then we have a lot of really bigger things to worry about, like that huge pile of code in the kernel which is orders of magnitude more complex than a dynamic loader.
Edit: I guess the best way to sum up my (current) understanding of the matter is that the case for static linking isn't as weak as it was a long time ago, but I don't think the case against dynamic linking is spectacular enough to be worth a full migration of everything. That its usefulness is diminishing, at least in some fields, is sufficiently proven by e.g. its adoption in Go. But I doubt that going back to static linking is the universal solution that it is sometimes advertised to be.
>offset by larger hard drives, better and faster network connectivity, and better updating systems.
Static linking puts more pressure on RAM and on each level of cache (because if 2 running programs share the same library, there are now 2 copies of the library contending for those resources) than dynamic linking does.
That strikes me as more important than increased use of the resources you list.
That's not always true, you don't need to have two full copies of the library at all times. See Geoff Collyer's explanation here: http://harmful.cat-v.org/software/dynamic-linking/ (but note that the memory use that he cites may not be that relevant).
I am also not convinced that this is a significant impediment for all workloads. For a lot of applications, the time wasted due to inefficient cache use is a fraction of the time spent waiting for stuff to be delivered over the network.