You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Investigate outputting App.framework as xcframework #36204
Xcode 11 introduces a new bundle format .xcframework for distributing frameworks for multiple platforms and architectures. At build time, the correct version of the framework is linked on.
Creating an App.xcframework may decrease iOS and macOS build time by cutting out the lipo stages, since App.xcframework could be built with all supported architectures and not one fat binary.
There doesn't seem to be support for build configuration since this feature is really for distribution, so it's expected to come from an Archive (which is Release by default). So we may need:
App.xcframework
App-profile.xcframework
App-release.xcframework
?
Which means different linker flags per build configuration.
Impact
Could remove xcode_backend.sh thin.
Could simplify build_aot.dart, mac.dart. Find usages of getNameForIOSArch and calls to lipo to see where the code would need to change.
@xster - add-to-app implications for easier linking in host app @cbracken - I think he added the first version of app thinning @stuartmorgan - impact to flutterMacOSFramework code paths @jonahwilliams - flutter assemble work
The frameworks in the architecture directories looks like a normal framework. So "only works in Xcode 11" means that the .xcframework can only be linked directly in Xcode 11. However once the .xcframework is created, versions of Xcode earlier than 11 can still link on the App.framework in the right arch directory, which still cuts out the lipo. But flutter tools would need to figure out those directories instead of letting Xcode handle it at build time.
I assume the xcframework can also only be generated on machines with xcode 11 right? In other words, in a flutter build framework command, we might still need to produce 2 paths to support machines on xcode 10- that invoke that command?
I assume the xcframework can also only be generated on machines with xcode 11 right? In other words, in a flutter build framework command, we might still need to produce 2 paths to support machines on xcode 10- that invoke that command?
Yes, xcodebuild -create-xcframework only works on Xcode 11.
When App.framework isn't version controlled (is that binary ever?), flutter build aot/xcode_backend.sh/whatever flutter assemble becomes can decide which bundle to build and link based on the locally installed version of Xcode, right?
The xcframework bundle looks pretty simple. That xcodebuild command could be skipped if flutter tools signed up for copying the .framework files to the right directories and generating that Info.plist. Xcode 10 could link on the .framework, and Xcode 11 could link on the xcframework.
The flutter tooling already knows the bundle structure on iOS (example Flutter.framework as a dylib with headers copied to a Headers directory, or copying files to /Versions/A/) so that bridge is crossed.
Add-to-app tooling might need to handle both types of bundles?
A- If both supplier and consumer have xcode 11, you just invoke flutter build framework, no arguments, then in your outer project, declare dependency onto the xcframework. Then everything's driven by your outer project's supported architectures.
B- If either doesn't have xcode 11, you do some manual steps. i.e. if the supplier doesn't have, you need to pass the architecture to the flutter build framework command so it lipos the the right thing. If the consumer doesn't have it, it needs to go depend on the .framework subdirectory in the .xcframework directory depending on what architecture they want in the outer project.
Is that right? i.e. we can't really delete xcode_backend.sh thin
A- If both supplier and consumer have xcode 11, you just invoke flutter build framework, no arguments, then in your outer project, declare dependency onto the xcframework. Then everything's driven by your outer project's supported architectures.
Yes, Xcode would handle linking the right App.framework architecture based on the outer project's architecture.
B- If either doesn't have xcode 11, you do some manual steps. i.e. if the supplier doesn't have, you need to pass the architecture to the flutter build framework command so it lipos the the right thing. If the consumer doesn't have it, it needs to go depend on the .framework subdirectory in the .xcframework directory depending on what architecture they want in the outer project.
Is that right? i.e. we can't really delete xcode_backend.sh thin
We could go two ways:
Stop making fat universal binaries and instead manually make a xcframework with the right architecture directories. flutter tools would be on the hook for setting up the linker flags to point at the right App.framework architecture based on the outer app's target architecture. Then thin could go away.
Have two code paths, as you say, and keep thin (less risky).
BUT:
When I moved beyond the barest proof of concept and looked at how build_aot creates the framework in release mode, it doesn't even work!
xcodebuild -create-xcframework -framework build/aot/armv7/App.framework -framework build/aot/arm64/App.framework -output build/aot/App-release.xcframework
Both ios-arm64 and ios-armv7 represent two equivalent library definitions.
Maybe they didn't bother supporting ios-armv7 since it was last used in the iPhone 4S/iPad 2 A5 chip (2011 generation)? Just guessing since there's no official documentation for this feature...
Oh ok, got it. You're saying the supplier doesn't need xcode 11 since we can manually package .frameworks up into the .xcframework vehicle. (kinda like what this guy is doing manually https://github.com/jeffctown/xcframework)
If we can produce an example of how to consume it without xcode 11, this SGTM.
Is the problem specifically around 32bit arm? i.e. if you did that exercise with x64 and 64bit arm it works?
It seems to think that arm64, arm64e, armv7, and arm7s (default VALID_ARCHS) all represent "equivalent library definitions" and I get the same error, though the Mach-O runtime architectures are different:
This feature really seems to be about platforms and variants (simulator) rather than architecture.
So it's still interesting for swapping between real devices and simulators, or distributing iOS and macOS and UIKit for Mac the same way if we also investigated for Flutter.xcframework, but it doesn't look like it's going to get the tools off app framework thinning.
I didn't watch the whole thing but looking through the slides at https://developer.apple.com/videos/play/wwdc2019/416, they never explicitly talked about architectures. Just mixing swift/objc, uikit/appkit etc. Are the iOS-UIKit-objc framework part of a xcframework still a fat binary? Maybe it's trying to address issues at a different granularity than architectures.
Are the iOS-UIKit-objc framework part of a xcframework still a fat binary? Maybe it's trying to address issues at a different granularity than architectures.
Seems to be. I had hopes because the subdirectories in my prototype looked like:
├── ios-arm64/
├── ios-x86_64-simulator/
etc. and the Info.plist contained lists of SupportedArchitectures. I was hoping to get
Creating an App.xcframework may decrease iOS and macOS build time by cutting out the lipo stages
How much time would cutting out the lipo save? We could also accomplish something similar by moving the lipo call into part of the targets for the iOS flutter assemble implementation. Then it will be skipped by the flutter_tool/xcode if the architectures/inputs haven't changed
Hi @jmagman i have a question about this closed issue, apple actually doesn't support create archives in lower versions than Xcode 12, i have older version of flutter (v1.7.8+hotfix.4) after usage of XCFrameworks, that means my build can't find armv7 architecture having this issue
lipo: -extract armv7 specified but fat file: /Users/xyz/Library/Developer/Xcode/DerivedData/Runner-dadfkcamaimtsnhgjdoojqnyuztv/Build/Intermediates.noindex/ArchiveIntermediates/Runner/InstallationBuildProductsLocation/Applications//Runner.app/Frameworks/App.framework/App does not contain that architecture
there is a posibility to fix this issue in older version of flutter or is necessary upgrade flutter?
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.
Activity
jmagman commentedon Jul 15, 2019
XCFramework bundle layout
I made a xcframework to see what gets put where in the bundle. I archived a few frameworks from macOS, iOS, iOS simulator, and tvOS.
Here's the Info.plist (note SupportedArchitectures and SupportedPlatformVariant keys):
Info.plist.txt
$ plutil -p Info.plist
{
"AvailableLibraries" => [
0 => {
"LibraryIdentifier" => "ios-x86_64-simulator"
"LibraryPath" => "DistributedFramework.framework"
"SupportedArchitectures" => [
0 => "x86_64"
]
"SupportedPlatform" => "ios"
"SupportedPlatformVariant" => "simulator"
}
1 => {
"LibraryIdentifier" => "ios-arm64"
"LibraryPath" => "DistributedFramework.framework"
"SupportedArchitectures" => [
0 => "arm64"
]
"SupportedPlatform" => "ios"
}
2 => {
"LibraryIdentifier" => "macos-x86_64"
"LibraryPath" => "DistributedFramework.framework"
"SupportedArchitectures" => [
0 => "x86_64"
]
"SupportedPlatform" => "macos"
}
3 => {
"LibraryIdentifier" => "tvos-arm64"
"LibraryPath" => "DistributedFramework.framework"
"SupportedArchitectures" => [
0 => "arm64"
]
"SupportedPlatform" => "tvos"
}
]
"CFBundlePackageType" => "XFWK"
"XCFrameworkFormatVersion" => "1.0"
}
Build configurations
There doesn't seem to be support for build configuration since this feature is really for distribution, so it's expected to come from an Archive (which is Release by default). So we may need:
App.xcframework
App-profile.xcframework
App-release.xcframework
?
Which means different linker flags per build configuration.
Impact
xcode_backend.sh thin.getNameForIOSArchand calls tolipoto see where the code would need to change.flutter/packages/flutter_tools/lib/src/build_info.dart
Line 290 in 13382f4
jmagman commentedon Jul 15, 2019
@xster - add-to-app implications for easier linking in host app
@cbracken - I think he added the first version of app thinning
@stuartmorgan - impact to flutterMacOSFramework code paths
@jonahwilliams -
flutter assembleworkjmagman commentedon Jul 15, 2019
The frameworks in the architecture directories looks like a normal framework. So "only works in Xcode 11" means that the .xcframework can only be linked directly in Xcode 11. However once the .xcframework is created, versions of Xcode earlier than 11 can still link on the App.framework in the right arch directory, which still cuts out the lipo. But flutter tools would need to figure out those directories instead of letting Xcode handle it at build time.
xster commentedon Jul 15, 2019
I assume the xcframework can also only be generated on machines with xcode 11 right? In other words, in a
flutter build frameworkcommand, we might still need to produce 2 paths to support machines on xcode 10- that invoke that command?jmagman commentedon Jul 15, 2019
Yes,
xcodebuild -create-xcframeworkonly works on Xcode 11.When App.framework isn't version controlled (is that binary ever?),
flutter build aot/xcode_backend.sh/whatever flutter assemble becomes can decide which bundle to build and link based on the locally installed version of Xcode, right?The xcframework bundle looks pretty simple. That xcodebuild command could be skipped if flutter tools signed up for copying the .framework files to the right directories and generating that Info.plist. Xcode 10 could link on the .framework, and Xcode 11 could link on the xcframework.
The flutter tooling already knows the bundle structure on iOS (example Flutter.framework as a dylib with headers copied to a Headers directory, or copying files to /Versions/A/) so that bridge is crossed.
Add-to-app tooling might need to handle both types of bundles?
xster commentedon Jul 15, 2019
Ah ok, so we're still saying there are 2 paths.
A- If both supplier and consumer have xcode 11, you just invoke
flutter build framework, no arguments, then in your outer project, declare dependency onto the xcframework. Then everything's driven by your outer project's supported architectures.B- If either doesn't have xcode 11, you do some manual steps. i.e. if the supplier doesn't have, you need to pass the architecture to the
flutter build frameworkcommand so it lipos the the right thing. If the consumer doesn't have it, it needs to go depend on the .framework subdirectory in the .xcframework directory depending on what architecture they want in the outer project.Is that right? i.e. we can't really delete
xcode_backend.sh thinjmagman commentedon Jul 15, 2019
Yes, Xcode would handle linking the right App.framework architecture based on the outer project's architecture.
We could go two ways:
thincould go away.thin(less risky).BUT:
When I moved beyond the barest proof of concept and looked at how build_aot creates the framework in release mode, it doesn't even work!
Maybe they didn't bother supporting ios-armv7 since it was last used in the iPhone 4S/iPad 2 A5 chip (2011 generation)? Just guessing since there's no official documentation for this feature...
xster commentedon Jul 15, 2019
Oh ok, got it. You're saying the supplier doesn't need xcode 11 since we can manually package .frameworks up into the .xcframework vehicle. (kinda like what this guy is doing manually https://github.com/jeffctown/xcframework)
If we can produce an example of how to consume it without xcode 11, this SGTM.
Is the problem specifically around 32bit arm? i.e. if you did that exercise with x64 and 64bit arm it works?
jmagman commentedon Jul 15, 2019
It seems to think that arm64, arm64e, armv7, and arm7s (default VALID_ARCHS) all represent "equivalent library definitions" and I get the same error, though the Mach-O runtime architectures are different:
For reference when all VALID_ARCHS are selected, I only see armv7 and arm64 (I don't know enough about this topic to tell you why):
This feature really seems to be about platforms and variants (simulator) rather than architecture.
So it's still interesting for swapping between real devices and simulators, or distributing iOS and macOS and UIKit for Mac the same way if we also investigated for Flutter.xcframework, but it doesn't look like it's going to get the tools off app framework thinning.
xster commentedon Jul 16, 2019
I didn't watch the whole thing but looking through the slides at https://developer.apple.com/videos/play/wwdc2019/416, they never explicitly talked about architectures. Just mixing swift/objc, uikit/appkit etc. Are the iOS-UIKit-objc framework part of a xcframework still a fat binary? Maybe it's trying to address issues at a different granularity than architectures.
jmagman commentedon Jul 16, 2019
Seems to be. I had hopes because the subdirectories in my prototype looked like:
etc. and the Info.plist contained lists of SupportedArchitectures. I was hoping to get
but it doesn't seem to split it up beyond arm64.
jonahwilliams commentedon Jul 16, 2019
How much time would cutting out the lipo save? We could also accomplish something similar by moving the lipo call into part of the targets for the iOS flutter assemble implementation. Then it will be skipped by the flutter_tool/xcode if the architectures/inputs haven't changed
jmagman commentedon Feb 8, 2020
Minimum version was just updated to Xcode 11: #50371
jmagman commentedon Nov 14, 2020
Closing this. App.frameworks are not distributed binaries.
alexviquez commentedon May 1, 2021
Hi @jmagman i have a question about this closed issue, apple actually doesn't support create archives in lower versions than Xcode 12, i have older version of flutter (
v1.7.8+hotfix.4) after usage of XCFrameworks, that means my build can't find armv7 architecture having this issuethere is a posibility to fix this issue in older version of flutter or is necessary upgrade flutter?
jmagman commentedon May 4, 2021
@alexviquez we don't hotfix old versions of Flutter. However, you can fork Flutter and add your own patches to the branch you're on.
https://github.com/flutter/flutter/wiki/Flutter-build-release-channels#will-a-particular-bug-fix-be-provided-in-a-hotfix-release
I recommend upgrading, though (if there's a bug preventing you from upgrading, please file it!)
github-actions commentedon Aug 2, 2021
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.