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?

1 Like

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?

1 Like

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 https://developer.apple.com/go/?id=framework-imessage for a workaround."

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.

@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.

2 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.

3 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.

1 Like

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

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)
3 Likes
Terms of Service

Privacy Policy

Cookie Policy