SwiftPM: Depending on a product from the same package

I have a package with two dynamic library products, where product B depends on the targets of product A. When SwiftPM builds this package, it includes the symbols of all targets in product A in both products, meaning if an application links against both libraries it will have duplicate symbols.

The situation I want is that product B includes only its own targets and dynamically links against product A. I can hackily achieve this by not declaring the dependency in SwiftPM and manually building product B after product A, but this seems far from an ideal solution. Is there any better way to achieve this? Separating product B into its own package and using a .product dependency doesn't quite work either; it correctly links against product A but also links in some upstream dependencies of product A, so there are still duplicate symbols.

To provide some context: product B is being dlopened at runtime and @_dynamicReplaces some stubbed out functions in product A. The configuration I want enables hot-reloading of module B.

1 Like

As far as I understand it, this is not possible with SwiftPM today.

Your workaround is probably your best bet until a later proposal to create dynamic libraries is supported, and [PITCH] Support for binary dependencies - #89 by jakepetroules is resolved.

I asked that same question a year ago and got no answer, so I’m glad to hear this matters to someone else:

I have been tracking the development of SwiftPM and since then and I have not noticed any improvements in this area.

As you note, splitting B into a separate package is the only way to make it work.

If there are upstream dependencies used by both, you can have only the bottom library depend on them, but use @_exported import to pass access to them onward to the top library. It’s not perfect though, because if B has another dependency C that also shares the upstream dependency, but is neither used by A nor depends on A, then C’s isolation from A will cause it to still duplicate the upstream symbols in order to get access to them, leading to B getting the symbols both from A and from C.

1 Like