For my iOS app I have written a Framework (let's call it A) that depends on another Framework (B). Everything is working except for one issue:
The resulting Framework A is quite large in size (100 MB) as it depends on numerous other frameworks. I am shipping the framework with all architectures included.
So what's working is:
App
--Framework A
--Framework B
What I would like to achieve is
App
--Framework A
--Framework B
In a way that Framework A has access to Framework B. This would mean that I don't have to ship my Framework A together with Framework B in it. It would also mean that one could always update Framework B without having to wait for me updating Framework A.
All this would not be an issue if I could just open source my Framework A but unfortunately this isn't the case here.
A little bit of background on Framework A: It is a Swift Framework targeting iOS iPhone as well as Simulator. I ship it as a fat framework built by an Aggregate target following the instructions given here: https://medium.com/@priya_talreja/create-custom-universal-framework-in-ios-aef7fa6fd51e. Then I add the .framework file to my app's Frameworks folder so it's showing up under Frameworks, Libraries, and Embedded Content in my app's Xcode Project.
I would much appreciate any help I could get on this. Or maybe the correct terminology so I can search for similar issues.
In general, it is not required to embed a framework and it can be located anywhere* as long as install paths and runtime search paths are appropriately specified in the binary.
Oh wow I have always wondered why these options exist in first place. Thank you for your response!
One more question: is this approach in any way compatible with the Swift PM? In a way that I can add the dependencies via Swift PM but not include them in the project?
AFAIK Swift PM is free to arrange your dependencies as it sees fit. I'm not aware how its deduplication strategy works, you need to experiment with that.
I'd consider Xcode project support being a "collateral", so do not rely too much on that. You should be able to use custom build configurations though.
I ship it as a fat framework built by an Aggregate target following
the instructions given here …
FYI, this approach isn’t something we support. iOS and its simulator are two different platforms and a universal binary can’t contain architectures from different platforms.
The recommended alternative is an XCFramework, as described in WWDC 2019 Session 416 Binary Frameworks in Swift.
Hey Eskimo, I know you from the Apple Forums and I know that you say that a lot but be assured that A LOT of apps make use of this kinda stuff. I've been shipping like that since ever.
I appreciate Apple's approach on the issue by introducing XCFramework but like everything Framework-related in Xcode, it's dangerously underdocumented. It almost feels as incomplete as the workaround solutions developed by the community over the years.
It took me days to get an XCFramework build going and then, for some reason, it was twice the size of my "hacky" .framework which works perfectly for me so there must be some very big overhead when the community solution that works perfectly is only half as large as the official way.
I really wish Apple would make things simpler there
but be assured that A LOT of apps make use of this kinda stuff.
True, but that doesn’t make it correct. Clearly I’m jaded because I get to watch my colleague, who supports developer tools for DTS, rescue folks from this pitfall time and time again. It’s a bit like calling AppKit from a secondary thread: It seems to work, until it doesn’t )-:
As a point of interest, we used to have to build fat binaries for OS X back in the day when building binaries (applications, frameworks, libraries, etc.) for PowerPC and Intel. I don't develop for iOS, so, I can't comment on that environment, but, what has changed for macOS, and how will that translate into the Apple Silicon Macs when we get there? Understand if you can't comment on that until later.
The situation you describe is not what Eskimo is talking about. "Universal Binaries" support multiple architectures for the same platform. That's how PPC/Intel binaries work, that's how Intel/Apple Silicon binaries will work. What isn't supported (but which you can hack to work) is multiple platforms in a single binary. These cross platform binaries would have iOS/Simulator or iOS/macOS slices. Even on the same architecture that won't work. You have to use the new XCFramework, which can contain, as separate binaries, the Universal Binaries of a framework for multiple platforms.