Hi !
I'm currently stuck with an issue on Xcode, I'll try explain to the best I can :-)
I have a workspace (that I need to keep that way, I can't split projects) that contains multiple projects.
I have 2 frameworks : Core and Draw. Draw depends on Core. So far so good. I needed to create a test application that can be modular and link my framewok, but also other drawing frameworks. To that extend, I created a CardLIbrary framewok, and a CardAdapter framewok, and I linked them into the test application.
Test App
└── DrawCardAdapter
│ └── CardAdapter
│ └── CardLibrary
│ └── Core
│ └── TCA (SPM)
│ └── Draw
│ └── Core
Here, all dependencies are local ones if not stated otherwise (for the SPM).
CardLibrary is a framework that generates only UI (linked to Core for logging purposes, nothing fancy). I also added TCA which is a SPM dependency, it may generate some issues after.
CardAdapter is an abstraction for CardLibrary. Basically, it acts as an interface between CardLibrary and Test Application.
DrawCardAdapter is the actual implementation of CardAdapter using local Draw framework.
Why so complex ? Because I need to be able to do this:
Test App
└── ExternalDrawCardAdapter
│ └── CardAdapter
│ └── CardLibrary
│ └── Core
│ └── TCA (SPM)
│ └── ExternalDrawFramework
With this architecture, I can create a new ExternalDrawCardAdapter that implents the CardAdapter logic. This new framework does not relies on my Draw framework, and yet, I can still generate a test application that visually looks and feel like all others, but use a completely different drawing engine underneath.
To do that, the Test App code only uses inputs and outputs from CardAdapter (the protocol), not concrete implementations like DrawCardAdapter or ExternalDrawCardAdapter.
But to be able to make it work, I have 2 test ap targets : a DrawTestApp and a ExternalDrawTestApp. All code files are shared, except a SdkLauncher
that is target specific and acutally loads the proper implementation. So the SdkLauncher
for DrawTestApp is linked to the DrawCardAdapter (embed and sign) and loads DrawCardAdapter framework, whereas the ExternalDrawTestApp is linked to the ExternalDrawCardAdapter (embed and sign) and loads ExternalDrawCardAdapter framework.
Now it looks like this (I only show local stuff othewise it would be too complicated :D)
So far so good, this works well.
Now, for the part that fails. My Draw and Core frameworks are frameworks that I release for my customers (Cocoapod), and I wanted to be able to test my productions frameworks with the test app (it's that actual purpose of the test app : being able to test development and released SDKs)
To do so, I duplicated every target and removed local dependency for a cocoapod dependency. All targets were named -pod
, but the actual module and product name are still the same (I tried differently, it did not work either, I'll explain it later).
Test App
└── DrawCardAdapter
│ └── CardAdapter
│ └── CardLibrary
│ └── Core
│ └── TCA (SPM)
│ └── Draw
│ └── Core
│
Test App Pod
└── DrawCardAdapter-pod
│ └── CardAdapter-pod
│ └── CardLibrary-pod
│ └── Core-pod
│ └── TCA (SPM)
│ └── Draw-pod
│ └── Core-pod
Once again, it's only targets, every project would look like
CardAdapter
└── CardAdapter
└── CardAdapter-pod
It continues to use local targets, except for the DrawCardAdapter-pod that actually loads Draw and Core from a Podfile instead of using the lkocal frameworks.
But now for the part that fails : even though TestApp-pod does not link any local frameworks, I get a warning
Multiple targets match implicit dependency for product reference 'Draw.framework'. Consider adding an explicit dependency on the intended target to resolve this ambiguity.
And actually, Xcode ends up packaging the wrong framework. I can check it but showing in the app the Draw framework version, and it's always the local one, not the one specified in the podfile. For the record, I get this message for all 3 frameworks of course.
I tried sooooo many things, that did not work of course:
- renaming the
-pod
frameworks so that the names are different (I had to rename all imports too). It works for all local frameworks (Lilbrary and Adapter basically), but not for Draw and Core (since I don't have-pod
versions of thoses framewoks of course). - Creating a new local workspace that only handles
-pod
versions. Does not work since as we work as a team, I have to keep the shared schemes, and all workspaces see all targets and schemes. I also tried with a separate derived data folder, but I end up with some compilation issues. It seems that mixing local, cocoapod and spm dependencies inside the same workspace is not well handled) - using explicit
Target Dependencies
from the build phase. I end up with some compilation issues - creating local podspecs for Library and Adapter. It fails because TCA is linked with SPM and apparently not copied when using podspecs.
To the few ones that stayed so far, thanks for your patience :D I hope that @eskimo will drop by as you always were my savior in the end :D :D