How to prevent duplicate resource bundles from SPM dynamic framework in app extensions?

We use a local swift package in 6 of our app extensions. The product from the local package that we link to each app extension is a dynamic framework. And while the dynamic framework is copied into the final app bundle once, the resource bundles of each target that comprise the dynamic framework is copied into each app extension. I'd much rather have the bundles be copied into the dynamic framework once to prevent app bloat.

Here is a visualization of the issue:

.
└── MyApp.ipa/
    ├── MyApp (executable)
    ├── MyDynamicFramework_TargetA.bundle
    ├── MyDynamicFramework_TargetB.bundle
    ├── MyDynamicFramework_TargetC.bundle
    ├── Frameworks/
    │   └── MyDynamicFramework.framework/
    │       ├── TargetA
    │       ├── TargetB
    │       └── TargetC
    └── PlugIns/
        ├── Widgets.appex/
        │   ├── MyDynamicFramework_TargetA.bundle
        │   ├── MyDynamicFramework_TargetB.bundle
        │   └── MyDynamicFramework_TargetC.bundle
        ├── Intents.appex/
        │   ├── MyDynamicFramework_TargetA.bundle
        │   ├── MyDynamicFramework_TargetB.bundle
        │   └── MyDynamicFramework_TargetC.bundle
        ├── IntentsUI.appex/
        │   ├── MyDynamicFramework_TargetA.bundle
        │   ├── MyDynamicFramework_TargetB.bundle
        │   └── MyDynamicFramework_TargetC.bundle
        ├── NotificationContent.appex/
        │   ├── MyDynamicFramework_TargetA.bundle
        │   ├── MyDynamicFramework_TargetB.bundle
        │   └── MyDynamicFramework_TargetC.bundle
        ├── RichPushContent.appex/
        │   ├── MyDynamicFramework_TargetA.bundle
        │   ├── MyDynamicFramework_TargetB.bundle
        │   └── MyDynamicFramework_TargetC.bundle
        └── NotificationService.appex/
            ├── MyDynamicFramework_TargetA.bundle
            ├── MyDynamicFramework_TargetB.bundle
            └── MyDynamicFramework_TargetC.bundle

Notice that the resource bundles of Target A, B, and C are copied multiple times causing an unhealthy app size.

I'd either like the resource bundles to be copied into MyDynamicFramework or copied once into the app bundle and let the app extensions reference them.

Given the SPM + Xcode linking is a black box for the most part, how would I accomplish this?

For others, I resolved this issue by:

  1. Rewrite my own version of the synthesized Bundle.module SPM provides and adding Bundle.allBundles.first(where: { $0.resourceURL?.pathExtension == "app" })?.resourceURL as a candidate location for the resource bundle.
  2. Adding a python script to remove the duplicate bundles as a build phase.

I am facing the same problem. Any chance you can share the script that you used?

Sure, @rosskimes did you still need it?

Hello @John.liedtke, please share your script :)

Hello,

Curious if you have looked into using a binary target and xcframework for your assets inside of your dynamic framework. There's a nice write up about this from Emerge Tools, but I've admittedly never tried it: https://www.emergetools.com/blog/posts/make-your-ios-app-smaller-with-dynamic-frameworks

Binary targets are pre-compiled, ensuring that your assets bundle is already neatly packaged inside the framework. This means the compiler won't build it, and won't re-bundle it into each of your targets

How to prevent duplicate resource bundles from SPM dynamic framework in app extensions?
 
 
Q