You can think of an
xcframework as a sumo "binary".
Here's how I understand things after going though this a few times:
xcframework is for bundling multiple platforms together into a distributable binary package. You can put
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
arm64v8 (aarch64). You may also need
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:
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):
│ └── libfoo-ios.a
│ └── libfoo-ios-macabi.a
│ └── libfoo-ios-sim.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.