The premise of this change feels off to me.
Just saying “Linux is a server-centric OS” is a bit of a misnomer. There are certainly distributions of Linux, like Alpine, that are server-centric, but there are also distributions that are desktop-oriented, like Ubuntu Desktop and Fedora. On Alpine, it makes sense to statically link everything, especially given that it’s a statically linked musl-based distribution. Ubuntu, Arch, and Fedora usually dynamically link runtimes. It really only at the distribution level that it makes sense to determine the default behavior.
In terms of “shipping a runtime”, the normal means of distributing files on most (at least all of the distros I've worked with) is via a package in the package manager. Creating a package like
swift-runtime so that one could run
sudo apt install swift-runtime on Ubuntu, for example, would satisfy the missing runtime and standard library issues in a way that is consistent with how other bits are installed. Then one would make that swift-runtime package a dependency of any swift-based programs.
In terms of propagating bug fixes; distributions regularly update the dynamic libraries, especially when a security vulnerability is found. For servers running a single program used to serve webpages, this shouldn’t be a problem if the runtimes are statically linked. The person hosting the server can re-compile with the fixed library and re-distribute it and bob’s your uncle. In a desktop context, the person using the machine will likely have more than one program. Are we expecting them to update every executable?
Additionally, in a server context with a minimal set of programs, the binary size overhead of packing around multiple copies of the same runtimes should be negligible, but once you have 100 apps installed, all of which are statically linked, that’s going to get expensive pretty quickly. As noted in the proposal,
Statically linking of the Swift runtime libraries increases the binary size from 17K to ~35M.
This jump in binary size may be alarming at first sight, but since the program is not usable without the Swift runtime libraries, the actual size of the deployable unit is similar.
The difference is that you only pay for the runtimes once when they're dynamically linked, whereas you will pay for each executable when it's statically linked. Once you have two copies of your program, you're paying for that runtime twice, so it will be ~70M instead of ~35M + 34K. (It looks like the cost of the program itself is fairly negligible compared to the size of the runtime + stdlib, so including the extra dead-code-elmination you get from statically linking, I'm estimating the runtime to be about 35M.) Three would be 105M instead of 35M + 51K. And once you get up to 100 apps, you're looking at 3 gigabytes in copies of the runtime.
I think my last concern is ABI. If an App links Foundation statically and another dependency in the OS contains a copy of Foundation, can objects be passed between them? If everyone dynamically links the same copy of Foundation, the answer is yes (or at least should be). With statically linked libraries, it’s unclear. I can’t tell if Jordan was inspired by this proposal when he wrote this blog post, but Dynamic Linking Is Bad For Apps And Static Linking Is Also Bad For Apps // -dealloc covers a lot of interesting points, and comments on why you really can’t mix dynamic and static linking safely.
Then my last ABI concern is surrounding copies of global variables coming from different statically linked copies of libraries. It’s the same problem that LLVM runs into when you try to statically link the library multiple times. The
cl::opt global variables conflict.
Linux isn’t just a container or server platform, so the premise of treating as such by default is incorrect. It really depends on what distribution you’re targeting. So to conclude, if you only ever want to have a single Swift program installed on someone’s computer, this is absolutely the right way to go. If we want more than one Swift program installed, then dynamically linking is still the correct behavior, and should continue to be the default on distributions that are used for desktop applications.
Is the problem big enough: Yes, Swift should be able to statically link programs, but I don't think it should be by default.
Effort into review: I've read the proposal through at least 4 times and thought about my answer last night while sleeping before writing it up.