Monday, October 10, 2022

Swift Was Always Going to Be Part of the OS

Jordan Rose:

Between Swift 1 and Swift 5 there was a massive amount of change, from shifting API design to changing ARC function conventions to adding missing optimizations to learning what was going to be practical and idiomatic in this new language. Looming over us the whole time was “ABI stability”, the point at which code using two different versions of Swift could interoperate. Why was this important, when so many other languages didn’t seem to bother? Because this was the very premise of Apple’s OS-based library distribution model: apps compiled for Swift 5 would work with an OS built on Swift 6; apps compiled with Swift 6 would still be able to “backwards-deploy” to an OS built on Swift 5. Without this, Apple couldn’t use Swift in its own public APIs.


We ended up (ab)using a feature called “rpath”, or “runtime search path”, which allowed an executable to find its dynamic libraries not by hardcoded path but by searching a series of directories. By making the search order start with /usr/lib/swift/ and following that with the app bundle, we could guarantee that apps would use the OS version of Swift if present and fall back to their embedded version otherwise.


This same technique was used just last year for Swift Concurrency, and then a serious bug was discovered in that first release…and it can’t be “fixed” in the backwards-deployment library because that wouldn’t help on the OSs that still contain libswiftConcurrency 1.0.


Specific functions can be marked with a not-yet-supported attribute to have them copied into clients instead of referenced by symbol name, much like a C static function defined in a header file. This only works for things like functions, methods, etc that don’t need identity, though; if the same implementation were used with a global stored variable, you’d end up with multiple copies of the global. And it also only works when the implementation is compatible with both past and future versions of the APIs it uses in turn.


In certain cases, the Swift team includes a “compatibility” library that’s linked in to the main app only (so that there’s exactly one) to bring some of the older OS’s support up to date.

Nick Lockwood:

I recall when ARC was added to Obj-C (and later fast enumeration, subscripting, object literals, etc) they had to bundle the ARCLite dylib with apps so they could run on earlier OSes that didn't support those features.


Comments RSS · Twitter

Leave a Comment