In SwiftPM, we added the notion of products which I think makes a lot of sense, but one downside is that the product name in the manifest is completely decoupled from the module name that a client imports.
In practice, I think that "good" packages should always aspire to provide a Swift module with the exact name of the product, so that the normal client usage is to depend on product Foo and also import Foo in their code.
Here is a thought:
What if SwiftPM would automatically synthesize such a module, if the developer didn't actually define one. That module would consist of a single Swift source file using
So if I had
products: [.product(name: "Foo", dependencies: ["Baz", "Qux"])]
then SwiftPM would synthesize a Swift module
Foo which would be compiled from a single source file:
@_exported import Baz
@_exported import Qux
WDYT? Is this too magic? I think it ends up giving a better user experience than what we have today, and we could also imagine that one day the Swift compiler would just give us better tools to express the product notion directly.
+1 SGTM. This is exactly what I've been suggesting to some SwiftPM users. The only major concern I have is the fact that
@_exported is an underscored API. Can we be confident that we'll get a similar behavior from the thing that will eventually replace
@_exported? /cc @jrose
Quick, bake it in before they can remove it!
To go even farther...
If we had the ability to restrict imports, it might even be nice to force packages to use the product name rather than the fine grained module names. This would effectively remove the fine grained module names from being part of the public API of the package, which would be good from a semver perspective.
We would of course need to do a gradual migration onto that...
I was talking about this with @jrose at some point. I think one approach we talked about was providing the compiler with the list of module names a module is allowed to import.
I can't quite promise that, but I do intend to propose something like it in the post-Swift-5.0 timeframe (reference again). It's tied up with other stuff, though, so it's possible the Swift community will decide it's better to have some other functionality instead.
I just had to explain the current behaviour to someone yesterday, complete with the same
@_exported workaround. It would definitely be nice to have a proper, non‐underscored, and hopefully straightforward way to make it work like that.