This PR fixes two issues. Accidental reuse of code assets between build modes and SDKs (https://github.com/flutter/flutter/issues/181724), and the bundling in ios-frameworks (https://github.com/flutter/flutter/issues/181382). To fix the accidental caching, the `Target`s related to build hooks and code assets now output their files to `environment.outputDir` instead of `$projectDir/$buildDir/native_assets`. * `xcode_backend` is updated to deal with this. * `Flutter.kt` has been updated to deal with this. * Because the `Target`s are responsible for caching, the code has been refactored to provide the target directories from there. The "global-ish" function `nativeAssetsBuildUri` that was calculating the directory before has been removed. * `runFlutterSpecificHooks` has nothing to do with that directory, it's access to it has been removed. * To avoid another cmakefile migration, the Linux and Windows implementation use the same directory. (Note that output dir and build dir overlap for Linux and Windows, while they do not for MacOS, iOS, and Android.) * This also means that we don't have to read `NativeAssetsManifest.json` in `xcode_backend` anymore. Instead the `Target` clears the output directory, so we should not have any stale frameworks. * Refactored `installCodeAssets` and its platform-specific implementations to return a list of all produced files. These are now added to the `Target`'s depfile. This fixes an issue where the build system would skip re-installing native assets after an Xcode "Clean Build Folder because it wasn't tracking the frameworks/dylibs as outputs. Closes: https://github.com/flutter/flutter/issues/181724 Other `Target`s related tweaks: * Added proper `Source.pattern('{BUILD_DIR}/${DartBuild.dartHookResultFilename}'),` for all `Target`s that depend on that file. These were missing. (The build system uses `dependencies` for ordering of `Target`s, but relies on `inputs` and `outputs` for caching.) * Removed code assets from `CopyAssets`. That target is supposed to make an asset-bundle that is OS-independent if I understand correctly. This PR changes the way code assets are bundled in `flutter build ios-framework`. * This PR now packages in an `.xcframework`, which is necessary to be able to package both device and simulator. * Run through the frameworks of both device and simulator and give errors on inconsistencies. Closes: https://github.com/flutter/flutter/issues/181382 Other iOS related tweaks: * Use `xcrun` for invoking all the commands. (This is used for producing the app framework, but was not for code assets frameworks.) * Make sure all commands are added to the traces when running verbose. (Also to bring it in line for with the other `xcrun` commands.) Testing: * The integration test is updated to inspect the `xcframework`s. * Added a test that simulates Xcode "Product > Clean Build Folder...", to check that it now correctly triggers a rebuild. * We do _not_ have an integration test that _runs_ the frameworks output from `flutter build ios-framework` inside a host app at all as far as I'm aware. * dev/devicelab/bin/tasks/build_ios_framework_module_test.dart builds a framework, but doesn't run it in a host app * dev/integration_tests/ios_add2app_life_cycle/build_and_test.sh runs, but does so via `flutter build ios` not as a framework. * Does not add an integration test for caching behavior between switching build modes. However, the proper functioning of `flutter build ios-framework` depends on the `Target`s for different not using overlapping directories. Architectural approaches tried but didn't work: * Subclass `InstallCodeAssets` per OS to be more precise in the `output`s on what files are output. This doesn't work because other OS-independent targets on the `InstallCodeAssets` target.
The Flutter Gradle Plugin
This directory contains Gradle code used to by the Flutter tool to build Flutter apps for Android, primarily the Flutter Gradle Plugin (FGP) - a Gradle plugin built on top of Gradle and the Android Gradle Plugin (AGP).
Editing in Android Studio
To get code completion in Android Studio, you must open a new Android Studio window with this directory as the root. Code completion will not work when navigating to files in an Android Studio window opened at the root of the entire Flutter repo.
Contributing
The Flutter Gradle Plugin is currently being re-written from Groovy to Kotlin
(Kotlin source specifically, i.e. not .kts). As such, outside of critical bug fixes,
new contributions will only be accepted in src/main/kotlin (and src/test/kotlin).
Testing
To run the tests from the CLI, you first need to download the Gradle wrapper.
- Ensure you have run gclient sync recently (i.e., from the root of your framework checkout, run
gclient sync -D). - From this directory, run
../../../engine/src/flutter/third_party/gradle/bin/gradle wrapper.
Tests can be run in Android Studio, or directly with Gradle: ./gradlew test
(note that this directory does not contain a version controlled Gradle file. You can find one in
the engines third_party directory at
<flutter_root>/engine/src/flutter/third_party/gradle/bin/gradle).
If you can not run the test task try running ./gradlew tasks. If that does not work then there is
a configuration error. The most common one is using the wrong version of java. Java can be
overridden by setting the JAVA_HOME environment variable.
This example sets the java version to 17 downloaded with brew and then runs the tests:
JAVA_HOME=/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home/ ./gradlew test
You can run all the tests in one file by passing in the fully qualified class name,
e.g. ./gradlew test --tests com.flutter.gradle.BaseApplicationNameHandlerTest, or one test in
one file by passing in the fully qualified class name followed by the method name,
e.g ./gradlew test --tests "com.flutter.gradle.BaseApplicationNameHandlerTest.setBaseName respects Flutter tool property".
Sometimes changing a test name and then running it will cause an IDE error. To get Android Studio back
to a good state on Mac, run Help > "Repair IDE", and then in the popup window "Rescan project indexes > Everything works now."
To add a new test, add a class under src/test/kotlin, with methods annotated with @Test.
These tests will get automatically run on CI by packages/flutter_tools/test/integration.shard/android_run_flutter_gradle_plugin_tests_test.dart.