Swift Packages in multiple targets results in “This will result in duplication of library code.” errors

I wouldn't say its telling us to not use SPM. I think this is an actual bug in Xcode and SPM. Everyone of us should be submitting Feedback reports until we hear otherwise.

Not sure what you mean by that, could you elaborate?

The original problem I was reporting wasn’t in sharing code across platforms—it was sharing code between an iOS app and an extension embedded inside the same app. Sharing libraries across iOS and macOS should work fine.

I'm finding that this is still an issue in Xcode 12 too. Interestingly, my project builds just fine normally. It has no app extensions or other embedded build products. However, Xcode Previews is the one throwing this error and doesn't even attempt to build. I've filed FB8015308.

2 Likes

Thanks, we aware of previews hitting this issue -- this is related to all package products being built dynamically right now to enable previews.

4 Likes

Great to here, Unfortunately 121 b3 doesn't have the fix.

1 Like

@NeoNacho - is there any workaround?

I'm hitting this when importing HSHelpers & HSSwiftUI from this package:

HSSwiftUI depends on HSHelpers, so this is giving the error

Swift package target 'HSHelpers' is linked as a static library by 'Skydive Designer' and 'HSSwiftUI'. This will result in duplication of library code.

regular build & run is fine - but previews are completely borked

Jumping into this thread. We are experiencing the same issue when building our apps (This will result in duplication of library code) although not through SwiftUI preview, but rather in a hybrid Xcode workspace mixing SPM library targets and regular Xcode targets (static lib, apps, extensions). Our Package manifest typically define both the actual static library (libA) and an associated dynamic library (libA-stub) that has a target dependency on the static one. We use this mechanism so that other Xcode static libraries (libB) can depend on libA (and import its modules) through libA-stub without linking libA's symbols as this is typically done by the 'final' target (the app), which is the only one to link libA symbols. It looks like Xcode 12b1,2,3 interprets the target dependency (libA - libA-stub) as a link and outputs that message, which was not the case previously (Xcode 11.5).

This is happening with Xcode 12b3 (12A8169g), and the DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC does fix the build error that otherwise occurs early in the build (preventing other build tasks). There is no problem and no need for this setting in Xcode 11.5.

I will try to reproduce this outside of our build environment which is quite complex, and hopefully submit it as a bug report. Anyone knows if the fix mentioned in this thread from Xcode 11.4.1 is already on its way to 12.0 or if this requires extensive reporting / documentation? Thank you.

I could isolate the issue, and reported it as FB8202677. Sample project demonstrating the issue in the configuration described in my last message (stub libs) is available here: GitHub - rsebbe/Bug_Xcode12_DoubleLinkError: Xcode 12 workspace that demonstrates double link build error with SPM dynamic targets: "This will result in duplication of library code". Bug report filed as FB8202677.

The error looks correct to me:

Swift package target 'A' is linked as a static library by 'C' and 'A-stub'. This will result in duplication of library code.

According to the manifest, the "A-stub" target does declare a dependency on "A". Is this right: Bug_Xcode12_DoubleLinkError/Package.swift at master · rsebbe/Bug_Xcode12_DoubleLinkError · GitHub?

The difference between 11.5 and 12.0 is that we amended the diagnostic to also detect duplicated linkage of package targets. In 11.5, we were only looking at package products.

Oh I see, what you're saying, we're incorrectly interpreting the dependency that libB.a has as linking statically.

We've been fighting with the tools (Xcode) over the last 10+ years with all kinds of workarounds, because although these are 2 different concepts (dependency and linking), they really want hard to make it a single concept. Dynamic libs have further masked this problem, but they are otherwise not optimal (load time + typically not stripped to just the symbols needed).

This (basic, common, useful) example, that Xcode targets are unable to implement, shows it:

App depends_on libB
libB depends_on libA
App (possibly) depends_on libA
App links libB
App links libA

I think SPM wants to allow that, but there remains friction on Xcode side. We sure hope to move the 5.3 (that now support resources) and remove many our "stub" workaround targets. + there is a lot less state in SPM targets than in Xcode's, which means easier maintenance.

2 Likes

I think setting DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC may reveal the root cause:

/warning:1:1: file: /Users/neonacho1/Library/Developer/Xcode/DerivedData/W1-drxqtaioopukohfdphknquwsadbh/Build/Products/Debug-iphonesimulator/PackageFrameworks/A-stub.framework/A-stub is a dynamic library, not added to the static library

So the build system thinks the A-stub dynamic product is being linked, but it just doesn't happen in practice.

Another parallel example is an app being comprised of multiple targets, all of which depend on some library A.

You have this structure:

App
  - Dependency A
  - Extension A
    - Dependency A
  - Extension B
    - Dependency A

This architecture is incredibly common, more so as additional extension points become available to iOS apps. Dependency A could be an analytics library, Alamofire, or an internal framework that encapsulates business logic in a shared codebase. Whatever it is, SPM and Xcode should be able to handle this gracefully. We should end up with one copy of Dependency A, and all of the binaries should link to it.

4 Likes

yes. We use "stub" dynamic libs because we know dynamic libs are never linked into a static lib, yet correctly setup build oder and module generation.

Again, this is a workaround. I'd rather not have such stub libs at all, and just declare depends_on and link_against relationships in Xcode. The former is not possible across targets in distinct projects in an Xcode workspace, only the latter is, which is why we need these stubs in the first place.

Hopefully SPM is smarter here, and we can progressively replace Xcode lib targets with SPM, which will do the right thing.

I'm struggling with this now. Not having previews has stalled my progress. For this particular issue the DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC=YES work-around hasn't worked for me.

We have a single SPM package in our Xcode project; I'll refer to it as the "root". That root package depends on a number of other SPM packages that specify no linking; neither dynamic nor static.

Wether we mark the single root package as "static" or "dynamic" we receive the error about duplicated code when attempting to use previews. DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC=YES does nothing.

You must fix this ASAP. As it stands SPM is useless because it disables the most valuable feature of Xcode.

I think this thread is starting to get a little confusing for everyone, since we are really discussing several different problems here, which just happen to have the same outcome. To summarise:

  • There were issues with just the diagnostic which have mostly been fixed at this point, except for the problem that @rsebbe is describing.
  • There is the general problem of actual diamond-shaped linkage in projects, for which currently the only solution is manually changing your project as a workaround. We aware that this is an issue for many people and are investigating a solution.
  • There is an entirely separate issue which happens only for Xcode previews which is related to all package products being built dynamically in Xcode 12 to enable previews. It is also something we're actively investigating. There is no workaround for this, since users do not have control over how builds for preview are being done.

The DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC setting only helps in the first case, because there isn't a real problem being flagged. In all other cases, it won't actually help because the diamond-shaped linkage is real.

9 Likes

The Xcode previews issue discussed here should be resolved in Xcode 12 beta 5.

5 Likes

Confirmed that the Swift UI Preview issue is resolved for Firebase with beta 5. Details at Error on SwiftUI Preview when using Swift Package Manager · Issue #6280 · firebase/firebase-ios-sdk · GitHub. Thanks!

1 Like