Question: Is Swift ABI stable on Windows? How far are we from there?

Just out of curiosity — MSVC has been stated to be ABI compatible for 7 years by the time, so it seems an achievable and reasonable goal to reach ABI stability on top of it.

Once ABI stability on Windows is a thing, we can start to split the runtime off the toolchain and distribute it separately, enabling different toolchains and products sharing the latest runtime libraries.

No, there is no guarantee of ABI stability on Windows and is a non-goal. I'm not sure I read that document the same way - they only say that 2015-2022 are ABI stable, not that it will be indefinitely. The runtime is already split and can be re-distributed, at least that is the intention. They are parallel installable, the problem is that we need to figure out how to version the DLLs so as to permit the co-installation still resolving properly.

2 Likes

While this is certainly useful, I don’t see it as more achievable. We have to either distinguish different versions by file name (diverged from other platforms) or let the executable inject DLL path first (hard unless we use a custom import library IMO). A low-cost solution of this is to use an xcrun-like tool to shim and inject the paths, which I believe still need broad discussion and investigations.

ABI stability on Windows is definitely not a short-term goal, but it should be something on the roadmap. Unlike Linux, which doesn’t guarantee a stable ABI, I believe the post implies that MSVC will keep ABI stable in no less than 2 years, before the next Visual Studio release (likely 2025) comes out. By the time it should cover all the supported Windows versions, including LTSC. It is also very likely that the story will continue ever since, making a natural ground for Swift ABI stability to fit in.

Let’s look back in 2019, when @jrose wrote ABI Stability and More:

As development of Swift on Linux, Windows, and other platforms matures, the Swift Core Team will evaluate stabilizing the ABI on those platforms.

And @tkremenek spoke of ABI on Linux on the forums:

Finalizing the ABI on Linux is less valuable in the server domain (one of the most active use cases for Swift on Linux) than the (say) iOS app domain since service executables are routinely built from source for deployment in that domain anyway.

The Windows story is more like Darwin than Linux. It is client-dominated. Binary and even commercial libraries are common. It has a full and stable set of system APIs. All these make ABI stability on Windows more promising and valuable.

1 Like

I know that blog post sounds like ABI stability is a goal in and of itself, but that’s not necessarily true. ABI stability lets you do one thing in particular: closed-source libraries don’t need to be recompiled when the compiler changes. That’s useful for people who write closed-source libraries, and it was certainly requested fair amount leading up to Swift 5, but for everybody else it doesn’t matter so much. Library evolution likewise allows closed-source libraries to depend on other closed-source libraries, and apps to depend on libraries outside their “app bundle” (on Windows, the program directory)

What was different about Apple is that Apple wanted to use Swift in the OS, and always did. That’s why Swift jumped through so many hoops to get library evolution working; not just the availability model, but the part where libraries could change out from under an already-built app without breaking ABI. I don’t think there’s any driver of that from Microsoft at this time, and I don’t think there’s likely to be since their everyday platform APIs are for the CLR, not compiled to native code. But I fully admit I don’t know much about the Windows development situation these days.

So without that, the main driver of ABI stability + library evolution would be so multiple apps could share common libraries without duplicating them. The main driver of ABI stability without library evolution (but also included in the above) would be distributing closed-source libraries for app developers. Are either of those important enough goals on Windows that we want to lock ourselves in? Commit to everything public having the memory layout it does, using the runtime functions and calling conventions it currently has? We’ve talked idly before about making classes COM-compatible on Windows; should we give up on that, or limit it? Those are the kinds of questions to ask for deciding when to commit to an ABI.

For Apple, the answer was obviously “yes, eventually”, and because of that there are some suboptimalities in the Swift 5 ABI. Some get worked around with deployment targets, as a proxy for the runtime version, but others are stuck forever. For Linux, the answer thus far has been “no, it doesn’t provide enough benefit”, because there’s not nearly as big a closed-source library ecosystem, particularly not for the server focus Swift has gone with. For Windows? I trust @compnerd to evaluate whether the benefits make it worth it, but at the moment I don’t see a strong reason to push for it.

But maybe I’m just missing it. What would you, specifically, do with a stable ABI on Windows, that you can’t do today?

P.S. As discussed, Swift ABI stability does depend on the underlying C ABI being stable*, but that isn’t really the main concern; glibc is pretty stable in the forward-compatibility direction, but that doesn’t automatically mean we want to stabilize the Swift ABI on Linux.

* Technically I think this is a library limitation more than a language limitation; I believe you could define the Swift ABI without referring to C at all, but as soon as you call a function provided by a C-based library, from memory allocation to I/O to COM to a custom library, you’re back depending on C again.

P.P.S. There’s another benefit to ABI stability, which is writing cross-language bridges that don’t go through C. But while that’s not an anti-goal for Swift, it isn’t really something the project has focused on either. It’s technically possible but in practice only the Swift compiler can really tell you how to call Swift APIs, so any tool that interoperates with Swift is likely to do so very narrowly anyway, or embed SourceKit / the compiler in the tool itself. But I digress.

4 Likes

The main benefits from my side:

  • Allowing different toolchains and applications to share the same runtime libraries;
  • Enabling closed-source library to be distributed more freely.

Of course these two things doesn’t happen for Swift now, but they’re really common on Windows (for the C++ world) — much more common than Linux, and, AFAIK, even compared to macOS / iOS.

I agree that locking the ABI now is pretty unwise, since Swift on Windows is far from mature at the moment. I simply wants to check if this is still on the roadmap. It should be something to consider before we invest too much into working around an ABI-unstable Swift on Windows.

2 Likes

This is already needed on Linux as well. Yes, DT_RUNPATH helps, but the naming is needed and an actual issue. I am not sure if I like the xcrun-style tooling.

I fully agree with all the points here. I think that the first point bears re-emphasizing, most issues like toolchain size and all really replicated across Windows and Darwin and Linux is the odd one out.

I agree with @jrose here - ABI stability isn't something that is currently something that has a reason to be pursued.

Re-distributing the closed source libraries is possible with re-packaging the runtime. I have tried to make that easy, and the runtime is a separate MSI actually. It should be possible to even convert that to a MSM if desired.