xcodebuild
can build a project with sdk set to either iphoneos
or iphonesimulator
but not both, so in order to generate a framework containing armv7 arm64
and i386 x86_64
architectures, I have to run xcodebuild
twice and then use lipo
to combine all the architectures into 1 universal binary. I see commercial framework that does this but it result in an incorrect info.plist
file because it has a field, CFBundleSupportedPlatforms
and all signs point to it only containing 1 value, e.g., CFBundleSupportedPlatforms = ( "iPhoneSimulator" )
.
Seems like lipo
shouldn't be used in this manner because it isn't officially supported by xcodebuld
. Is there a better way to build a framework to contain all architectures?
Whereas Universal Frameworks contain many slices without knowledge of the platform SDK for each one, XCFrameworks contain many slices organized by platform. Because of this platform-awareness, an XCFramework can target more than one platform for the same architecture, which solves our problem.
Select Project Target → Edit Schema → Archive → Post-actions → Press “+” → New Run Script Action. After completion of archive process the above script will be execute and generate the universal framework and will open in project directory itself. Now your universal framework is ready.
iOS and iPadOS arm64 is the current 64-bit ARM CPU architecture, as used since the iPhone 5S and later (6, 6S, SE and 7), the iPad Air, Air 2 and Pro, with the A7 and later chips.
Remove the architectures (using lipo -remove ) that aren't necessary for the device slice of the XCFramework. Remove the architectures (using lipo -remove ) that aren't necessary for the simulator slice of the XCFramework. Combine the two slices into an XCFramework using xcodebuild -create-xcframework .
I follow the question, but I suppose I am a bit puzzled why you want to unnecessarily bloat a single .framework
with simulator-only i386 and x84_64 slices that are really only relevant to your development builds. Would you by chance be wanting to distribute a framework to other developers and want to make it work on simulator as well as device?
If so, you are on the right track with using lipo
to join the thin binaries for device together or to join the thin binaries for simulator together, but shouldn't be trying to spawn one single device and simulator framework. Apple's own use of SDKs and Frameworks serves as the guide here. Within Xcode, there are two different platform SDKs -- iPhoneOS.platform and iPhoneSimulator.platform that contain the SDKs with only the slices for the relevant target architectures:
You can drill into each of these folders and find the UIKit frameworks do indeed follow the per-platform idea and are conditionally linked based on the SDK that is in use:
I'd further guess that you wanted to have one universal, all-architectures framework so that consuming developers didn't have to remember to swap out one .framework file for another depending on how they were compiling the app. The great news is that you can use conditional linking flags to be able to affect this without needing to do file-system swaps!
As folks adopt your library, part of the setup should be to use conditional linking -- Within the OTHER_LINKER_FLAGS
option you can have per-configuration (Debug, Release, Ad-Hoc, etc.) build settings and can also have per-Architecture or per-SDK specific settings too:
To get access to these SDK-specific settings you'll need to click the + next to each of your build configurations where you want to custom tailor framework linking. You can then select the appropriate SDKs from the dropdown list and add your linker flags for each of the two target frameworks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With