What is Module Stability in Swift and why should you care?
The Swift team has recently released Swift 5.1. This version of the Swift language contains many cool features like Function Builders that are used for SwiftUI and Property Wrappers that can be used to add extra functionality to properties. This release also contains a feature called Module Stability. But what is this feature? And what does it mean to you as a developer? In this week’s blog post, I will explain this to you. But before we get to Module Stability, let’s do a little time traveling back to Swift 5.0, which shipped with ABI (Application Binary Interface) Stability.
Looking for a great mobile CI/CD solution that has tons of iOS-specific tools, smooth code signing, and even real device testing? Learn more about Bitrise’s iOS specific solutions.
This sponsored message helps keep the content on this site free. Please check out this sponsor as it directly supports me and this site.
Understanding ABI Stability
Up to Swift 5.0, every time you built an app with Swift, your app would include the entire Swift standard library and runtime. The reason for this was that Swift was changing so much that it wasn’t feasible to include the Swift fundamentals into releases of iOS. Swift 5.0 changed this with ABI Stability. Swift now defines a stable binary interface that will not change across Swift versions. In practice, this means that the Swift 5.1 (or later) runtime can execute code that was compiled with the Swift 5.0 compiler due to this stable interface definition.
When you write code, you do not need to understand or think about this binary interface, or ABI. This is all handled internally by the Swift compiler and it’s possible that the biggest win for your app is simply that your application binary is smaller for iOS versions that include the Swift runtime because the App Store will now strip the Swift runtime out of your binary if your app is being downloaded on a platform that has ABI Stability.
One common misunderstanding I’ve seen with ABI stability is that people were hoping that it would allow them to use frameworks that are compiled with Swift 5.0 in a project that uses the Swift 5.1 compiler. Unfortunately, this is not the case and the following error is likely one that you’ve encountered when you upgraded from Swift 5.0.1 to Swift 5.1.
Module compiled with Swift 5.0.1 cannot be imported by the Swift 5.1 compiler
This brings us to the Module Stability introduced by Swift 5.1.
Understanding Module Stability
While Module Stability and ABI stability are completely different animals altogether, they are also quite similar. While ABI Stability allows programs written with different versions of Swift to exist in a shared runtime, Module Stability allows you to use frameworks compiled with different versions of swift in a project that might use yet another version of Swift. The way this works is best explained by the following excerpt from the Swift 5.1 release announcement:
Swift 5.1 enables the creation of binary frameworks that can be shared with others leveraging the language’s added support for module stability. Module stability defines a new text-based module interface file that describes the API of a binary framework, allowing it to be compiled with code using different versions of the compiler.
Binary frameworks that were built with Module Stability enabled contain a special folder with the
.swiftmodule suffix which contains
.swiftmodule files. These files are the text-based definition of your framework's API that is mentioned in the Swift 5.1 release announcements. To build your own frameworks with support for module stability you need to enable the
Build Library for Distribution setting in your framework's Project Settings pane and set the
Skip Install property to
NO. After doing this, Xcode includes the
.swiftmodule in your product when you archive it, making your framework "module stable".
Every binary framework that is compiled with the Swift 5.1 compiler and Xcode 11 or later can be used in any project that uses Swift 5.1 or later as long as the
Build Library for Distribution and
Skip Install properties are configured correctly. So, in short, Module Stability means that you should never see an error message that reads “Module compiled with Swift 5.1 cannot be imported by the Swift 5.2 compiler” because all frameworks that were built with module stability are automatically compatible with the Swift version it was built for and newer. Pretty cool, right?
Now that we have Module Stability and ABI Stability in Swift, the language is likely to change at a slower rate than we’re used to. We should see less radical, source breaking changes and the language should slowly mature into a beautiful, fast and stable language that will be a great basis for your applications for years to come. However, don’t think that Swift will stop innovating and evolving. The Swift Evolution forum is still going strong and folks are still working very hard to make Swift a versatile, safe and clean language to work with.
As always, feedback, compliments, and questions are welcome. You can find me on Twitter if you want to reach out to me.