How does Swift 5.1 runtime work with older versions of iOS? - ios

About a year ago, if you wanted to use Swift 4.2 for iOS development, you would have to install Xcode 10, which meant that you used iOS 12 SDK. As part your apps deployment, Swift 4.2 runtime would automatically be bundled with your app binary. This would mean that user installing your app would essentially download a copy of that Swift runtime that will enable your app work.
However, ABI stability came with Swift 5, and you no longer needed to bundle a runtime if your deployment target was iOS 12.2, since the runtime was now part of that iOS version. However, if you wanted to support iOS 10 and iOS 11, this Swift runtime would still be bundled with your app binary, and it would behave the same way as described above.
Documentation on swift.org states the same:
Apps deploying back to earlier OS releases will have a copy of the Swift runtime embedded inside them. Those copies of the runtime will be ignored — essentially inert — when running on OS releases that ship with the Swift runtime.
So far so good. If you use Xcode 10.2 with Swift 5.0, and you deploy your app to older iOS releases, you will still bundle Swift 5.0 runtime with it. Then, if your app is running on iOS 12, app will use the runtime provided by the iOS, and if it's running on e.g. iOS 11, it would use the runtime that was bundled as part of the app binary. Now the first question: Is that a correct assumption?
Now we come to Swift 5.1 and iOS 13 that will be released in September. Swift 5.1 includes some additional runtime features, e.g. opaque result types, which require Swift 5.1 runtime.
In WWDC 2019 session 402 "What's New in Swift", the speaker, when discussing the Swift 5.1 feature Opaque Result Type (SE-0244), mentions that the feature will only work on new OSes:
Requires new Swift runtime support
Available on macOS Catalina, iOS 13, tvOS 13, watchOS 6 and later
This is the confusing part for me. Wouldn't Swift runtime 5.1 be shipped with your app regardless if you support older iOS versions (e.g. iOS 10 as well), thus enabling it to use these new runtime features or am I just not understanding this correctly?

Now the first question: Is that a correct assumption?
Yes, that is correct.
Wouldn't Swift runtime 5.1 be shipped with your app regardless if you support older iOS versions (e.g. iOS 10 as well), thus enabling it to use these new runtime features or am I just not understanding this correctly?
The embedded runtime is not exactly the same runtime as the one found in your OS. E.g. the runtime in your OS is tightly integrated:
By being in the OS, the Swift runtime libraries can be tightly integrated with other components of the OS, particularly the Objective-C runtime and Foundation framework. The OS runtime libraries can also be incorporated into the dyld shared cache so that they have minimal memory and load time overhead compared to dylibs outside the shared cache.
Source: https://swift.org/blog/abi-stability-and-apple/
Of course, the embedded runtime cannot be tightly integrated into older systems. The embedded runtime can only support features that were already possible on the current system it is being executed. Features that require a newer systems are simply not present when your app runs on an older one.
Note that this has never been different for ObjC. If a class or a method only exists starting with a certain OS version, you can still deploy backwards to older system versions but then you cannot use that class/method there as it simply doesn't exist.
if (#available(iOS 13, *)) {
// Code requiring iOS 13
} else {
// Alternative code for older OS versions
}
or in Swift:
if #available(iOS 13, *) {
// Code requiring iOS 13
} else {
// Alternative code for older OS versions
}
Just like with ObjC, new Swift features will only be available for new OSes from now on. Only if it is possible to make these features also available for older OSes, regardless if these shipped a runtime or need to use the embedded one, this feature may also deploy backwards, though not necessarily all the way.
E.g. 10.15 introduces a new feature in its bundled runtime, then maybe this feature can also be made available for 10.14 and 10.13 using a shim library but not for 10.12 down to 10.9, then this feature will be tagged as "Requiring macOS 10.13 or newer".
If you deploy to 10.15, nothing has to be done, as the runtime of 10.15 supports the feature. If you deploy to 10.14 or 10.13, then the compiler will add shim library (like it would add an embedded runtime) and on 10.13 and 10.14 the code in this library will be used while on 10.15 and later the code in the runtime will be used. If you deploy to systems earlier than 10.13, this is okay but you must not use this feature on these systems then.
Of course, if a new feature can be made available even trough the embedded runtime, it can certainly also be made available using a shim library for all systems that shipped with an own runtime which just didn't support this feature, as the shim library can then use the same code that the embedded runtime uses.
The ability to sometimes make new features available even to older systems is explained by the very last question on that page:
Is there anything that can be done to allow runtime support for new Swift features to be backward deployed to older OSes?
It may be possible for some kinds of runtime functionality to be backward deployed, potentially using techniques such as embedding a “shim” runtime library within an app. However, this may not always be possible. The ability to successfully backward-deploy functionality is fundamentally constrained by the limitations and existing bugs of the shipped binary artifact in the old operating system. The Core Team will consider the backward deployment implications of new proposals under review on a case-by-case basis going forward
Source: https://swift.org/blog/abi-stability-and-apple/

Related

Is Swift ABI compatible between minor versions?

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).

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.

Adding Swift to project increase size substantiously. How and when can it be avoided

I have a small app written in Objective-C. It was something like 3 Mb of size.
When I added one Swift file the size of my archive grew up to 10 Mb.
What i found is that Swift embeds it's actual library in every project it is used in. This is necessary to be able to run the project even in case that Swift library changes in the future.
But 8 Megabytes is a huge overhead for small projects. Maybe there is some information about when Swift will get stable library that will be embedded in OS?
Or maybe there are some flags that can be added to the project that force compiler to use standard Swift library embedded in iOS?
Swift is still changing. So at the moment the runtime has to be included with every app. Maybe Apple will include the Swift runtime in iOS once the development of Swift slows down.
Swift source code had to be adjusted after almost every release of Xcode since the 6.0 betas. The runtime has changed at the same time the compiler has. iOS can't use a standard swift library, but has to use the one the app was compiled and linked with.
See this explanation by Apple.
you can trust that your app will work well into the future. 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
While your app’s runtime compatibility is ensured, the Swift language itself will continue to evolve, and the binary interface will also change.
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
Not using Swift is the only way to keep your app size down.
Since Swift 3.0 won't deliver a stable ABI, this will remain the same for the time being. So in a year or two probably translates to Swift 5.0 in 2018.

iOS6 does not have libxml2.2.7.3.dylib.are there any substitutes?

I have made a project in xcode4.2 and when i opened it with xcode4.5 ,iOS 6 SDK it gives error 255 and the reason seems to be absence of libxml2.2.7.3.dylib.
What are my options is there any other substitute provided?
thanks
Xcode 4.5, or more precisely the iOS6 SDK (because the libraries available are dependent of the SDK, not the Xcode version) still has libxml2.2.dylib.
It is just probably not the version 2.2.7.3 but a newer, up-to-date 2.2.x.y version that is embedded in the SDK now.
You should generally not link your application with a specific version of libraries like that, but better with a generic version like libxml2.dylib or libxml2.2.dylib.
Generally libraries respect the semantic versionning, meaning that:
their major version change only when the API is not backward compatible with the previous major version,
the minor version change only when new methods are introduced in the API, but are still compatible with the previous API,
patch version means that some bug fixes have been made, but the API hasn't changed.
So if libxml respect this semantic versioning (and I guess is does, like quite every standard library), every version 2.2.x.y of libxml is API-compatible with any other 2.2.x.y version and will continue to work with your program. A hypothetic new version libxml2.2.x.z will simply fix bugs, but won't introduce any change in its API. And when a version of libxml2.3.x.y will arise, it will still be backward compatible with 2.1 and 2.2 too (just adding new features but not dropping the existing ones).
Thus, you can safely link your application with the generic library version libxml2.dylib, which will automatically point to the latest 2.x.y.z version available in the current SDK. Or link with libxml2.2.dylib which will point to the latest 2.2.x.y version (these are symbolic links to the latest versions, as all UNIX-like OSes use to do)
I think SDK for iOS6 just contains different version of libxml

Resources