Swift on Windows Status

I spent some time looking into this today and trying to get things working. It looks like the status of things hasn't changed much: static linking still works and dynamic linking is an issue.

With regards to dynamic linking, we're waiting on Full Type Metadata On Windows - #9 by Joe_Groff, which is a little beyond my ability to fix. @compnerd, do you have any updates on how that's going? Alternatively, @Joe_Groff – you suggested a possible implementation for this; is it likely to be a major change, or is it a small change that happens to be tricky in how it interacts with other systems? If either of you were able to help implement those changes it would be a major step forward for Swift's usability on Windows, and would help lower the bar for other people to contribute to the port.

In terms of actually getting non-trivial Swift programs working on Windows: here are the notes I took for my process. They were mainly written for my own reference, so I'm happy to elaborate on any parts that don't make sense. My process is focused on cross-compiling to Windows from Ubuntu on Windows.

The interesting part is really getting the Swift libraries built for Windows - swiftCore.lib, swiftOnoneSupport.lib etc. Once that's done, those libraries can be copied to lib/swift_static/windows/x86_64 on any Swift installation and used to cross-compile to Windows.

I wrote up some steps for getting my environment set up.

My Notes

  • Download Ubuntu for Windows
  • Install Swift dependencies via apt, including a recent version of clang.
  • export UCRTVersion=10.0.17134.0 (or whatever the current version is)
  • export UniversalCRTSdkDir="/mnt/c/swift-source/Windows Kits/10"
  • export VCToolsInstallDir="/mnt/c/swift-source/VCToolsInstallDir"
  • Modify configure_sdk_windows in CMakeLists.txt within the swift root source folder to remove Windows archs other than x86_64.
  • Rename kernel32.Lib in the VCToolsInstallDir/lib/x64 folder to kernel32.lib, and other files as appropriate.
  • For static linking:
    • Go to Visibility.h in stdlib/public/SwiftShims and comment out __declspec(dllimport); do the same in Platform.h for SwiftDemangle and SwiftRemoteMirror.
    • In Linking.cpp, always return false from useDllStorage().

64-bit build invocation:

utils/build-script -R --no-assertions --build-swift-static-stdlib --extra-cmake-options=-DCMAKE_AR="/usr/bin/llvm-ar",-DCMAKE_RANLIB="/usr/bin/llvm-ranlib",-DSWIFT_SDKS="LINUX;WINDOWS",-DSWIFT_WINDOWS_ICU_I18N_INCLUDE="/mnt/c/swift-source/windows-icu/include",-DSWIFT_WINDOWS_ICU_UC_INCLUDE="/mnt/c/swift-source/windows-icu/include",-DSWIFT_WINDOWS_ICU_I18N="/mnt/c/swift-source/windows-icu/lib64/icuin.lib",-DSWIFT_WINDOWS_ICU_UC="/mnt/c/swift-source/windows-icu/lib64/icuuc.lib"
/usr/bin/cmake --build /mnt/c/swift-source/build/Ninja-Release/swift-linux-x86_64 -- -j20 swift-stdlib-windows-x86_64

Build Swift (ignoring the last failures of the dynamically linked core libs). Run the build commands a few times and stop when it keeps hitting the same point.

Then, rename lib(...).a files in lib/swift-static/windows/x86_64 to (...).lib.

Possibly generate a new swiftCore.lib by linking the generated one statically with libicuuc and libicuin – otherwise icuuc.lib and icuin.lib always need to be passed as libraries in the linker arguments.

Need to use a modified version of lld-link (patch open here) that allows multiple definitions - build from source and pass /force:multiple as a linker argument to it to continue linking when multiple definitions are encountered.

To Build Swift code:

Make sure INCLUDE and LIB environment variables are set, mirroring those set in Windows' Developer Tools Command Prompt with VsDevCmd -arch=amd64.

Run build command, assuming a single main.swift file:

swiftc -static-stdlib -target x86_64-unknown-windows-msvc -use-ld=lld -Xlinker /LIBPATH:/mnt/c/swift-source/Windows Kits/10/Lib/10.0.17134.0/um/x64 main.swift -Xlinker /mnt/c/swift-source/windows-icu/lib64/icuuc.lib  -Xlinker /mnt/c/swift-source/windows-icu/lib64/icuin.lib -v -o SwiftTest.exe

For Swift Packages

You can see the build script I use here, but the main interesting part is the destination.json file passed as --destination to the Swift Package Manager. I did have to make a couple of changes to SwiftPM to get it to recognise Windows as a supported platform – I'll see if I can get those upstreamed in the near future.

9 Likes