TL;DR: Swift is much more exposed to the system than Go or Rust.

Go is a special snowflake, so we'll address it first: Go has essentially zero system dependencies. On Linux it makes all syscalls itself, without going through libc, and so is well protected against differences in libc versions and types. It links almost none of the binaries provided by Linux. Your average Go binary links nothing from the system, and the Go build tool itself has the following linkage:

linux-vdso.so.1 (0x00007ffef1d47000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa1a881b000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa1a842a000) /lib64/ld-linux-x86-64.so.2 (0x00007fa1a8a3a000)

That's libc, libpthread, and the vDSO: that's it. Not much! Because it depends on so little, the risk that Go will inadvertently use something from the system that is not available on all Linux distributions is very low.

Next, Rust. Unlike with Go, Rust does link some things from the system to get its standard library working. In fact, if you take a thin OS image and install Rust on it, your rust toolchain won't work! It requires that you have a compiler toolchain installed already. So we're already away from where we were with Go.

Regardless, if we build Cargo's hello world project we see the following linkage:

linux-vdso.so.1 (0x00007ffd8cd68000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f03b67e2000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f03b65da000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f03b63bb000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f03b61a3000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f03b5db2000) /lib64/ld-linux-x86-64.so.2 (0x00007f03b6c19000)

There are some more things here! libgcc_s , librt , and libdl . This is an indication that even more of Rust's standard library depends on things coming from the system. If we look at what rustc requires we see an additional dependency on libm .

Now let's look at Swift. If I do swift package init --type=executable and print the linkage of the resulting binary we get:

linux-vdso.so.1 (0x00007ffc1a5c1000) libswiftSwiftOnoneSupport.so => /usr/local/swift/usr/lib/swift/linux/libswiftSwiftOnoneSupport.so (0x00007f64734a4000) libswiftCore.so => /usr/local/swift/usr/lib/swift/linux/libswiftCore.so (0x00007f6472d7e000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f64729f5000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f6472657000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f647243f000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f647204e000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f6471e2f000) libatomic.so.1 => /usr/lib/x86_64-linux-gnu/libatomic.so.1 (0x00007f6471c27000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f6471a23000) libicui18nswift.so.61 => /usr/local/swift/usr/lib/swift/linux/libicui18nswift.so.61 (0x00007f647152d000) libicuucswift.so.61 => /usr/local/swift/usr/lib/swift/linux/libicuucswift.so.61 (0x00007f647114d000) libicudataswift.so.61 => /usr/local/swift/usr/lib/swift/linux/libicudataswift.so.61 (0x00007f646f5a8000) /lib64/ld-linux-x86-64.so.2 (0x00007f64732c2000)

This is a lot more! Many of these are part of the Linux distribution of Swift so they don't count, but we can add libatomic and libstdc++ to the mix.

But this is still not too bad, right? Right, except that we have way more libraries than that. Swift ships at least the following libraries:

libBlocksRuntime.so libFoundation.so libFoundationNetworking.so libFoundationXML.so libXCTest.so lib_InternalSwiftSyntaxParser.so libdispatch.so libicudataswift.so libswiftRemoteMirror.so libswiftSwiftOnoneSupport.so libicui18nswift.so libicuucswift.so libswiftCore.so libswiftDispatch.so libswiftGlibc.so

If we ask them all what they need and uniqify them, we end up with the following dependencies on the system:

/lib64/ld-linux-x86-64.so.2 libasn1.so.8 libatomic.so.1 libc.so.6 libcom_err.so.2 libcrypt.so.1 libcrypto.so.1.1 libcurl.so.4 libdl.so.2 libffi.so.6 libgcc_s.so.1 libgmp.so.10 libgnutls.so.30 libgssapi.so.3 libgssapi_krb5.so.2 libhcrypto.so.4 libheimbase.so.1 libheimntlm.so.0 libhogweed.so.4 libhx509.so.5 libidn2.so.0 libk5crypto.so.3 libkeyutils.so.1 libkrb5.so.26 libkrb5.so.3 libkrb5support.so.0 liblber-2.4.so.2 libldap_r-2.4.so.2 libm.so.6 libnettle.so.6 libnghttp2.so.14 libp11-kit.so.0 libpsl.so.5 libpthread.so.0 libresolv.so.2 libroken.so.18 librt.so.1 librtmp.so.1 libsasl2.so.2 libsqlite3.so.0 libssl.so.1.1 libstdc++.so.6 libtasn1.so.6 libtinfo.so.5 libunistring.so.2 libutil.so.1 libuuid.so.1 libwind.so.0 libxml2.so.2 libz.so.1 linux-vdso.so.1

This is quite a lot! Much more than Rust, and hilariously more than Go.

This is because Swift on Linux includes Foundation, and in particular FoundationNetworking and FoundationXML, an extremely broad pair of libraries that have been built on top of the primitives provided in Linux distributions. When using another Linux distribution, some or all of these dependency libraries will be present either in different versions, or with different implementations. These require compatibility shims and version-specific code to be added to Swift's libraries in order to get them to work.

Note that this is a different goal from being able to use Swift on Linux. It's extremely possible to build a Swift binary on Linux that can easily be made to run on a wide range of platforms, if you don't rely on FoundationXML or FoundationNetworking. However, to distribute an official Swift on those platforms those two libraries must be present. The difficulty of using a different Linux distribution therefore comes down to the cost of porting to use other versions of these libraries.

Incidentally, this is not actually a problem unique to Swift: many other languages have similar issues, especially higher level interpreted ones. Go and Rust are somewhat unique in their effort to reinvent all wheels in their own programming language and without deferring to the system. Python links several libraries as well, for example, and therefore requires some porting work to run on a new system.