This repo demonstrates a current issue in certain project set ups in Xcode and SPM. The project is structured like so:
- A Widget package that vends a Widget library and a WidgetTestSupport library that depends on Widget.
- Widget vends a single public class.
- A Thingamabob package that vends a Thingamabob library (that depends on Widget) and a ThingamabobTestSupport library that depends on Thingamabob.
- An Xcode project with an app target that depends on Widget and Thingamabob, and a test target that depends on WidgetTestSupport and ThingamabobTestSupport.
Here is a diagram to visualize these dependencies:
flowchart TB
A[AppTests]
subgraph Production
B[App]
E[Thingamabob]
C[Widget]
end
subgraph TestSupport
D[WidgetTestSupport]
F[ThingamabobTestSupport]
end
A --> B
A --> D
A --> F
B --> E
B --> C
D --> C
F --> E
E --> C
With that set up one cannot run tests in the Xcode project without encountering this warning in the logs:
objc[57439]: Class _TtC6Widget9TheWidget is implemented in both /Users/brandon/Library/Developer/Xcode/DerivedData/XcodeBug-dhezmlxfsyctfmakkodkuonvastz/Build/Products/Debug-iphonesimulator/PackageFrameworks/Widget_1CCEF16185F6EA_PackageProduct.framework/Widget_1CCEF16185F6EA_PackageProduct (0x104414288) and /Users/brandon/Library/Developer/XCTestDevices/4ACBAB4D-2ED0-43F9-BB1C-2461005B7EE6/data/Containers/Bundle/Application/C4AB393F-B4C8-48BA-BCFF-E3BAC3F98E25/XcodeBug.app/PlugIns/XcodeBugTests.xctest/XcodeBugTests (0x1053380e0). This may cause spurious casting failures and mysterious crashes. One of the duplicates must be removed or renamed.
This leads to real problems where different parts of the code base can use different versions of the duplicated class.
A few things worth noting:
- The duplicated symbol seems to only affect public classes, and the above logs mention "objc", so perhaps it is related to Objective-C bridging.
- SPM does not have this problem. The exact same set up in a pure SPM package works just fine, and then that package can be used in an Xcode app target just fine. This problem is specific to Xcode targets.
- If WidgetTestSupport were extracted to its own dedicated package, the problem goes away. But this causes a maintenance burden to manage two separate repos, and the test support library cannot access
packagelevel symbols in the core library.