I think that this is a different usage model. This is what I was referring to upthread. There are different models for different environments. Windows is not a server-only ecosystem. The server side ecosystem benefits from the single module structure where as the regular applications tend to have differing tradeoffs and some are better with dynamic linking and some are better with static linking. In fact, these choices may differ even within the same project and use a different set internally.
I would say that exact opposite: we should default to dynamic linking everywhere unless they explicitly state static linking. Particularly with common shared code, the page sharing wins are very much helpful on desktop environments and can be beneficial on server cases as well.
To be fair, you only get those wins if you happen to be running multiple applications using the same versions of the same libraries. That could certainly be the case if you're shipping a bunch of apps together that can be built in a coordinated way, but for the typical developer trying Swift on Windows seems a lot less likely, since Swift doesn't ship with the OS, there's no ABI stability guarantee on Windows yet, and packages themselves are not generally expected to try to maintain binary compatibility.
Agreed! But, that doesn't mean that we shouldn't be setting up everything for that eventuality. There is certainly interest in defining ABI stability for Windows as this has become a serious difficulty as of late as we start integrating more Swift code into the toolchain.
Do you have a sketch of what an example Package.swift and resulting .build directory would look like with the changes proposed? I don't think I'm following the idea to drop: ".library(name:type:targets:) where type is .dynamic"
For example I use this to explicitly build SVD2LLDB (an lldb plugin) as a dylib, instead of whatever a client might want.
I think that a Package.swift change would be something along the lines of what I describe at:
I don't have a strong opinion on the .build structure - each target would need to be duplicated though - static or dynamic variant.
I agree that it is useful, however, if we build everything for static and only for static, then we cannot build a dynamic library. I do not think that it is reasonable to restrict dynamic library products to non-Windows targets only, so the equitable solution here is to simply drop all support for dynamic library products. I fully agree that this makes the build system something which would be very limiting for many use cases.
The problem with this is that, if lldb were ever to adopt Swift itself and use any package that got built into your plugin dylib, the process would now have multiple copies of runtime records that Swift expects to be unique within the process, possibly disagreeing with each other if different versions of the package were used, which isn't supposed to happen and will lead to undefined behavior. This could in principle be made "safe" if SPM arranged for the modules linked into the dylib to be given unique ABI names so they couldn't collide with any use of Swift outside of the dylib; that might be another path to consider in addition to the "static only" and "dynamic only" paths.
I agree on the long term goal once we have a stable ABI on Windows but in the short term it still sounds to me like Swift PM should continue to statically link a single executable. In my opinion, this will result in the best user experience out of the box since users will be building a single statically linked library that doesn't require any other libraries to be shipped along.
If user's want to use shared libraries for size optimisations that sounds to me like an advanced use-cases that should be opt-in.
However, I am by far no expert on Windows development and if you say that dynamic libraries should be the standard then we should make that the standard in SwiftPM on Windows. The fact that the default linkage type is nil allows us to adapt this on a platform by platform basis.
Ah, I think I see the disconnect here! I wrote in prose that .library(name:type:targets:) was related to product. My suggestion on the post was to sink that to the target. This is a conceptual difference that seems analogous but is wildly different. It is now making this decision on a per target basis not a per-product basis. This means that each product can therefore be ruled out from use in building a particular type of product.
That is to say, I am not against static or dynamic linking but rather would prefer that the developer retain control over this. The problem today is that we do not have the necessary expressiveness in the package manifest to declare this type of dependency structure.
Totally agree. Please please let us Swift programmers the possibilities to build static or dynamic libraries (.dylib, .so, and yes DLL). Needed on Windows.
If any problems with SPM to achieve this, please Swift Team, fix SPM.
A Swift user on all platforms including Windows (Not a compiler engineer..).
The opt-in requires supporting the model . That is what the conversation has been about - what are the technical requirements to support it. This is not about the default value. One approach that we were discussing was to not support a particular linkage model (static or dynamic) in case that simplifies the issue. However, that comes at a significant cost that makes it undesirable IMO.
I'm thrilled about this active discussion that my question prompted, really, and I'm going to let y'all keep at it, but I'm just going to bring it back to using dependencies in SPM on Windows for a moment so that I know where to go from here.
I didn't know that you could do that. Now that I understand that that's what's going on, the question is is it a stable workflow, and is it safe to ship code that was built like that?
Sounds like anyone building Swift packages with dependencies on Windows should encounter these warnings and hence the answer is yes, but I only found little discussion about this so I'd love it if you could clarify.
To chime in on that, this utility I'm developing is actually a command-line front to a Swift library which I plan on eventually hosting in and calling from DotNET code, so dynamically-linked products are a must for me.
Thanks. I definitely appreciate your quick follow-ups @compnerd.
Um, I cannot say anything about stability. As to it being safe ... well, the way I see it is that the linker is able to work around it with penalties. You are paying in terms of code size, runtime performance, load times, etc, but it should functionally be correct (and why I believe this is the right behaviour to have currently). It can sometimes cause trouble with complex setups, so I don't think that we should be trying to squelch the warnings - that is something that should remain visible and irritating.
Regarding the interop between Swift and C# my current solution is to build the Swift library with .dynamic option in SPM and to create 'C' API functions in the Swift library using the @_cdecl attribute.
The resulting DLL can be called from C# using DllImport. Its a pain compared to the Swift no-glue C Interop but it works. Of course creating a C API over a horse-power Swift code base may be very limiting.
Another solution is to use the new features of Swift and C++ interop. Very promising for Swift 6, currently a work in progress but ok for experimentation. You might be interested in this excellent article by Daniel Kennett:
@Datagram, thanks for the interop pointers. I have a working POC that's modeled exactly like that, where I successfully call into a Swift library from DotNET using a C API on both macOS and Windows.
I've also seen Daniel's incredible post and read it with glee. I suspect that the lack of callbacks and the need for polling in his workflow could prevent me from using it down the road for a GUI app we develop because of our heavy reliance on MVVM and data bindings, but it's certainly a journey I've just started on and still experimenting with.
About building Swift GUI apps on Windows, we should mention the work of The Browser Company on a solution allowing you to build GUI applications on Windows with Swift similar to SwiftUI. Their works are based on Swith interop with Windows COM/WinRT.
Since this solution also uses Swift C++ interop, I speculate that we might learn more about the progress of this project once Swift 6 is available. They mentioned that this project will be open-source. @compnerd can certainly elaborate on the current status of the project and the vision. I can't wait to build Windows GUI apps using Swift and their framework.
In the interim, we also have the david-swift solution also similar to SwiftUI allowing you to build small GNOME GUI apps on Windows and Linux in Swift.
I tested briefly on macOS but on macOS obviously SwiftUI is the best experience.
Building libraries and applications like command line tools on Windows is a reality now and everything is falling into place to soon also be able to build Swift GUI applications.