Upcoming changes to Windows Swift SDKs

Hello Windows Developers,

This post has two aims:

  1. To notify users of a significant upcoming change.
  2. To recruit additional early testers.

Over the past few months, there’s been quiet but substantial progress on improving the Swift SDK for Windows. As these changes near completion, I’m seeking broader external testing and validation to help surface any remaining issues.

In recent builds—specifically those from The Browser Company, since there haven’t been releases on swift.org for over a month—the Swift SDK for Windows has introduced a new platform SDK: WindowsExperimental.sdk.

Experimental SDK

While still labeled experimental, this SDK is now considerably more stable. It represents a build of the runtime using the new build system developed by @etcwilde, @justice-adams-apple, @edymtt, and others. In theory, this should be functionally identical to the existing runtime.

Static Runtime

A key aspect of this iteration is the distribution of a static variant of the SDK for Windows—a static runtime build.

Current Limitations

At present, this SDK lacks the following components:

  1. Differentiation
  2. SwiftRemoteMirror
  3. C++ Interop overlays

Notably, Foundation support is absent. This is because Foundation, when built for static linking on Windows, conflicts with system libraries—specifically due to ICU collisions. This is a temporary limitation, pending updates.

Details:
Windows ships ICU, and Foundation also bundles ICU. With static linking, the system ICU takes precedence, causing runtime conflicts and crashes. This will eventually be mitigated via ICU’s symbol renaming, but the current ClangImporter doesn’t support this.

Recent compiler features—macro-based alias importing (c66d43e) and ImportDeclAliases (c08372a)—require updating to the latest compiler in swift-foundation CI before Foundation can be rebuilt for static linking.

Foundation support will be restored once these PRs are merged:

Other missing pieces are being addressed:

  1. Differentiation overlay search/link
  2. Build Differentiation in experimental SDK
  3. Package _Differentiation in experimental SDK

For C++ Interop overlays, support must still be added to the new build system.

The SwiftRemoteMirror module revealed further ODR violations that must be resolved before it can be included.

Details:
Both the Swift Runtime and SwiftRemoteMirror are host libraries embedding copies of LLVM libraries (ADT, Support, and for RemoteMirror, BinaryObject and Object). We pin and namespace the first two to avoid conflicts, but need to update the pinned version and apply this to the new libraries as well.

To minimize the TCB, binary size, and maintenance, we trim interfaces to essentials. This work must be repeated for the updated libraries.

Dynamic Runtime

As the runtime build converges, the dynamic variant will also be added to the SDK. This will ultimately make the experimental SDK a full drop-in replacement for the existing one.

Notable Changes

A user-visible change: dynamic modules will now embed a manifest resource, enabling use with Win32 SxS. This addresses a longstanding limitation—previously, only a single runtime could be installed. With embedded manifests, application authors can specify the runtime version, and the system will load the correct version from those installed. If installed with elevated privileges, the runtime can be placed in the GAC for sharing across applications, removing the need to bundle it with every executable.

For developers: Windows versioning uses a four-part, 16-bit value (65535 per component). Consequently, only one development runtime can be installed at a time, though multiple release/RC runtimes are supported. Runtimes are versioned as [major].[build] (e.g., 6.1.0), with the build number incrementing per release.

Testing

The new runtime has not been exhaustively tested, but it has passed enough testing to warrant broader use. Testing so far has focused on building and using the early swift-driver on Windows. PR #76574 enables this, and while it’s not ready to merge due to Foundation issues (and a known CI-specific failure under investigation), it suffices to build the toolchain and test suite.

Implications

Care has been taken to minimize disruption, but the SDK isn’t yet a seamless replacement. It installs in parallel and requires explicit selection. The simplest way is to update the SDKROOT environment variable to point to the new SDK, or use the -sdk ... flag in your Swift invocation. Work is ongoing to enable easier switching via tcrun (e.g., tcrun -sdk WindowsExperimental swift build). Contributions are welcome.

As dynamic runtime packaging matures, further work will be needed to generalize SDK packaging. @mhegazy is also working on installer improvements to support additional toolchain variants (e.g., NoAsserts).

How to Get Involved

Note that this is a call for early adopters. Due to the Foundation changes not being merged, testing this currently will require applying the changes and building a toolchain locally. If your applications could benefit from static runtime linking or you’re interested in experimenting, please build a new toolchain with the Foundation changes and try the new SDK, reporting any issues. Broader help will especially be needed for testing and validating the dynamic builds and Win32 SxS support to ensure readiness for production use. I intend to make a follow up post in the coming weeks (:crossed_fingers:) once the necessary changes are merged and we have a toolchain with the new SDK in its entirety.

As usual, please report any issues through GitHub Issues.

14 Likes

Without understanding all details, it sounds great and I would use the new toolchain as soon as Foundation support is there. Thanks to all involved.

Is this static linking “complete”, resulting in a single executable file, without any DLLs needed? What about link time optimization for a smaller executable?

It is great if the large ICU data does not have to be part of the application. (So theoretically the Windows application could behave differently from the macOS application because of different ICU data, but this should be acceptable.) A little off-topic here, how is this on Linux systems, an installed ICU linux package could also be used there.

No, it is not a fully static binary, it is the Swift runtime that is statically linked. Longer term, the goal is that the only dependencies for such a program would be libclosure, libdispatch, and MSVCRT.

The work that I've been doing to support static linking does enable a future possibility of such a runtime distribution. It would require an additional runtime library flavour to be built and packaged. This is a bit tricky since we would need to figure out how to:

  1. package this into the SDK (without collisions)
  2. how to allow the user to control the C/C++ runtime linkage (i.e. driver level flags)

No, the ICU data is still part of the application - it is part of the Foundation library itself. That is the cause of the current issue. The ICU that Foundation uses is not the standard ICU but has extensions/changes. As such, we need to use the ICU variant that is shipped with Foundation. This problem exists on all the environments. It is just that on Apple platforms, that ICU is the system ICU and Foundation is shipped as part of the OS itself.

Thanks @compnerd, dealing with DLLs is so painful for distribution. Eager to give these things a new try soon.

Are you aware of the MSM that we package up in the toolchain distribution? That should allow you to generate a MSI without having to do the manual work of the distribution of the DLLs - you simply reference the MSM in your MSI.

Uhm, I'm afraid it doesn't apply to my use case. I'm developing a cross-platform Swift library that I'd like to eventually distribute as a static library with C headers + @_cdecl on all supported platforms, not only Windows. Objective-C was the first pain point, and I happily migrated it all to C. Now, as you also mentioned, Foundation is another complex piece of the runtime. Concurrency, I'm not sure yet. Linux has probably been trickier than Windows.

It's a long journey, but I'm enjoying the evolution that Swift is taking to become multiplatform. The silent work you guys are putting into this is golden. One year ago I would never have thought that I could make my Swift library run on so many platforms with reasonable work. Not trivial, but absolutely reasonable.

At least on Windows, this is currently not possible with SPM, only with CMake as SPM does not properly build libraries currently (it builds all objects for DLLs which is why you see so many warnings from the linker).

Good to know! Yes, I noticed that SPM support across platforms is a bit inconsistent.