Is Swift ABI compatible between minor versions? - ios

I know Swift is not yet ABI stable, but does that only count for major versions of Swift?
Is there any guarantee that minor or patch versions (under semantic versioning) of Swift are ABI stable?
I'm guessing there is no guarantee here, but just wanted to double check if anyone has come across anything detailing ABI stability for different minor/patch versions of Swift.
Also, if I use a Swift binary framework compiled with a different version of Swift I get a compiler error usually. If I don't get a compiler error in my project does that mean it is safe, or could there still potentially be runtime issues with a slightly different (patch version) of Swift?

Update 3
We also have module stability, starting with Xcode 11, with the help of the newly introduced .swiftinterface files. One caveat, though, is that the code will have to be build with the -enable-library-evolution flag. More details here.
Update 2 Module stability is scheduled for Swift 6: https://swift.org/blog/abi-stability-and-more/#module-stability
This is an excerpt from the Swift evolution repo.
Update Swift 5 comes with some ABI stability:
The Swift 5 release will provide ABI stability for the Swift Standard Library.
Unfortunately, not yet. For Swift 4, they state this here: https://swift.org/blog/swift-4-1-release-process/.
Swift 4.1 is not binary compatible with 4.0. It contains a variety of under-the-hood changes that are part of the effort to stabilize the Swift ABI in Swift 5.
Hopefully we'll get ABI stability in Swift 5

I think we should know what is ABI stability firstly, After that your confusion has already been removed.
Today, the latest version of Swift is 3.1, so chances are if you ship an app tomorrow, your app bundle will contain the Swift dynamic libraries for 3.1, however, there are plenty of apps in the store right now which link 3.0, 2.3, and probably even some older apps that link 2.1 and earlier. Nothing is stopping me from downloading your app (on 3.1) and my app (on 2.3) and running them side-by-side on my iPhone with iOS 10.3, since both apps link against their own bundled version of Swift. It's exactly the same as you bundling Alamofire 4.4 and while I bundle 3.0.
When a language is ABI-stable (Application Binary Interface), that means it is packaged and linked with the operating system itself, in this case: iOS. The Swift code you compile on your computer has a binary interface into the operating system itself rather than any dynamic library you bundle with your application. Because of this, Apple has to be able to guarantee that my Swift code, when compiled to machine code (bitcode, LLVM-IR, yada-yada), will be able to interface properly with the rest of the operating system, and (probably more importantly) will not break between versions of iOS / Swift.
As it stands today, the Swift language specification and compiler are not in a state where the Swift team would feel comfortable making this promise of ABI-stability; changes to Swift are still too frequent and the roadmap is still too long. As soon as the Swift library is merged into iOS, it becomes much much harder to make big changes.
Why does it matter?
Yes, the bundle size of your application will decrease because you will no longer have to include the Swift standard library in your Frameworks folder, which is nice.
Language changes will be smaller / less frequent, so you won't have to worry about events like migration from Swift 2 -> 3 (I'm still scarred from that)
Developers will be able to create 3rd-party libraries written in Swift and distribute pre-compiled frameworks (binaries), because they no longer need to bundle the Swift standard library into their framework, and will instead be linking against the same version of Swift as your app (the one packaged with iOS).

Related

How to prebuilt libraries to be compatible with future swift versions

We are prebuilding some libraries (mainly with carthage) for some of our projects to reduce development times. These libraries are not updated very often, but we want to update our XCode versions pretty fast.
Now every time a new XCode brings a new swift version, we are seeing this incompatibility issue
File.swift:4:8: error: module compiled with Swift 5.3.2 cannot be imported by the Swift 5.4 compiler: /......./Debug-iphoneos/Alamofire.framework/Modules/Alamofire.swiftmodule/arm64-apple-ios.swiftmodule
How can I pre-build my dependencies in a way that a swift update wont affect it and I dont have to re-build the dependencies with every xcode update (I thought thats what ABI stability was for? How can I activate that?)
It sounds like you're misunderstanding what ABI stability enables. The main benefit is that it allows the OS to include only one version of the Swift standard library, and for all Swift binaries to share it. What you want is "module stability". From the docs on ABI stability:
ABI stability is about mixing versions of Swift at run time. What
about compile time? Right now, Swift uses an opaque archive format
called “swiftmodule” to describe the interface of a library, such as a
framework “MagicKit”, rather than manually-written header files.
However, the “swiftmodule” format is also tied to the current version
of the compiler, which means an app developer can’t import MagicKit if
MagicKit was built with a different version of Swift. That is, the app
developer and the library author have to be using the same version of
the compiler.
To remove this restriction, the library author needs a feature
currently being implemented called module stability. This involves
augmenting the opaque format with a textual summary of a module,
similar to what you see in Xcodeʼs “Generated Interface” view, so that
clients can use a module without having to care what compiler it was
built with.
This is not yet supported in any version of Swift.

Module compiled with Swift 5.1 cannot be imported by the Swift 5.1.3 compiler

Check several publications with the same compilation error, and it really seems annoying that some libraries do not have support for current versions, well Apple also updates the Xcode many times along with the Swift version. Then after reviewing many publications and research, I discovered this post where they indicate:
Swift 5 provides binary compatibility for applications: a guarantee
that, in the future, an application created with one version of the
Swift compiler will be able to communicate with a library built with
another version. This applies even when using the version
compatibility mode from previous languages ​​(-swift-version 4.2).
In other cases, they indicate using carthage update --platform iOS --no-use-binaries but I am using cocoapod so I cannot use that solution and finally indicate enabling Build Libraries For Distribution, but nothing really worked for me until now and I can't help thinking that maybe tomorrow they will launch swift 5.1.4 and the support they make for swift 5.1.3 is unusable.
I really hope you can help me with the solution to the problem I present with the compilation error and if anyone knows about the post ABI STABILITY

Swift 3.0 will not be 2.2 source compatible... will I have to rebuild my apps?

http://thenextweb.com/apple/2016/05/09/swift-3-0-developer-previews-wwdc/#gref
Does this mean anything? Will I have to completely rebuild my apps or merely convert 2.2 syntax to 3.0?
Swift 3.0 will not be compatible with 2.2. Here is the list of the current proposals, it also details what has been implemented already, and what will be :
https://github.com/apple/swift-evolution
You will not have to entirely rebuild your App, but you will have to adapt your code.
I'd say no. Every Swift app comes with its own runtime and standard libraries of whatever Xcode version you used to build it. Some of my Swift 1.0 app still runs on the latest version of El Capitan.
Source incompatibility means you can't take valid code written in Swift 2, feed it to the Swift 3 compiler and expect everything to go smoothly. There will be errors and deprecation warnings, much of which you already see today with Swift 2.3.
You also can't take a compiled application written in Swift 2 and make it run without modification on a Swift 3 runtime either. Swift is lacking a stable Application Binary Interface (ABI) at the moment. That's why every Swift app must carry its own runtime. OS X and iOS don't provide those at the system level. Hence Swift app tends be larger in size, more of a problem on iOS than OS X.
With Swift 3, Apple is trying to establish a stable ABI so your compiled Swift 3 can run without modification on the Swift 4 runtime, whenever that comes.
What about source code compatibility? No one knows what Chris Lattner has in mind or what he considers archaic. Removing the ++ and -- operator in Swift 3 seem superfluous to me. And why kill C-style for loop too?
I'm currently adapting all my code to the present state of Swift 3. The existing code is certainly not compatible; most methods have been renamed, case names have been lowercased, and so on. To what extent Apple will assist by providing a migration tool is unknown, as that's in the future.
#CodeDifferent provided a great answer, but I'd like to extend on it.
AFAIK, if your Swift 2 app is compiled with its own runtime linked in (i.e., not relying on the system runtime), then your app will run fine & there's no need to rebuild on a Swift 3 machine to run on a Swift 3 machine. But if there's no runtime compiled into the app, then your app won't run on a machine with a Swift 3 ABI.
Of course, if you are going to compile with application with Swift 3, then you will have to re-build.

How does iOS7 understands Swift Code? Is there any Swift support by OS?

Here is my short assumption on that currently looking more on it.
Application with Swift code bundles Swift specific standard libs with Swift, Apple has changed how standard libraries are shipped. With Objective-C, all of the standard libraries, system frameworks, and the runtime itself, were shipped with the OS. But With Swift, Apple trying to ship a specific version of the standard library with your app.
Please share your thought on that.
Found Interesting - Compatibility Blog
According to that - In fact, you can target back to OS X Mavericks or iOS 7 with that same app. This is possible because Xcode embeds a small Swift runtime library within your app’s bundle. Because the library is embedded, your app uses a consistent version of Swift that runs on past, present, and future OS releases.
Any other discussion warm welcome!

Swift compatibility between versions for a library

I'm distributing libraries for other developers to use (http://empiric.al). I've noticed that between swift versions, even 2.0 to 2.1, I'll get Module file was created by a (newer/older) version of the compiler.
I need to be distribute in a future-proof way.
How can I make sure my compiled frameworks can be used by newer versions of Swift in the future so I don't have to recompile as soon as Apple puts a new beta out?
From Apple's website:
Binary Compatibility and Frameworks
While your app’s runtime compatibility is ensured, the Swift language
itself will continue to evolve, and the binary interface will also
change. To be safe, all components of your app should be built with
the same version of Xcode and the Swift compiler to ensure that they
work together.
This means that frameworks need to be managed carefully. For instance,
if your project uses frameworks to share code with an embedded
extension, you will want to build the frameworks, app, and extensions
together. It would be dangerous to rely upon binary frameworks that
use Swift — especially from third parties. As Swift changes, those
frameworks will be incompatible with the rest of your app. When the
binary interface stabilizes in a year or two, the Swift runtime will
become part of the host OS and this limitation will no longer exist.
Until the Swift ABI (application binary interface) stabilises (I'm guessing another year or two) the only way to distribute libraries that will work across different Xcode versions is to distribute the source code. Cocoa pods and Carthage are both good tools for making library distribution easier but for Swift code they will still rely on source code being available.
It might be possible to have an Cocoapod that detects the version of Xcode it is run with and then downloads and provides the correct build of your library but you will still need to build the libraries for all Xcode versions that you want to support and recompile every time Apple release a new Xcode but at least the user wouldn't need to download a new version manually.

Resources