You can think of an xcframework as a sumo "binary".
Here's how I understand things after going though this a few times:
An xcframework is for bundling multiple platforms together into a distributable binary package. You can put ios, ios-simulator, ios-macabi, darwin (macos), and tvos (and watchOS and carPlayOS and their respective simulator) platform code together into an xcframework. Those are your "library definitions". So the maximum number of frameworks (.framework) or libraries (.a) that can go in an xcframework at the top level is limited to the total number of platforms. And they all must be targeting different system interfaces (platforms) which means you can't put two binaries expecting e.g. the ios-simulator system interface into an xcframework at the top level.
In order to support the different architectures on each platform, you must lipo those architecture slices together to make a fat binary. Generally the options for those, on modern Apple hardware, are x86_64, and arm64v8 (aarch64). You may also need armv7 and i386 if you're targeting older hardware. The same rule goes for lipo, you can only have one instance of any given architecture slice in a fat binary which means you can't put two binaries targeting e.g. x86_64 hardware into a fat binary at the top level.
There is some literature suggesting that lipo is not an Apple tool and is not supported (3rd and 4th bullet point under Motivation & consequences section: https://awesomeopensource.com/project/bielikb/xcframeworks). I believe that to be inaccurate. lipo is distributed with Xcode, by Apple:
❯ lipo
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: ...
...
That resource is otherwise somewhat helpful and much appreciated. I believe the misunderstanding is that Xcode now does the heavy lifting so that you are no longer manually required to add special build phases and invoke lipo yourself anymore (unless you're not using Xcode, of course).
Look at the folders in the xcframework (other folders omitted for brevity):
❯ tree
.
└── Foo.xcframework
├── Info.plist
├── ios-arm64
│ └── libfoo-ios.a
├── ios-arm64_x86_64-maccatalyst
│ └── libfoo-ios-macabi.a
├── ios-arm64_x86_64-simulator
│ └── libfoo-ios-sim.a
└── macos-arm64_x86_64
└── libfoo-macos.a
Clearly Xcode is combining architecture slices when building frameworks that target e.g. ios-simulator. So this strategy seems to be both supported and the intended way to distribute a framework that can be used with multiple architectures.
Post
Replies
Boosts
Views
Activity
I wrote up some details in another answer asking essentially the same question:
https://developer.apple.com/forums/thread/666335?answerId=685927022#685927022
The summary is:
xcframework is a collection of (usually fat) platform binaries all targeting different platform system interfaces
framework or library is a collection of different mach-o binaries targeting various different hardware architectures but all targeting the same platform system interface.
You must use a combination of lipo and xcframework to achieve an ultimate sumo framework supporting multiple platforms and multiple architectures.
I don't know why Apple is absolutely no help or instruction regarding this issue, but you must use lipo to make fat binaries, one for each platform. Details https://developer.apple.com/forums/thread/666335?answerId=685927022#685927022.
@neywen we gave up on Xcode cloud.