<p>ABI stands for <em>application binary interface</em>, and it represents how different precompiled components of a program interact. This can be a program calling out to an OS function or part of the language runtime, or even to a library if it’s dynamically linked.</p>
<p>In some languages, such as Swift, the standard library is <em>ABI stable</em> — that is, even source-breaking changes to the runtime or standard library must remain backwards-compatible with already-compiled programs. Additionally, programs compiled with a newer version of the compiler that don’t use new runtime components must continue to work with old versions of the runtime and standard library.</p>
<p>ABI stability causes challenges for language and library evolution. Some otherwise positively-received changes to Swift have been rejected since they can’t be implemented without breaking ABI. Other languages that aren’t ABI-stable don’t need to worry about this, and can change or remove existing features (though that may necessitate a major version bump).</p>
<p>With that background out of the way: When is ABI stability a net positive? What factors would cause a language to restrict itself in this way?</p>

<language-design><compilers><standard-library><abi-stability>
When is ABI stability “worth it”?
<h2>It is actually very simple.</h2>
<p>A stable ABI is needed when you need to link against libraries <em>after compilation</em>. If you have all the sources for your libs, you can just recompile it all with the new abi.</p>
<p>The problem is that there is no adult supervision in computing. As a result you often have to do this when it is actually unnecessary. Take the gamedev on linux example. The linux kernel syscalls don't change, ever. So you can build a static binary and never worry about linking. However, for graphics you are requiered to dynamically link against a userspace driver. This means the C abi must be stable for this to work.</p>
<p>Many &quot;modern&quot; languages require a precompiled runtime in addition to all the other garbage in order to run. This is a complete waste because those who wan't their software to actually run on someone else's machine bundle the runtime with their application. At which point there is <strong>no purpose for it to be a standalone binary!</strong></p>
<p>If you are writing your own language there is no reason to have a stable abi unless you intend to distribute precompiled libraries.</p>
<p>I'm a believer that languages should be made finished and not modified, in which case your abi is stable because your language is stable.</p>

CC BY-SA 4.0
2023-06-23T15:44:39.790Z
2023-06-23T15:44:39.790Z
Sam H. Smith
<h1>Game development</h1>
<p>Most of the time, games get little to no updates after a certain time passes. In desktop platforms, this can often mean that after some time they may not run at all. Linux games developed in the early 2000s for example have recently broken due to SDL updates, which is relatively easy to fix by replacing the original SDL. If the C standard library were to suffer breaking changes, this would be way harder to fix. Something similar did happen with glibc recently on an even deeper level, where they broke the mechanism used to find functions by name in libraries: <a href="https://lwn.net/Articles/904892/" rel="nofollow noreferrer">https://lwn.net/Articles/904892/</a></p>

CC BY-SA 4.0
2023-06-20T18:30:01.777Z
2023-06-20T18:30:01.777Z
kouta-kun
CC BY-SA 4.0
2023-06-20T18:50:44.180Z
I’ll point out that the C standard library did have a breaking change just this year, but afaict only in the uncommon case of `realloc(ptr, 0)`.
Bbrk24
<p>This is far from a comphrehensive answer but</p>
<h2>When you need hot reloading</h2>
<p>Some systems try to be always on. An upgrade requires that a new function or datastructure replaces another in place without the application being restarted or the rest of the code being recompiled. This could be signficantly harder without a stable ABI.</p>
<h2>When your library is the target for other applications</h2>
<p>Consider the C standard library and Posix. One is mandated by the language the other by the OS. However they overlap considerably.</p>
<p>You are not free to change the ABI for a compiler is it is mandated by the OS. If the OS ABI changes all packages on that OS may have to be recompiled.</p>
<p>The same reasoning applies if your language ecosystem includes a package manager which allows binary packages. They may break if the ABI changes and so will need to be re-compiled. To (re)compile packages from source requires your package manager to also be a compiler.</p>
<p>This is typically assuming ahead of time compilation.</p>
<h2>When you don't want to break contracts</h2>
<p>If the language is interpreted code may run but a change in the ABI might mean subtle a change in the contract so something may cease to comply with the contract introducing a subtle bug.</p>
<p>I haven't got a good real world example in mind off the top of my head but say you have a function</p>
<pre><code>[requires: x &lt; 100]
f(x: int) -&gt; int
</code></pre>
<p>If you change that to:</p>
<pre><code>[requires: x &lt; 200]
f(x: int) -&gt; int
</code></pre>
<p>In a new version of your API then a caller could legitimately think its okay to invoke f(101) but that call could go to an implementation using the old contract (x &lt; 100) leading to undefined behaviour.
This is a case where you should update the API version number (to indicate a breaking change) even though you might not be able to encode the contract in the interface itself.</p>
<p>Now consider the same logic applied to the case of an <a href="https://stackoverflow.com/a/3784697/1569204">ABI instead of an API</a> and replace the API pre-condition with an equivalent property of your ABI.</p>
<p>Say you pass a pointer and change who is responsibile for deleting the associated memory. The call may still appear to succeed but you will have a potenital resource leak.</p>

CC BY-SA 4.0
2023-06-21T08:10:53.050Z
2023-06-22T01:49:46.643Z
2023-06-22T01:49:46.643Z
Bruce Adams
CC BY-SA 4.0
2023-06-21T18:16:24.023Z
Could you elaborate on that last one? If everything is distributed in source and either interpreted or JIT’ed, there’s not necessarily an ABI to speak of, is there?
Bbrk24
CC BY-SA 4.0
2023-06-21T20:43:29.357Z
I've tried to elaborate that in the answer.
Bruce Adams
CC BY-SA 4.0
2023-06-21T21:03:47.317Z
That sounds more like A**P**I stability, which is different. Swift has a concept of "source-breaking ABI-stable changes", which I think that would fall under.
Bbrk24
CC BY-SA 4.0
2023-06-21T23:44:26.717Z
Maybe a better example for contract breaking would be when C# added non-nullable types, turning what was before a simple `int` to `int?`.
kouta-kun
CC BY-SA 4.0
2023-06-22T01:01:53.333Z
Yes indeed its not a good example.
Bruce Adams
CC BY-SA 4.0
2023-06-22T01:40:27.017Z
The very last paragraph there -- the call signature is the same but ownership changes -- is a much better example.
Bbrk24
# When is ABI stability “worth it”?
Posted by: username_0 on 2023-06-20
ABI stands for *application binary interface*, and it represents how different precompiled components of a program interact. This can be a program calling out to an OS function or part of the language runtime, or even to a library if it’s dynamically linked.

In some languages, such as Swift, the standard library is *ABI stable* — that is, even source-breaking changes to the runtime or standard library must remain backwards-compatible with already-compiled programs. Additionally, programs compiled with a newer version of the compiler that don’t use new runtime components must continue to work with old versions of the runtime and standard library.

ABI stability causes challenges for language and library evolution. Some otherwise positively-received changes to Swift have been rejected since they can’t be implemented without breaking ABI. Other languages that aren’t ABI-stable don’t need to worry about this, and can change or remove existing features (though that may necessitate a major version bump).

With that background out of the way: When is ABI stability a net positive? What factors would cause a language to restrict itself in this way?
**Tags:** language-design compilers standard-library abi-stability
---
## 3 answers
### Answer by username_3 on 2023-06-21. Score: 7 | Accepted answer
This is far from a comphrehensive answer but
When you need hot reloading
Some systems try to be always on. An upgrade requires that a new function or datastructure replaces another in place without the application being restarted or the rest of the code being recompiled. This could be signficantly harder without a stable ABI.
When your library is the target for other applications
Consider the C standard library and Posix. One is mandated by the language the other by the OS. However they overlap considerably.
You are not free to change the ABI for a compiler is it is mandated by the OS. If the OS ABI changes all packages on that OS may have to be recompiled.
The same reasoning applies if your language ecosystem includes a package manager which allows binary packages. They may break if the ABI changes and so will need to be re-compiled. To (re)compile packages from source requires your package manager to also be a compiler.
This is typically assuming ahead of time compilation.
When you don't want to break contracts
If the language is interpreted code may run but a change in the ABI might mean subtle a change in the contract so something may cease to comply with the contract introducing a subtle bug.
I haven't got a good real world example in mind off the top of my head but say you have a function
[requires: x < 100]
f(x: int) -> int

If you change that to:
[requires: x < 200]
f(x: int) -> int

In a new version of your API then a caller could legitimately think its okay to invoke f(101) but that call could go to an implementation using the old contract (x < 100) leading to undefined behaviour.
This is a case where you should update the API version number (to indicate a breaking change) even though you might not be able to encode the contract in the interface itself.
Now consider the same logic applied to the case of an ABI instead of an API and replace the API pre-condition with an equivalent property of your ABI.
Say you pass a pointer and change who is responsibile for deleting the associated memory. The call may still appear to succeed but you will have a potenital resource leak.
> **Comments:**
> **username_0** (2023-06-21): Could you elaborate on that last one? If everything is distributed in source and either interpreted or JIT’ed, there’s not necessarily an ABI to speak of, is there?  
> **username_3** (2023-06-21): I've tried to elaborate that in the answer.  
> **username_0** (2023-06-21): That sounds more like A**P**I stability, which is different. Swift has a concept of "source-breaking ABI-stable changes", which I think that would fall under.  
> **username_2** (2023-06-21): Maybe a better example for contract breaking would be when C# added non-nullable types, turning what was before a simple `int` to `int?`.  
> **username_3** (2023-06-22): Yes indeed its not a good example.  
> **username_0** (2023-06-22): The very last paragraph there -- the call signature is the same but ownership changes -- is a much better example.  
---
### Answer by username_1 on 2023-06-23. Score: 1
## It is actually very simple.

A stable ABI is needed when you need to link against libraries *after compilation*. If you have all the sources for your libs, you can just recompile it all with the new abi.

The problem is that there is no adult supervision in computing. As a result you often have to do this when it is actually unnecessary. Take the gamedev on linux example. The linux kernel syscalls don't change, ever. So you can build a static binary and never worry about linking. However, for graphics you are requiered to dynamically link against a userspace driver. This means the C abi must be stable for this to work.

Many "modern" languages require a precompiled runtime in addition to all the other garbage in order to run. This is a complete waste because those who wan't their software to actually run on someone else's machine bundle the runtime with their application. At which point there is **no purpose for it to be a standalone binary!**

If you are writing your own language there is no reason to have a stable abi unless you intend to distribute precompiled libraries.

I'm a believer that languages should be made finished and not modified, in which case your abi is stable because your language is stable.
---
### Answer by username_2 on 2023-06-20. Score: -2
# Game development

Most of the time, games get little to no updates after a certain time passes. In desktop platforms, this can often mean that after some time they may not run at all. Linux games developed in the early 2000s for example have recently broken due to SDL updates, which is relatively easy to fix by replacing the original SDL. If the C standard library were to suffer breaking changes, this would be way harder to fix. Something similar did happen with glibc recently on an even deeper level, where they broke the mechanism used to find functions by name in libraries: <https://lwn.net/Articles/904892/>
> **Comments:**
> **username_0** (2023-06-20): I’ll point out that the C standard library did have a breaking change just this year, but afaict only in the uncommon case of `realloc(ptr, 0)`.  
---
