Setup,
I've got a Xcode project with a dynamic library target called Parent. Parent has a SPM static dependency called Child. I'm using library evolution and AccessLevelOnImport on both.
Goal,
My goal is for the symbols of Child to be available to consumers of Parent.framework. Either by consumers directly calling import Child or by adding a @_exported import Child within Parent. Both of these exhibit the issue so thats a bit of a tangent for now.
Issue,
When I build my final Parent.framework and embed/link that to a Consumer I get the "Missing Require Module Child" error.
Diagnosis,
From the build logs it appears onlyParent.swiftmodule is copied into Parent.framework/Modules/ but while Child.swiftmodule is produced in derived data but is not copied (or merged?) into the Parent.framework.
Within the Consumer I can add an explicit SWIFT_INCLUDE_PATHS the Child.swiftmodule and this works. This however, does not seem right nor is it scalable for consumers.
Is there some proper way to combine these .swiftmodule directories, am I fundamentally misunderstanding something or perhaps this is a bug?
Steps To Reproduce,
Build SPM-Framework/Parent/Parent.xcodeproj
Copy the produced Parent.framework into Consumer/. I've pre-included a copy of Consumer/Parent.framework if you want to skip building Parent yourself
Delete Derived Data. Don't skip this step.
Build Consumer and see the issue.
Some Other Observations,
An awkward solution that works. In the PrebuiltChild-Framework directory I've pre-built a Child.framework. Parent statically links to this pre-built Child.framework. Consumer is happy with the final Parent.framework from this approach. EDIT: This does not work either. Xcode search paths got me .
A non-SPM solution that does not work. In the XcodeProject-Framework directory I'm defining Child as a sub-xcodeproj within Parent.xcodeproj.
@manish12jain Can you share the steps you took and what Xcode version are you on?
You shouldn't be seeing a Child.framework in derived data if you are building from SPM-Framework/Parent/Parent.xcodeproject. Even if you are, delete that and retry Consumer and you should see error.
I chatted with @manish12jain. He was accidentially building the PrebuiltChild-Framework working example.
If you'd like to reproduce the issue you should be running the SPM-Framework or XcodeProject-Framework to build the Parent.framework. Copy that into Consumer to see the error.
@NeoNacho - The details are still a bit unclear but I was curious if there is a way to define a module map the supports this? The re-exporting seems plausible on the surface.
This might be a poor option even if it works. That said, is there a proper way to combine these module map directories? If we could have a run script that merged these we might be ok?
@popwarfour did you find any way to do this?I also need to implement something like this so it would be helpful if you could share your findings on same
I've found a few work arounds but none of them feel great.
Write the code you want to propagate up from child in some c-flavor language (probably obj-c) and manually include the headers in the outer framework's umbrella header. I wasn't successful writing the types in swift and moving the Child-Swift.h into the framework header but that'd be ideal if I could get that working.
Manually copy/ship the child frameworks(s) .modulemap and .swiftmodule and have consumers manually set an INPORT_PATH.
Make everything a separate dynamic library.
Write a bunch of ugly bridging code to manually re-expose symbol copies.
I briefly thought mergable libraries were going to be my savior but they are not.