I'm facing a problem with SPM, and my understanding from my research so far is that SPM simply currently does not support what I want to do, so what I'd like to know is if someone could point me to the relevant discussions on this topic or share any insight about the status of this feature.
Here's my setup. I have a package called CoreToolkit
, which is my personal toolkit for miscellaneous, generally useful code. I also have another package called XCTestToolkit
, which extends the XCTest
framework in useful ways and which I import and use for the unit tests of all my other packages, including my unit tests for CoreToolkit
. My problem is that, as far as I know, SPM does not give me any way to specify that XCTestToolkit
is only used by the test target of CoreToolkit
, not by the CoreToolkit
library product itself. As a result, I can't use any of my CoreToolkit
code in XCTestToolkit
because if XCTestToolkit
depends on CoreToolkit
then SPM thinks there is a cyclic dependency. Unless I'm misunderstanding something I think this is an unnecessary problem to have because the reality is that XCTestToolkit
depends on CoreToolkit
, CoreToolkitTests
depends on both CoreToolkit
and XCTestToolkit
and CoreToolkit
depends on nothing.
Does anyone know if there are any plans to lift this restriction?
SwiftPM can tell, because you had to specify the dependency on the particular target you want. Newer versions of SwiftPM are getting better and better at skipping dependencies not touched by the product whenever a client depends on your package.
I can't use any of my CoreToolkit
code in XCTestToolkit
because if XCTestToolkit
depends on CoreToolkit
then SPM thinks there is a cyclic dependency.
The real problem here is that you are trying to wedge an external package in between two targets in the same package. This is a cyclical dependency at the package level.
The standard arrangement for what you are trying to do is to have one package (CoreToolkit
) with two products (CoreToolkit
and XCTestToolkit
).
There is a reason cyclical dependencies at the package level (where the version is attached) are rejected even if their target graphs could theoretically work out in the short term: Breaking changes would be impossible. When it came time to start working on CoreToolkit
2.0.0, you would have to disable the tests, since they depend on XCTestToolkit
and in turn CoreToolkit
1.0.0, which cannot co‐exist with the new code you are trying to test.
1 Like
Thank you! I'm unexpectedly satisfied with the solution of putting them in the same package as different products.
I always enjoy when the compiler teaches me things I didn't know about my own concepts - when "annoying" error messages turn out to be golden pieces of architectural advice. I hadn't seen the analogy between my CoreToolkit
and XCTestToolkit
packages until now... now I see that they're really the same thing - XCTestToolkit
is just the manifestation of CoreToolkit
in the test universe. Since every Swift package I write should theoretically have unit tests, and "every Swift package" is also pretty much the target demographic of CoreToolkit
, it's in fact entirely natural to put them in the same package - I realize now that I wouldn't have it any other way.

1 Like