How do Apple OSes provide ABI-stable libraries?

As I understand it, there’s ABI stability on Apple platforms, but not Module stability.

What I don't understand is, how can you have one without the other? How are iOS frameworks, for example, able to provide this functionality to Swift clients now, but a third party can't do the same?

Module stability and ABI stability are two different things. Module stability is concerned with build time issues, ABI stability is concerned with run time issues. Third parties may do so, but the understanding that they can be broken at anytime as there is still no official specification for other platform's structure layout that the compiler guarantees to adhere to.

But that doesn't answer my question about how Apple is able to do this. I can write code that imports an Apple framework, and I don't need to bundle run-time libraries with my app. How is this different from what a third-party module developer would have to do?

If you are building a Swift "framework", Apple can't and you can't because of module instability, since the module definitions are part of the framework, which are compiler version specific. If you build a library (static or dynamic), an executable linked with your library will work on newer versions of the operating system, because the Application Binary Interface (ABI) enforced by the compiler has stabilized, so that run-time libraries can maintain backward compatibility for executables that have linked the older versions of the library.

When you import a framework, that is part of the compile process. Modules are artifacts of the compile process. Once compiled and linked, executables are not aware of the modules anymore. That's why you run an executable on an older O/S.

Imagine this is like C/C++/Objective-C but the header (.h) files for using the library are generated by the compiler. Now imagine this header file format changes with each compiler release. What you need to do is regenerate the header files every time you change the compiler, and Apple can do that easily since the compiler is bundled in the SDK among the header files. Third parties will have a rougher time because they'll need to generate different header files for each compiler release.

2 Likes

Sure, you could do this on another platform as well. On Linux, for example, if you have a way to have the distribution provide packages for the runtime libraries, you would not need to package them. But, the compiler used to build that must be the exact same one (ignoring the fact that you may be able to get away with some divergence in reality). Failure to do so means that your program may or may not work with the runtime on the system since the compiler makes no guarantees about the ABI on non-Darwin targets currently.

What it comes down to - Apple has made the necessary engineering investment to provide a guarantee over the language ABI and governs the releases of their OSes to ensure that the runtime conforms or provides a mechanism for backwards compatibility. If someone else wishes to put forth that effort, nothing prevents other platforms from having a guaranteed "stable" ABI. (Just to give a rough guide for effort required: to this day, Microsoft does not provide a stable C++ ABI, nor does any other platform, except perhaps Apple?) This is simply a contract, and there are obligations towards fulfilling that contract that Apple has stated that they will assume.

3 Likes

So the answer is, Apple provides a new module interface with each release of Xcode?

The SDK, which includes the module interfaces and the compiler, is part of Xcode. I assume they rebuild everything from source for each release so the module interfaces would be regenerated too.

1 Like