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?
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?
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."
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.
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.
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.
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.
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.
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?
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)
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.
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 ?