Closed diogobalseiro closed 1 month ago
Hi @diogobalseiro,
First of all, thank you for the very detailed and well-explain description.
I would say this duplicated-class problem is universal to how dependencies are linked (statically or dynamically). Even if with CocoaPods, this issue still happens. A typical example is when both App and Tests depends on a static framework, like following. Check out the demo at https://github.com/trinhngocthuyen/ios-demos/tree/main/shared-lib.
App Tests
| |
----- Logger-----
(static)
The problem, in this example, would have been resolved if Logger is rather dynamic.
So, I think it's more about how we structure the dependencies (what depends on what, and whether one is static or dynamic). Unfortunately, an SPM package product is static by default while a pod is dynamic by default. This explains why the issue surfaces more frequently in the context of SPM.
For in-house packages, possibly you can consider updating the library type when appropriated. For 3rd-party packages, it would be difficult to deal with at the moment. With CocoaPods, we can magically turn a pod into static or dynamic form easily due to the flexibility of ruby code (podspecs are ruby). But for SPM, there are very few actions we can take from the plugin side to modify the library type to make it works the way we want.
Hope the explanation above helps clear your doubts.
Hello.
Your explanation was helpful, it cleared some suspicions we had. We tried fiddling with the library type of our SPM dependencies but couldn't find the right configuration to fix the problem.
Eventually we managed to avoid the problem altogether by not relying on the tests specs for certain dependency installations.
Thanks 🙏
What happened?
Hello.
Before explaining the issue I'm seeing, let me say thank you for this plugin. 🙏 The lack of interoperability between Cocoapods and SPM is crazy, and is stranding many medium/large sized projects with Cocoapods unnecessarily.
Context
I've started using this plugin to migrate over 150 Cocoapods dependencies (most internal) to SPM, in my work project, and I've ran into an issue regarding test targets. I'm unsure how to proceed at this point.
I've setup a sample repository, which is just a fork this repo with some minor modifications to the sample project. The aim is to provide a very easy and simple way to reproduce the problem I'm seeing.
The problem I'm seeing is when running the unit tests:
Class _TtC8SwiftUIXP33_266C9A88B74B5500A763A7BF40B6456F12_AlertWindow is implemented in both /Users/diogo.balseiro/Library/.../EX.app/EX (0x1035fc640) and /Users/diogo.balseiro/Library/.../EX.app/PlugIns/EXTests.xctest/EXTests (0x111efc068). One of the two will be used. Which one is undefined.
The SPM dependencies that are imported to the test target are not correctly de-dupped and can result in undefined behaviour at runtime. In the example above, the spm dependency is
SwiftUIX
.Sample
The changes made to showcase the problem above are simply these:
CommonTestsKit
. That pod depends on the spmSwiftUIX
and another other remote cocoapodMoonKit
:A swift file containing some sample code. Lets pretend this code helps with some unit test related logic:
We can make a minor tweak to the actual
EXTests
, though I believe its not necessary:Run the unit tests and the issue appears in the console log.
Notes
This problem happens with all SPM dependencies that are "shared" between the
EX
andEXTests
targets, and do not happen for regular Cocoapods dependencies (like theMoonKit
above). This is why this behaviour seems incorrect.Consequence
This problem would seem fairly innocuous but can result in flaky tests and undefined behaviour, particularly if the duplicated classes rely on static code, such as singletons. I've reproduced this problem in my work project resulting in two static shared singletons for the same class, breaking a test suite. (While singletons are a design pattern we tend to avoid, its not always possible) This is preventing us from adopting the plugin further and migrating more classes, as we starting to reach test targets that need to import dependencies already present in the "main" targets of the app/frameworks.
Do you have a suggestion on how to fix/avoid this problem?
Thanks in advance. 👍
CocoaPods environment
Stack
Installation Source
Plugins
Podfile
Anything else?
No response