This is a description of how to compile the Flutter Engine for Flutter Release 1.22.6 (Stable) with a bugfix that prevents executing code on the GPU if the app is in background mode. This version of the engine potentially resolves the following issues (not yet confirmed):
There is a pull request that potentially fixes the problem on the master branch (flutter/engine#24503). I transferred this fix manually for the flutter engine for 1.22.6. Unfortunately this pull request didn'fix the problem, but there was a second one (flutter/engine#24958) which amends pull request 24503). I also transferred this fix manually for the flutter engine for 1.22.6.
The changes I made (2 commits on Mar 2, 2021 (backport of pull request 24503) and 1 commits on Mar 12, 2021 (backport of pull request 24958)) can be seen here: https://github.com/Wooder/engine/commits/flutter_engine_for_stable_1_22_6_with_gpu_disable_sync_switch_via_appstate_fix
- install
depot_tools
(http://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up) (In case of problems: the setup of the Flutter Engine Dev environment is explained here: https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment) mkdir engine
in your desired root directory. In this directory create a file named.gclient
with the following content (the branch used is based on the Flutter engine used in 1_22_6 (engine revision 2f0af37152) on which the bugfix from gaaclarke (from commit 90c8015280344f1faf0127599351e264d4d9a9d7) was manually transferred. It also contains a bug fix in the DEP file (siehe flutter/flutter#72108 (comment))):
solutions = [ {
"managed": False,
"name": "src/flutter",
"url": "git@github.com:Wooder/engine.git@flutter_engine_for_stable_1_22_6_with_gpu_disable_sync_switch_via_appstate_fix",
"custom_deps": {},
"deps_file": "DEPS",
"safesync_url": "",
},
]
The following explantion is just for documentation purposes - its best to go to step 3 and continue:
Theres another patched flutter engine based on commit 40441def692f444660a11e20fac37af9050245ab - The branch is git@github.com:Wooder/engine.git@flutter_engine_at_40441def6_with_PR24958_PR24503_backport - I've backported flutter/engine#24958 and flutter/engine#24503 on this branch - I did it because the solution above lead to other crashes: see flutter/flutter#76068 (comment) and @gaaclarke suggested to try this.
If you want to give it a try use the follwing .gclient
file:
Unfortunately this solution does not compile in Xcode - flutter build ...
ends up with the following error:
Receiver: null
Tried calling: matchAsPrefix("ERROR: FormatException: Could not find an option named \"bytecode-options\".", 0)".
Oops; flutter has exited unexpectedly: "NoSuchMethodError: The method 'matchAsPrefix' was called on null.
Receiver: null
Tried calling: matchAsPrefix("ERROR: FormatException: Could not find an option named \"bytecode-options\".", 0)".
Oops; flutter has exited unexpectedly: "NoSuchMethodError: The method 'matchAsPrefix' was called on null.
Receiver: null
The problem seems to be that the flutter engine is too new and that's why this problem arises (tl;tr; "Your local engine and flutter checkout are out of sync, i.e. bytecode-options was removed as a compiler argument but your tool checkout is still passing that into the engine."): flutter/flutter#75357
solutions = [ {
"managed": False,
"name": "src/flutter",
"url": "git@github.com:Wooder/engine.git@flutter_engine_at_40441def6_with_PR24958_PR24503_backport",
"custom_deps": {},
"deps_file": "DEPS",
"safesync_url": "",
},
]
cd
to theengine
-Directory and executegclient sync
(this fetches alle required sources and will take about 1 hour)
-
Prepare the directories:
cd
to theengine/src
-directory and executeFor debug builds
- iOS debug for devices
./flutter/tools/gn --ios --unoptimized
- host debug
./flutter/tools/gn --unoptimized
- iOS debug for simulator
./flutter/tools/gn --ios --unoptimized --simulator
(iOS simulator)
For release builds
- iOS release build:
./flutter/tools/gn --ios --runtime-mode=release --unoptimized
- host release build:
./flutter/tools/gn --runtime-mode=release --unoptimized
(for details on compiling the engine see: https://github.com/flutter/flutter/wiki/Compiling-the-engine)
- iOS debug for devices
-
Compiling with ninja:
For debug builds
- debug build for iOS-devices:
ninja -C out/ios_debug_unopt
- host debug (always needed):
ninja -C out/host_debug_unopt
- debug build for iOS-simulator:
ninja -C out/ios_debug_sim_unopt
For release builds
- host release build:
ninja -C out/host_release_unopt
- iOS release build:
ninja -C out/ios_release_unopt
- The out-arguments must be adapted in Step 1 & 2 for optimized build
cd
in the directory of your flutter app and execute
- For a debug build on an iOS Device
flutter run --local-engine-src-path="/Users/yourusername/src/engine/src" --local-engine="ios_debug_unopt"
. - For a debug build on an iOS simulator
flutter run --local-engine-src-path="/Users/yourusername/src/engine/src" --local-engine="ios_debug_sim_unopt"
. - For a release build:
flutter run --local-engine-src-path="/Users/yourusername/src/engine/src" --local-engine="ios_release_unopt"
.
Now the app starts with the patched engine.
When you execute the following command (to build a release of the app)
flutter build ios --local-engine-src-path="/Users/xxx/src/engine/src" --local-engine="ios_release_unopt"
you will likely get this error message:
/Users/xxx/source_code/flutter_user/ios/Flutter/Flutter.framework/Flutter, building for iOS-armv7 but attempting to link with file built for iOS-arm64
Undefined symbols for architecture armv7:
"_OBJC_CLASS_$_FlutterStandardMessageCodec", referenced from:
objc-class-ref in FlutterWebView.o
"_OBJC_CLASS_$_FlutterError", referenced from:
objc-class-ref in FLTWKNavigationDelegate.o
objc-class-ref in FlutterWebView.o
"_FlutterMethodNotImplemented", referenced from:
-[FLTCookieManager handleMethodCall:result:] in FLTCookieManager.o
___83-[FLTWKNavigationDelegate
This is caused by Issue flutter/flutter#51989 which was fixed with Pull Request flutter/flutter#73072. Unfortunately, the fix is not yet included in the flutter tools for stable 1.22.6, so we need a workaround.
The workaround is to build the app only for arm64 (all 64 bit iPhones better than iPhone 5/ iPhone 5c).
- Add the following post install hook to your Podfile (maybe merge it with an existing post install hook - only one hook is allowed):
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES'
end
end
end
- In Xcode open your build settings and set "Build Active Architecture Only" to YES for Debug/Profile/Release builds
- In Xcode open your build settings and set architectures the following way: Remove "$ARCHS_STANDARD" and add "arm64"
cd
into~/src/engine/src/out/ios_release_unopt/clang_x64
(the directory of your self built flutter engine) andcp gen_snapshot gen_snapshot_arm64
- Xcode expects thegen_snapshot_arm64
however after compiling the file is namedgen_snapshot
(but is arm64)- Change to the source directory of your flutter app in which you want to run
flutter build ios ..."
flutter clean
flutter build ios --local-engine-src-path="/Users/xxx/src/engine/src" --local-engine="ios_release_unopt"
- Now a error shows up but Generated.xcconfig was created and
pod install
was executed (Have a look atGenerated.xcconfig
inside Xcode) - Building the app in Xcode: Open the .xcworspace of your app with Xcode and select "Any iOS Device (arm64)" as target
- In the Xcode main menu: Product -> Archive
- Do NOT update architectures if Xcode asks to do so
- The IPA for your app should now be created successfully