Build commands for several scenarios for Swift on Windows

Hi all.

I am a Windows programmer new to Swift, and I have found and/or figured out the build commands for a number of scenarios on Windows that I would like to publish. It took a fair amount of digging to find the exact options needed, especially to first get debugging working, and then to debug from a Swift main into a C DLL. I'd just like to help any future Windows Swift newbies.

What I have are the swiftc, clang, and lldb commands needed to compile, link, and debug the cases below. There are no uses of the swift package manager here (possibly a future topic).

So, does such a command summary sound useful? Or has it been done already and it was just that I hadn't been able to find it?

If useful, where would be a good place to locate this, so that new Windows Swift users would easily find it?

100% Swift

  • hello world - 1 source file
  • hello world - 2 source files
  • hello world - a main executable module (2 source files), and a dll module (2 source files)

100% C

  • hello world - 1 source file
  • hello world - a main executable (2 source files), and a dll module (2 source files)

50% Swift, 50% C, both built with DWARF debug info

  • hello world - a Swift main executable module (2 source files), and a C dll module (2 source files)

Thanks for any guidance!

While I personally don't find that to be useful, I might not be the best judge of the utility of this collection.

However, given that this is primarily focused on the non-SPM use case, I believe that the better way to encourage new users to determine these commands is technically by encouraging them to not do that in the first place. CMake provides an abstraction for this and if needed or desired, the user can always look at the generated invocation.

I think that the scenarios you are enumerating should be covered with compnerd/swift-cmake-examples: Swift example projects (github.com) and running with ninja -v should give you the invocations involved. If there are use cases that it doesn't cover, I'm happy with accepting PRs and if there are limitations of CMake, those would be better to address at that level - which is likely to help the Swift project as a whole.

I don't think that there is any way to generate "Swift-compatible debug info" for C programs. The "Swift-compatible debug info" is a AST serialization as that is what Swift uses. Did you meant DWARF? In that case, it may be something which is a bit unnecessary as Swift is able to generate both CodeView (and subsequently the associated PDB) as well as DWARF.

I think this would be useful to have somewhere, yes!

Did you meant DWARF?

Yes, sorry if I did not word that well. My example builds the C DLL and the Swift main with DWARF so that LLDB can step from the main into the DLL, seamlessly. Also, that note should probably have been on the 50%/50% line. I will fix that.

the utility of this collection

I feel that I need to explain how I got here.

After reading the Swift Getting Started (GS) page, my goal was to build and debug the scenarios I listed above. In sections 'Using the Package Manager' and 'Using the LLDB Debugger', it says to use the 'swiftc' compiler with -g and lldb. On Windows, that leads you immediately into assembly code - lldb has no awareness of the source code, line numbers, or var names. Also there is no mention that you need SWIFTFLAGS on your builds, which turned out to be required. (I later found it mentioned in the REPL section.)

That led to much searching for examples of how to build on Windows. Since the tools named in the GS page were Swift PM, 'swiftc', and LLDB, those are what I searched for.

In particular, there are no mentions on the GS page of using CMake and Ninja - nothing there would have led me to your cmake-examples page that you referenced. On the GS page, Swift PM is the build system.

After hours of searching for how to build and debug on Windows, including Google searches and searching this forum, I finally found or deduced how to build the scenarios. Obviously I should have stopped searching at some point and simply asked this forum. Hindsight, sigh.

The one thing that would have eliminated much of the toil would probably have been information in Getting Started that gave the correct commands for Windows to build and debug with Swift PM, 'swiftc', and lldb (since those are its focus). Or a link to such a page. I just want to prevent any new Windows Swift person from taking the hard road that I followed. And that is underlying reason for this post.

Even now, knowing about your page, I still feel it worthwhile to make it clear how to build with Swift PM and with 'swiftc'. It would surely help all those coming off the GS page, and those who opt not to use CMake. And personally, I find it valuable to know what goes on behind the curtain, as does the author of this page. I guess I am just assuming that some portion of developers are kindred spirits. However, to address your concerns, a link to your page could certainly be inserted.

Also, I do plan to submit suggestions to Issues · apple/swift · GitHub to improve the Getting Started page regarding the omissions above. (I have already submitted several regarding the install instructions for Windows.)

For now, I guess I would like to wait and see if there are other responses from the community, on whether such information would be useful (and @xwu, thanks for your comment!).

Please do propose improvements to the Getting Started page (and IMO preferably sooner rather than later). I tried to make it as precise and thorough as possible, but it is extremely difficult given all the differences between the different versions and the rapid pace of changes to the Windows builds.

The ecosystem is built around Swift PM which is why there is no mention of the CMake and Ninja. While it is possible to build Swift code with both CMake and bazel, I think that the official documentation should be around SwiftPM only.

That should largely just be swift build for most projects at this point. For debug builds, I suppose that -Xswiftc -g -Xswiftc -debug-info-format=codeview -Xlinker -debug can be documented, though perhaps the better way to handle this is to improve SPM to not require that in the first place. I think that it may be interesting to consider aliasing -debug-info-format=codeview to -gcodeview (and to introduce -gdwarf) which would be alterations to swift-driver. I think that the piece that is really missing is the default of -Xlinker -debug in SwiftPM but that requires some work to correctly inject. Patches to improve that would be nice.

Part of the problem is that LLDB's PDB support can be challenging to work with (sometimes switching from the LLVM PDB support to DIA works better, sometimes the inverse). Improvements to the debug info generation as well as processing would also be a great thing to have (which is difficult to do with time constraints). In my experience, DWARF enabled binaries have caused silent data corruption, particularly in larger binaries (>= 2G) and there are possibilities of debug info introduced failures with DWARF in sufficiently complex binaries.

Yes, I agree. GS should stay with 'swiftc' and SPM to stay focused and simple. Very appropriate. My reason for saying "no mentions on the GS page of using CMake" was only to show why I would not have found your page; it wasn't to imply that GS should have content describing other build systems beyond SPM. So to perhaps state that more clearly, none of the pages that could have helped me get started on Windows builds (including your page) were easily findable.

In light of all this, what does seem helpful might be a page called Next Steps, which could just be a page of links - links to all manner of helpful pages, organized with a major section for each platform (Windows, Apple, Linux, etc). Then in the Windows area, links such as:

  • how to build and debug with Swift DLLs and C DLLs via Swift PM (one of the 2 pages I propose above)
  • how to build with CMake and Ninja (your page)
  • how to use DWARF and Codeview formats
  • Editors/IDEs that work well with Swift, which could include links to VS Code and others
  • debuggers that work well with Swift with links to LLDB, VS Code + CodeLLDB, WinDbg.

These links would be organized under subtopics such as Building, Debugging, etc.

Such Windows-oriented links would have been of great help to me at least, since so many searches on these topics come up with solutions in the Apple environment, because of Swift's long history of life only on Apple.

And where would such a page best live?

A wiki is attractive in light of what you wrote about potential improvements to SPM and swift-driver - the wiki could reflect the current command options, and then easily updated by the community when the tool changes are released.

And finally, how to get to that page?

  • There could be a link at the bottom of Getting Started.
  • Or (if it lived in www.swift.org), perhaps it could be listed in the leftside pane, just after Getting Started, i.e.,
    ABOUT SWIFT
    BLOG
    GETTING STARTED
    NEXT STEPS
    DOWNLOAD

My thought is simply to provide a search-free path of links, started from Getting Started or its left pane, to help the new-at-Swift developer who is ready to move to the next level.

Thoughts and counterthoughts are welcome.

It seems that your concern is that the information, while available, is spread out across different locations. This is primarily a historical artifact, and collating the information would require a motivated person to put in the work. The forums have served the role of a centralised location for the information, which is often overlooked.

As to the support for GitHub Wiki's @mishal_shah might be able to answer that. I think that the ideas that you have for making the information more locatable are better suited for Swift.org - Swift.org website work group (SWWG) as they are responsible for the website.

Thanks for pointing me to @mishal_shah and the SWWG, I will follow up with them.

Turns out I had already submitted suggested changes to the Getting Started page for Windows issues, so they are all set for someone to look at:

[On Windows 10, swiftc gets error regarding swiftrt.obj · Issue #58435 · apple/swift · GitHub]
[On Windows 10, lldb gets error regarding python310.dll · Issue #58438 · apple/swift · GitHub]
[Eliminate duplicate instructions? · Issue #58446 · apple/swift · GitHub]
[On Windows 10, lldb breakpoint command gets error · Issue #58449 · apple/swift · GitHub]
[On Windows 10, what is the order of installs? · Issue #58451 · apple/swift · GitHub]
[Might it be possible to make the footprint a bit leaner, for the Windows installation? · Issue #58453 · apple/swift · GitHub]

An Apple person applied labels ('windows', 'website') to some of the issues, but I don't think that all appropriate labels have been applied to all issues. Also, for some of the issues, a single issue holds a combination - it (a) reports the error experienced, so that someone searching for the error will find the issue page, (b) supplies a workaround to the developer experiencing that particular error, and then (c) also includes a suggested change to GS to prevent it from happening in the future. I was unsure how to submit all that, so I combined them all into one issue because they were so related. Hope that's ok. (I see now that an alternate strategy could have been to separate them: put the error+workaround in one issue (and close it), and put the website change request into a different issue, and then link them together.)

Thanks for when you work on those updates!

the better way to encourage new users to determine these commands is technically by encouraging them to not do that in the first place

There are good reasons for steering a lot of user documentation toward the best way to do common things, but personally, this philosophy drives me crazy. :slight_smile:

My current example (unrelated to the specifics of this post) is the Microsoft documentation for DllGetActivationFactory, which is marked as "no longer updating this content", and which actually says "Do not call". But it seems to be exactly the function I need. But I digress...

Yes, the typical best way to write docs is to tell them "how to do". But that's almost never what I want. What I want is "how it works". Show me under the hood. And I have learned to accept that I am not typical in this regard.

TLDR: the kinds of information described by the OP is the kind of information I consider precious. I wish we had more commonly recognized ways of making it available while somehow tagging it as "fringe".

While I agree with this sentiment, that often doesn't work for everyone. I don't have an issue with that type of documentation, but it also feels inappropriate for many places (particularly so with the getting started guides).

This is actually a bug. If you use the unstable snapshots, you shouldn't need to worry about the flags here. This also highlights another problem: documenting workarounds for a particular release version becomes difficult (and tedious) when you are working across multiple different versions. Perhaps you can create a document that describes the various limitations and workarounds per release. The drift between main and the release versions tends to skew so much that I can often not even enumerate what has changed on given release by the time that it ships.

Perhaps what we want is a reference model. Do you know of any (public) documentation that explains how Visual Studio is setup and laid out and the interactions between ucrt, msvcrt, WinSDK, WinRT, WinUI? The Swift setup is basically that and an additional Swift SDK that is overlaid.

I think that some of the information is at swift-build/Windows.md at master · compnerd/swift-build · GitHub (and some of its peers). However, there is no such documentation for the other platforms where this can easily fit into.