Adding a package to two targets in one projects results in an error

I upgrade to Xcode 11.4 and now I am getting an error in a project that has one package used by two targets in the same project. The error I get is:

Swift package product 'x' is linked as a static library by 'y' and 'z'. This will result in duplication of library code.

This worked fine in Xcode 11.3. Any ideas?

1 Like

It depends on your concrete scenario, this diagnostic is new in 11.4, that's why you did not see it in 11.3.

If an app and an embedded app extension or helper tool statically link the same package product, this error will incorrectly be emitted. In this case, you can set the DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC build setting to YES in your app target to disable this diagnostic.

When a binary (such as an app or a framework) uses a statically linked package product, the code from the library is copied into the binary. At runtime, there can be only one copy of the code in each process, so if multiple binaries that will loaded into the same process use the same statically linked package product, this diagnostic is correct and should not be disabled. In this case, restructure your project to use the package product in only one binary, or change the type of the library product to dynamic in its package manifest.

2 Likes

I have a similar post about this problem. In short, my two targets are an iOS app and an iMessage extension embedded inside of it. They run as separate processes AFAICT. I initially thought that DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC wasn’t working, but then I realized I had added it to an xcconfig file that wasn't actually getting used; with this (correctly) set to YES, my project builds again.

Where should this be set?

As a custom build setting (or in an enabled xcconfig file).

Here is my solution to the problem:

Just in case someone else finds this and has trouble, the problem is that Xcode 11.4 is checking for duplicate static libraries and sometimes incorrectly assumes using the same library in two independent targets will cause duplicate symbols.

This can be disabled by adding a custom build setting to the project with the build setting of DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC = 1. In Xcode project settings, go to Build Settings, click the +, and add a custom setting of DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC and set the value to 1.

Thank you all for your help.

3 Likes

Why do you think this is "incorrectly"? Two of your packages will embed the code from the static library, and you will indeed have duplicate symbols. I linked a solution I use above which offloads the whole linking resolution completely to SPM. It won't be the perfect solution for everyone due to some missing SPM features such as package resources, etc., but it's a good workaround that avoids DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC, which I consider as wrong solution anyway.

It's incorrect because the package is linked to two separate executables, there's no chance there will be duplicate symbols. This is the project structure, and I do not want to use dynamic libraries.

Target A: A command line program
Target B: A XPC service
Target C: A SwiftUI application using the XPC service

Targets A and B use the same package, a set of "helper" Swift files.

Target A is used by Target B, and Target B is used by Target C. They are all separate processes, all linked independently. There is no reason whatsoever for Xcode to detect these as duplicate linking and fail the build.

2 Likes

Yeah I got the same "Problem". It's not a duplicated symbol warning. It's a duplicated code warning and it's fair enough. You could link all this with a dynamic framework and the specific search pathes.

The downside is that you need to be in control of all the packages to make dynamic linking possible :/

Yes. This is BUG behavior and assume Targets in one Project should produce same executable. Try do the same framework without SPM, which does not show any error. Just Xcode team’s issue with SPM integration

DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC = YES

worked for me, and now I can run my iOS app. However my mac catalyst app still won't compile:

multiple configured targets of 'x' are being created for macOS

This might be a known issue, do you have any iOS-only target dependencies by any chance?

If that's the case, I'm afraid there is no good workaround for this issue, the only thing you could do would be temporarily removing that dependency while building for catalyst.

I have an iOS only iMessage app. But both my swift packages are iOS + macOS.

To all the targets that's referencing the same package?

It is not incorrectly. I actually links it multiple times. So by just silencing that warning you can face some weird behaviour in reuntime like:
Class _TtGC10PromiseKit7PromiseGSaO9Shared21GroupableSearchEntity__ is implemented in both ?? (0x7ff73295abf0) and ?? (0x7ff73295cb78). One of the two will be used. Which one is undefined.
And then you can get weird typechecking behaviour.
It seems that the only correct way to link it is to create a dynamic umbrella framework as it was suggested above

It is incorrect, read my scenario, they are two separate executables. This has been fixed in the latest releases.

I see this in XCode Version 11.7 (11E801a). I have 2 dynamic frameworks in 1 executable that are referencing the same swift package with DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC on and the type check does not work in runtime. let say we have class A in the package and one framework returns func getA() -> A?. Another framework checks if let a = a as? A and the check fails.
But may be for 2 different executables it is not the case.

1 Like

This is not my use case. See above.

Terms of Service

Privacy Policy

Cookie Policy