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?

Replies

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.