Windows has partially supported static linking for a while now. It explicitly requires that modules declare their type at compile time: libraries are assumed to be dynamic unless otherwise indicated via the -static
flag. This is then serialised to the swiftmodule and wired through to IRGen to properly generate code with the appropriate DLL Storage.
While this allows for all user modules to be statically linked, it still was insufficient to enable static linking of the standard library. There has been a renewed push recently to enable the use of -static-stdlib
on Windows. At this point, the issues in IRGen and DependencyScanning have been worked through. This lifts the restriction at the level of code generation.
In order to deal with the collision of import libraries changes to the library naming conventions have been instituted. This is in accordance to examples from within the MSVC distributions. Akin to libucrt.lib
being the static distribution for UCRT and ucrt.lib
being the import library, the driver assumes that the same naming convention applies to only Swift libraries autolinked through import
statements. As this is relatively new, this has not been integrated into CMake, but is something that the user can easily workaround by adding -D CMAKE_STATIC_LIBRARY_PREFIX_Swift=lib
when configuring the project.
Assuming that the proper flags are used and users use the feature as intended, I believe that in addition to supporting statically linking the standard library here, this will formally introduce support for -experimental-hermetic-seal-at-link
. The -static
ensures that symbols are not re-exported from the consuming module, -static-stdlib
will also statically link the standard library, and it is UB to dynamically link against any other Swift library with -static-stdlib
as that would involve multiple copies of the Swift standard library in the same address space.
Unresolved Items
-
-nostartfiles
needs to be supported in the C++ driver (this is actively being worked on)
-
a new variant of the
swiftrt.obj
(at least on Windows) must be formed for the static library variant (this is actively being worked on - introducing
swiftrtT.obj
) -
We would need a static build of Foundation (
this is actively being worked on)
-
We would need a static build of libdispatch
-
The concurrency runtime needs to be taught how to deal with a static libdispatch.
-
The driver needs learn about the new
swifrtT.obj
-
The standard library build needs to be adjusted to enable building a static library variant for distribution. Note that this static library would still dynamically link against ucrt/msvcrt/msvcprt/vcruntime.
-
We need to package and distribute the new runtime build.
-
How do we ensure that
-static-stdlib
does not link against any other Swift libraries? -
Should
-static-stdlib
impact the BlocksRuntime? This is an extension for the C language and thus might need to be shared for the scenario where you may have a C host using Blocks which links against a statically linked Swift binary that uses the BlocksRuntime indirectly. I am tempted to say that BlocksRuntime should remain a dynamically linked component as it is a language extension, unlike GCD. -
Should
-static-stdlib
be synonymous with-static-sdk
? The SDK comprises of more than just the standard library. It contains at the very least:_Concurrency
_StringProcessing
Distributed
Foundation
Dispatch
,BlocksRuntime
XCTest
Testing
What makes this complicated is the fact that
BlocksRuntime
is something which could be dynamically linked against a fully sealed Swift containing binary. The restriction with static linking is that you may not have two copies of the standard library in the address space. However, the Blocks extension is a C extension and you may have a dynamically linked executable with a statically linked Swift runtime that also uses Blocks. Currently, we do not have a means for isolation of static vs dynamic linking of runtimes. To further complicate matters, BlocksRuntime on Windows was expected to always be dynamically linked (until recently - I just lifted this restriction with the introduction of-static-libclosure
to clang upstream).
Unaddressed Items
-static-executable
will not be addressed with these changes.-static-executable
requires a subsequent set of changes to build a static swift standard library with/MT
to get a static ucrt/msvcrt and a static msvcprt/vcruntime.- Swift Testing is not supported with static binaries/static standard library AFAIK.
- Although we use the thick swiftmodule format with SDKs on Windows, we cannot resolve the conflict between the static and dynamic variants currently. Technically, this shouldn't be a problem as long as we keep the
lib/swift
andlib/static_swift
distinction, but that currently is not very well handled on Windows.
I really wish that we named the registrar srtm{,S,T}.obj
as it is just the metadata registration