[Accepted] SE-0342: Statically link Swift runtime libraries by default on supported platforms

The core team appreciates all the discussion for SE-0342:

As part of considering the points raised in the review, the core team discussed the general rollout of Swift across platforms and how we may the defaults between static and dynamic linking of the Swift runtime. Further, we also discussed how and when those defaults might evolve and change.

Before Swift 5, all Swift applications effectively bundled the runtime with the app on Apple platforms. App bundles contained their copy of the dynamic runtime libraries, and ordinary executables (not bundles) statically linked the runtime. Once ABI stability arrived on Apple platforms, the inflection point changed, and all executables used dynamic linking of the system's copy of the Swift runtime. There is a caveat here that apps that backward deployed to earlier OS releases may have carried a copy of the Swift runtimes for running on those older OSes. Still, the primary detail is that the apps on Apple platforms switched from having a copy of the runtime for themselves and using a shared version. This switch happened when critical components came to play:

  1. The ABI was deemed stable enough to lock-in.
  2. There was strong demand for Swift usage in the system to grow beyond just apps using Swift in isolation and instead allow Swift apps to use distributed libraries (including system frameworks) that published Swift APIs.
  3. The volume of processes using Swift in the system was large enough that using a shared runtime between apps had a notable performance benefit.

The theme that cross-cuts these three points is the scale and maturity of Swift usage in the system.

Presently the usage of Swift on Linux does not satisfy any of the three points above. On Linux, Swift has neither a stable ABI nor enough pervasive use in the system to justify the complexity of apps using shared runtimes. Swift usage on a typical Linux system is likely isolated to a modest number of processes, while no system frameworks are using Swift. One comment from the review thread captured this well:

Defaulting to static linking on Linux in many ways mirrors the behavior of how Swift apps behaved on Apple platforms before Swift 5: they included a copy of the runtime with them. Effectively including the runtime within executables makes the executables slightly easier to distribute while allowing the ABI to evolve without disrupting users. Thus, the core team has decided to accept the proposal and change the default linking behavior of the Swift runtime on Linux for executables built for distribution.

However, this default can change in the future, as it did on Apple platforms. As the usage of Swift on Linux evolves and grows and Swift achieves a stable ABI on Linux, we should reevaluate the choice to default to static linking of the Swift runtime on Linux.

Thus, this proposal is accepted, with a tiny revision. Today, the Swift Package Manager performs no validation when linking libraries into an executable that statically links the Swift runtime libraries. A user can mistakenly link a library that already has the Swift runtime libraries statically linked into the executable that will also link the Swift runtime libraries. Such a scenario could lead to runtime errors if the versions of the Swift runtime libraries do not match. As part of accepting this proposal and considering it implemented, the Swift Package Manager will gain a new post-build validation checking for this condition and warning the user accordingly. This requirement has been added to the proposal text.

Thank you to everyone who contributed to the discussion of this proposal.

37 Likes