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.

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

1 Like

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.

2 Likes

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.

Well, seems that one module that missed our initial count was the Volatile module. However, in the mean time, the Differentiation module is now packaged up.

This process has uncovered a number of issues and fixed up code generation in a variety of ways. Unfortunately, we did find a new instance of incorrect code generation in the Differentiation module as part of the work to build the runtimes dynamically with the new build system. Additionally, a new issue has been identified in the swift-driver wrt library search paths when building with the new runtimes build which will need to be addressed as well.

It's nice to hear Windows is finally getting a static build.

Since work on the runtime is being done, would the issue of the runtime not being able to shut down, when the Swift product itself is a DLL included from a C program, rather than a standalone program, also be resolved?

Is this windows specific? Is there a filed issue to track this issue? I’m trying to address part of this type of usage - the intention of always requiring libclosure and libdispatch (even in static linking cases) to be distributed due to the dynamic linking is related to this use case - hosting within a C program.

I've been busy with other projects lately, but I'll make an effort to make an MRE once I'm free.

I previously mentioned in a different thread that, on shut down, the runtime seems to endlessly loop on FlsFree.

As for other platforms, I don't have a Mac to test with, and I'd need to study the process for building and using an .so file on Linux. I think it's not quite the same as a DLL, but it would be interesting to see if there are similar results.

@compnerd Given your previous comments:

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.

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.

I'm not sure I understand the role of Foundation here long-term, and maybe in Swift in general. Talking about Windows, do you mean that it will be part of the/a static runtime at some point?

Yes, it is meant to be part of the static SDK, however, we were unable to merge the changes for supporting that due to the lack of updated snapshots. The last sentence in the quote are relevant: "This is a temporary limitation, pending updates".

Each of the libraries would be statically available, allowing you to statically link the Swift content once we are able to switch to the new "experimental" SDK as the default.

Ah, cool. I asked because I was more concerned that Foundation would be statically linked into the executable no matter what, but the "statically available" sounds much better. Thanks.

No, we are not dropping the dynamic libraries. The default behvaiour on Windows has been and will remain dynamic linking. However, there is enough interest in the static linking (and there is a use case in the toolchain build as well) that I've been working on lifting the static linking restriction. If you want to statically link to the Swift runtime, it will be an opt-in -- you must pass -static when invoking swiftc.

1 Like

As a follow up to the original post - I believe that the latest snapshot should have Foundation and Differentiation as well. I expect that Volatile should also be soon included in the packaging.

The C++ Interop and SwiftRemoteMirror are still under construction, but hopefully will be complete soon.

If this prebuilt snapshot works:

https://download.swift.org/development/windows10-arm64/swift-DEVELOPMENT-SNAPSHOT-2025-08-05-a/swift-DEVELOPMENT-SNAPSHOT-2025-08-05-a-windows10-arm64.exe

I'm happy to test the static thing one of these days and report back here.

1 Like

Awesome, thank you! BTW, note that you will need to adjust SDKROOT in your environment to point to the new experimental SDK. There are a few extra flags that are currently required:

-static -static-stdlib -Xfrontend -use-static-resource-dir -Xcc -static-libclosure -Xcc -Ddispatch_STATIC

I intend to remove the need for the last 4 (-Xcc -static-libclosure, -Xcc -Ddispatch_STATIC) as per the previous messages - libclosure and libdispatch will be dynamically linked (they are C libraries).

I hope to remove the 2 preceding options as well (-Xfrontend -use-static-resource-dir) once things have settled (this is a bug in the swift-driver - we should infer this from -static-stdlib)

-static: indicates that you should build a static library (you will need need this for any non-executable targets)
-static-stdlib: indicates that you should build and link against the static standard library

Longer term, when building with SPM, the intent is that SPM will appropriately add -static when building the library. That will leave a single flag that developers will be responsible for: -static-stdlib.

@ArtemC @dschaefer2

@compnerd Does this mean a Swift executable linked with -static-stdlib will still be dependent on a libclosure.dll and libdispatch.dll?

If so, what is the use case of having a static runtime at all if there are still some non-system DLLs required?

And will the static runtime be compatible with use of the static MSVCRT?