I believe we've encountered an Xcode bug but wanted to cross-post this in "Using Swift" for visibility. Please let me know if anyone has an idea about why the following problem might be happening.
We have a Swift Package "FooPackage" that declares two dynamic library products:
Foo target depends on Fooable.
Some frameworks in our app link Fooable (without embedding), and this works just fine.
The app itself links and embeds Fooable.
However when we linked Foo also to the app, now compile breaks with:
Swift package target 'Fooable' is linked as a static library by 'App' and 'Foo'. This will result in duplication of library code.
Why is Xcode statically linking the dynamic library,
Fooable, into to
Foo? This must be a bug in Xcode, right?
I've found two workarounds so far:
- Only link
- Set "DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC = YES" in all build settings.
- Which option is the better workaround and why?
- Why this problem is happening in the first place?
- Why would Xcode try to statically link these dynamic libraries?
- Is there a way to prevent it from statically linking these, and if so, how? If not, why not?
I also noticed that after building the app, we'll have two sets of products made from the Swift package:
- DerivedData/MyWorkspace/Build/Products/Debug-iphonesimulator/Foo.swiftmodule & Fooable.swiftmodule
- DerivedData/MyWorkspace/Build/Products/Debug-iphonesimulator/PackageFrameworks/Foo.framework & Fooable.framework
If I link the app to these two packages by dragging these frameworks into "Frameworks & Libraries" in Xcode, and then make sure
$(BUILT_PRODUCTS_DIR)/PackageFrameworks is in the Frameworks Search Paths, now also the app will succeed to build.
It seems that Xcode produces these .frameworks (which can be dynamically linked) but then also produces the .swiftmodule files, which can't. And for whatever reason (I guess due to a bug?) Xcode is preferring to link to the .swiftmodule files even when the libraries are declared as dynamic!
However, linking the frameworks from
$(BUILT_PRODUCTS_DIR)/PackageFrameworks is not a great workaround, because it means the app will fail to build on the first go-round (since the built frameworks won't be there at that point).