Swift.org blog: ABI Stability and More

Thanks, I also have a different question, since I'm discussing this with collegues: Is the binary code when using the Swift 5 toolchain, the same for language version 4.0, 4.2 and 5.0 (since they are compatible according to the documentation)?

Related to this we have a problem currently with dynamic library loading times using the new Swift 5 toolchain which has deteriorated from 500 ms to more than 6 seconds (affecting the app startup time). We verified that reverting the toolchain to version 4 fixes this issue. We are pretty worried by this. Do you have any insights maybe?

1 Like

It's correct that the language version does not affect the ABI version; the compiler toolchain is the same and the generated code should vary only in places affected by the language mode.

That is indeed a big jump. I suggest setting the environment variable DYLD_PRINT_STATISTICS=1 (see man dyld) to see if the time is being spent pre-main, and Instruments to see what's going on during that first call to UIApplicationMain. If it's something that's changed between the two compiler toolchains, we'd like to know about it! (But probably on a different thread, or in a bug report.)

[Immediate edit: I see you already said "dynamic library loading times". Is it loading more libraries than before, or are the same libraries taking longer? Because I don't think that much has changed.]

Thanks @jrose . It took me some time to collect the data, but I created a Swift bug with the profile traces attached showing the issue.

The code base is exactly the same, the only difference between the two traces is the compiler version.

Please see: https://bugs.swift.org/browse/SR-10755

1 Like

Hi @jrose, Iā€™m noob on this so donā€™t kill me please

Letā€™s suppose that I have an app which is coded using swift 4.2 and it has many dependencies built with ABI 4.2.X

In order to jump to the new ABI 5.X.X, we have requested our third partyā€™s to recompile their frameworks with the new ABI. My first question is, do these framework should be written using Swift 5? I understand that no because Swift version and ABI level are independent

Once we have every third party library ready we update them on the app and start using the new ABI level of Xcode. My second question goes here, do we need to update also the Swift version or not? What I expect is to be able to update the ABI level and after check that we havenā€™t broken anything on the app, migrate the app to Swift 5.X

Thanks in advance and again sorry if I killed someone with my mistakes :slight_smile :)

Your assumption is right, but if you plane to use binary frameworks not compiled with your project, you should either make sure you are using the same toolchain version, or use a toolchain that support Module Stability (in addition to ABI Stability). I think module stability is available from Swift 5.1.

That said, I had to migrate a large project from 4.2 to 5, and I didn't had a single code change to do. So you may just try to enable Swift 5 mode and see what the compiler tell you.

4 Likes

Please don't be worried about this, it should always be okay to ask questions when you've already looked for answers!

Letā€™s suppose that I have an app which is coded using swift 4.2 and it has many dependencies built with ABI 4.2.X

In order to jump to the new ABI 5.X.X, we have requested our third partyā€™s to recompile their frameworks with the new ABI. My first question is, do these framework should be written using Swift 5? I understand that no because Swift version and ABI level are independent

As Jean-Daniel mentioned, this is correct; the language compatibility version is independent of the ABI. The frameworks you're using will have to recompile with Xcode 10.2, but they can keep using Swift 4 or 4.2 modes. (If they're using Swift 3 mode, though, that's been removed.)

Once we have every third party library ready we update them on the app and start using the new ABI level of Xcode. My second question goes here, do we need to update also the Swift version or not? What I expect is to be able to update the ABI level and after check that we havenā€™t broken anything on the app, migrate the app to Swift 5.X

You shouldn't need to update your app's language version either (though again, you can), as long as you're not using Swift 3 mode.


The references to module stability go back to what's in this blog post: ABI stability means that two binary frameworks will work together at run time, but the compiler in Xcode 11 still isn't able to understand the framework content from Xcode 10.2. Starting in Xcode 11, however, there's a new format for binary framework module interfaces that's intended to be stable going forward (so Xcode 11.1 won't have the same problem). @harlanhaskins and I gave a talk about it at WWDC, "Binary Frameworks in Swift".

3 Likes

Hi @jrose (and the rest of you fellas as well)

so, started working with iOS recently (another noob, yup) and made an SDK written in Swift 5.
Now, obviously, related to this topic - I'd like not to have a binary-per-swift-version when it comes to loading it into projects written in versions prior to Swift 5 (e.g. v3, v4, v4.2), while hopefully thanks to ABI/Module stability that won't be an issue with newer versions.

And most importantly, if Objective-C wrapper should work for that case -> what would be recommended approach in achieving that, any guide available or is it just achievable by simply using @objc annotation or NSObject extension of API classes?

Welcome to the forums, @happydev. Module stability does sound like what you're after, but it only starts with the release of Swift 5.1. Now, you can use the Swift 5.1 compiler to build projects written using the Swift 4 or 4.2 language modes (not 3, though, sorry), but if you want to continue using earlier compilers (i.e. earlier Xcodes) you'll have to still build a version of your framework for each one you want to support.

The "Objective-C interface only" strategy is a way out of that that only depends on ABI stability, which means it works with the Swift 5 compiler (but still not earlier). There's no guide because it's not really a common use case, but if you implement a framework in Swift that exposes things publicly to Objective-C, those APIs will show up in the generated "-Swift.h" header that's added to your framework. If you then want to distribute that framework, you can delete the Swift interface out ("MyKit.swiftmodule" in the Modules folder in the framework), and clients will use it just like a pure Objective-C framework. The framework still has Swift in it, though, so if those clients are deploying to an OS version that doesn't have Swift in it, they'll have to embed the Swift standard library in their app even if they themselves are not using Swift.

1 Like

Thanks a lot, that was pretty fast too.

I think I understood the part with Module stability prior to to the question (thanks to the article that led me to this forum :slight_smile: ).
So basically, what you are saying is that I am scre*ed :laughing: - binary-per-version it is :sob:. If I understood the latter part, the Objective-C wrapper also works in forward-compatibility mode only it just gives me the advantage to do it since 5.0 instead of 5.1 (which is the case with Module stability)?

That sounds about right. The good news is life is better in the future; the bad news is it wasn't a better we could backport.

2 Likes

Just one question regarding module stability and Swift 5.1 prerelease versions: I noticed that pre-release version were not module stable with the actual released version of 5.1 (even though swift --version reported 5.1, only the swift-lang version differs). Is this correct? Xcode 11 seems to complain about it, it says the binary is compiled with a different version of Swift and needs to be recompiled.

The binary .swiftmodule files are not and are not planned to be stable across compiler versions. The stable module-description files are the textual .swiftinterface files.

2 Likes