Swift 5 and ABI Stability — the best time to migrate
Swift is a fast, safe and a fun language to code in with full stack potential and a great community support. It is about 2.6 times faster than Objective-C according to Apple, however, some studies indicate that the difference is not that dramatic. Swift code is easier to maintain as there are no separate interface and implementation files, the syntax is shorter and the language supports dynamic frameworks.
The language has grown significantly and has been adopted by a large number of developers. It is the 6th most loved language according to StackOverflow Developer Survey 2018. For a language released in just 2014, the adoption rate is phenomenal.
Those are some of the benefits of Swift, now let us look at the drawbacks from a developers’ perspective. Swift is still not mature and is like a moving target with major changes being introduced with every new release. One of the key problems articulated by many developers is the lack of backward compatibility with older language versions and the version-lock which means there can be only a single version of Swift in the entire project and its external dependencies. Consequently, developers are forced to completely rewrite their projects if they want to switch to the latest Swift version and update their external dependencies. For developers who make frameworks, they have to update their framework for every new Swift version and they cannot distribute it as a binary precompiled framework.
Luckily the Swift team and the Open-Source community are working on this issue and are expected to address this in the next major release of Swift i.e. Swift 5.0, having been pushed forward since Swift 3.0. The ABI Stability Manifesto states they have the goal of accomplishing:
- Source Compatibility, which means that newer compilers can compile code written in an older version of Swift. This removes the version-lock currently in Swift.
- Binary framework & runtime compatibility, which enables the distribution of frameworks in a binary form that works across multiple Swift versions. Binary framework compatibility will be achieved by module format stability which stabilizes the module file, which is the compiler’s representation of the public interfaces of a framework and ABI stability enables binary compatibility between applications and libraries compiled with different Swift versions.
What is ABI?
At runtime Swift program binaries interact with other libraries and components. Application Binary Interface is the specification to which independently compiled binary entities must conform to be linked together and executed. These binary entities must agree on many low-level details like how to call functions, data representation in memory, and even where their metadata is and how to access it.
What is ABI Stability?
ABI stability means locking down the ABI to the point that future compiler versions can produce binaries conforming to the stable ABI. Once an ABI is stable, it tends to persist for the rest of the platform’s lifetime.
ABI stability only affects invariants of externally visible public interfaces and symbols. For example, future compilers are free to change the calling conventions for internal function calls so long as the public interfaces are preserved.
Prerequisites of ABI Stability
- Types, such as structs and classes, must have a defined in-memory layout for instances of that type and share the same layout conventions.
- Type metadata is used extensively by Swift programs. This metadata must either have a defined memory layout or have a set of defined APIs for querying the metadata of a type.
- Every exported or external symbol in a library needs a unique name upon which binary entities can agree. Swift provides function overloading and contextual namespaces (such as modules and types), which means that any name in source code might not be globally unique. A unique name is produced through a technique called name mangling.
- Functions must adhere to calling conventions, which entails such things as the layout of the call stack, what registers are preserved, and ownership conventions.
- Swift ships with a runtime library which handles things like dynamic casting, reference counting, reflection, etc. Compiled Swift programs make external calls out to this runtime. Thus, Swift runtime API is Swift ABI.
- Swift ships with a standard library that defines many common types, structures, and operations on these. For a shipped standard library to work with applications written in different versions of Swift, it must expose a stable API. Thus, Swift Standard Library API is Swift ABI, as well as the layout of many of the types it defines.
All these tasks have been accomplished by the Swift core team but they have not yet been released on GitHub. Looking at the status of the tasks we can safely expect the next major release of Swift to be ABI stable.
Advantages of ABI Stability
- So once Swift is declared to be ABI stable, the code written from this point on would be compatible with the newer versions of the language and the developer won’t have to update all the external dependencies of the project while migrating to a new version of Swift.
- The library author can supply his framework as a binary framework once module format stability is achieved.
- The application bundle size would decrease as the stable Swift runtime could then be incorporated within the OS.
- The language would keep evolving but the changes to the ABI from that point on would be additive. The ABI-additive changes may be taken advantage of when the minimum targeted Swift version supports them, since ABI stability locks only the externally visible public interfaces and symbols. The newer compilers can make internal changes that may improve efficiency.
Swift is clearly the future for development in the Apple ecosystem and once it is ABI stable and module format stable the language would be free of its biggest disadvantages. Please read through these articles for a detailed comparison between Swift and Objective-C.
If you wish to convert your Objective-C codebase to Swift, now is the best time to start. I have written an article covering the conversion of SVProgressHUD to IHProgressHUD which is fully written in Swift and is thread safe with the same API design as SVProgressHUD using Swiftify for Xcode.