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

I have a project that has an iOS app and a Messages app embedded in it. This project uses Swift Package Manager to manage its dependencies, including Alamofire and Valet, plus some private shared code among the app targets and the Vapor-based server code. When building with Xcode 11.4, I get build errors of the following type:

error: Swift package product 'Alamofire' is linked as a static library by 'EmojiClub' and 'EmojiClubMessages'. This will result in duplication of library code.

If I remove Alamofire (or any of the libraries for which this error happens) from the iOS app target or the Messages app target, then I get missing symbol build errors. I’ve seen some guidance on this around these forums to use .dynamic in the Swift package declaration, but I can’t force third-party frameworks to do so. Is there a solution to this problem from within Xcode or SPM, or do I need to try making a new, dynamic Swift package for these dependencies and then import that in my app targets?

7 Likes

I’ve fixed this for now by creating a third framework target that imports the dependencies, then importing this target in the other two. This feels like a hack, though, surely there’s a better way?

2 Likes

Perhaps I spoke too soon. Attempting to upload this results in this error:

App Store Connect Operation Error
ERROR ITMS-90205: "Invalid Bundle. The bundle at 'Emoji Club.app/PlugIns/Emoji Club Messages.appex' contains disallowed nested bundles. Refer to Redirect: Embedding a framework in an iMessage App for a workaround."

1 Like

I don't believe SPM can do dynamic linking all the way through in Xcode (someone will need to verify), so if you're static linking symbols into two dynamic libraries then both of those get linked to something else, it'll show up as duplicates.

The "hack" you describe is the right workaround for now but this issue might also be app extension related, I assume the .appex is just going to use the same /Frameworks folder as the .app so you should only have the copy frameworks set up for the .app; again not sure on the SPM setup here, just know the issue from having to structure things around this problem manually in the past.

1 Like

@SlaunchaMan Can you share you Package file ?

@davidharris I use SPM to expose dynamic or static version of my libraries.

.library(name: "LibraryDyn", type: .dynamic, targets: ["Library"]),  
.library(name: "Library", targets: ["Library"]),

Unfortunately I don’t think Xcode creates a Package.swift file when you use it to manage your SPM dependencies.

I’ve filed this as FB7643637 if any Apple folks want to take a look. There’s also a sample project attached.

1 Like

Trying to find it but last I played with this Xcode ignored the .dynamic and always used static, although building from the package itself would respect it. Haven't verified what the 11.4 behavior is and can't find a previous thread on it.

Xcode does not support SwiftPM's dynamic linking. It always use the static library one and no even swiftinterface (Library Evolution). So you can not do this. Until Apple support this feature.

If you need dynamic framework, using swift build to build binary framework and link it to your Xcode Project.

Xcode does not support SwiftPM's dynamic linking.

I’m hardly an expert on Swift packages, but there’s a specific fix mentioned in the Xcode 11.4 Release Notes that might apply here. Search for 55564324.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

In the meantime I have used DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC=YES in an xcconfig file to work around this problem.

3 Likes

If you’re thinking of:

iOS, tvOS, or watchOS apps with a Swift Package that builds a dynamic library can be submitted to the App Store. (55564324) (FB7303066)

That’s not the issue. The issue is that Xcode doesn’t allow you to choose to link packages dynamically when the package allows. It will choose static linking unless the article package explicitly sets dynamic linking (I think), which most don’t, as the default is automatic.

5 Likes

I should clarify: the issue fixed in 11.4 does help this issue, as it allows the "workaround" of a single imported dynamic library encompassing all other dependencies to actually work with apps submitted to the stores.

2 Likes

Hi Jon, can you explain in practice how this works?

Say I have:
A) A swift package which produces a dynamic library
B) An iOS app
C) A today widget

What settings do I use to be able to use the swift package in both B & C? I can't figure out a way to get this to work AND be accepted by iTunes upload.

Are you saying I need to create a new framework (D) which embeds A and then include D in C & C?

Thanks in advance

2 Likes

Today's Xcode 11.4.1 release does claim to fix some part of this issue:

  • Fixed an issue where an error like “Swift package product A is linked as a static library by B and C. This will result in duplication of library code.” was incorrectly emitted if an app and an embedded app extension or helper tool statically linked the same package product. If you previously set the DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC build setting to work around this issue, you can delete this setting now. (59310009, 61227255)
5 Likes

I wish we had an update to this because it seems like dependency resolution is still a nightmare in Xcode via SPM.

2 Likes

I guess Xcode 12 does not fix this issue. Has anyone tried? I haven't found any mention in Release Notes.

7 Likes

This is not resolved in Xcode 12 :(

4 Likes

It may actually have an additional problem.

I have an SwiftUI application that compiles on Xcode 11 and does create a valid application.

If I take the application as is and compile it on Big Sur using Xcode 12-beta (12A6159) it works as-is without changes. So far so good.

If I then create a new project using Multi-platform/App and add the same dependencies I can compile and run it on the Mac. Again so far so good.

But then when I want to enable previews the preview fails and the problem that is listed us similar as listed above:


Showing All Messages
Swift package target 'CNIOAtomics' is linked as a static library by 'AsyncHTTPClient' and 3 other targets. This will result in duplication of library code.

etc.

So for some reason the problem only shows during preview and not during a normal build and run.

4 Likes

It seems like this example is working with a package shared between iOS and macOS on xcode12. However I don't know how the package was setup. It did not use SPM, so is it telling us to not use SPM ?