Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@dnfield
Copy link
Contributor

@dnfield dnfield commented Jul 10, 2021

Makes scenario_app part of the GN build.

This deletes shell scripts that were used solely by developers/internal scripts to compile assets, since that is all now taken care of by GN/Ninja.

It leaves scripts that are currently used by CI. Once this change is in place, CI can be changed to avoid using those scripts, in particular ones that directly invoke ninja/autoninja, which is incompatible with upcoming verisons of depot_tools/LUCI.

High level overview of changes:

  • New build rules added to create dart kernel and AOT/JIT gen_snapshot artifacts for Android/iOS
  • New build rule that invokes gradle and tries to get it to use the out/android_whatever directory for build output.
  • Updates to gradle scripts to avoid copying things into the source tree, e.g. pulling flutter.jar and libapp.so from the out directory instead of from the source tree. This means that the gradlew builds will no longer work without specifying these properties.
  • Copy the scenario app into the out direcotry using copy_trees to avoid mutating the source tree during build.
  • Create the App.framework directly in out/ios_whatever/scenario_app/Scenarios instead of in the source tree.
  • Updates to the Scenario xcodeproj to refer to Flutter.xcframework from two directories up (e.g. out/ios_whatever/scenario_app/Scenarios/../../Flutter.xcframework) to avoid needless copying.
  • Delete the compile_[ios|android]_[jit|aot].sh scripts.
  • Update the run_and_build_[ios|android]tests.sh and the build[ios|android]_tests.sh scripts to use the GN/ninja built artifacts to avoid disruptions on CI

These builds also avoid needing a host toolchain build by using prebuilt dart sdk.

While working on this patch, I discovered that the scenario_app FTL android test is completely broken. That's fixed separately in #27295.

This work should help unblock adding a test harness for #27141

Related bugs:
fixes flutter/flutter#53455
part of flutter/flutter#84618
part of flutter/flutter#84290

/cc @godofredoc

Copy link
Member

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorely needed. LGTM with some nits and comments.


kernel_target = "_${target_name}_kernel"
snapshot_target = "_${target_name}_snapshot"
is_aot =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Perhaps add assert(!is_fuchsia) here as this would be invalid on that target.

@richkadel: FYI, you may run into such assumptions while working with engine GN rules for Dart. We can patch them later though. The issue is that the assumption of AOT being tied to a specific runtime mode does not hold on Fuchsia.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fuchsia has its own template(s) for this.

Perhaps we could add it as an arg and default it to this, and let fuchsia specify the arg differently?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flutter_runtime_mode can also be jit_release. It might simplify things for Fuchsia to use that to signal that a release build is using JIT rather than AOT (if it isn't like that already.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now I'm just moving this to //flutter/testing/scenario_app/runtime_mode.gni.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Errr... wrong comment thread - I moved it from common.gni. I'll add the assert.

#
# Invoker must supply dart_main and package_config. Invoker may optionally
# supply aot as a boolean and product as a boolean.
template("dart_snapshot") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an unfortunate repetition of the rule (in //flutter/testing/testing.gni) used by the gtest harness for Dart fixtures. Can we dry this up (in a later patch if you wish)? If anything, //build/dart/rules.gni is the right spot for such rules.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will lead to template name collision if both gnis are included from a .GN definition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are now several places where we have rules like this - I'd like to clean them up separately to avoid potential issues that only get caught in post submit :\

One thing I can see is that the testing rules lack special handling for iOS, which will need to be addressed.

main_dart = rebase_path(invoker.main_dart)
package_config = rebase_path(invoker.package_config)

platform_dill = "$root_out_dir/flutter_patched_sdk/platform_strong.dill"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit: Presumably, these are outputs of the //flutter/lib/snapshot dep below. Can we use get_label_info with target_gen_dir to determine the location of these artifacts? Right now, these paths are hardcoded in unrelated rules.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't in the target_gen_dir of that target - it's hard coded in there.

Changing that is possible, but right now recipes depend on this location being where it is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a goal of cleaning up the way recipes get artifacts though - and once that's all set, we can start changing these things more easily.

# supply aot as a boolean and product as a boolean.
template("dart_snapshot") {
assert(defined(invoker.main_dart), "main_dart is a required parameter.")
assert(defined(invoker.sources), "sources is a required parameter.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why must the sources be explicitly specified even though the script action supports depfiles? Seems redundant. The main_dart and the package configuration ought to sufficient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is wrong, removed it.

outputs = [ kernel_output ]

depfile = "$kernel_output.d"
abs_depfile = rebase_path(depfile)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: Not that it matters here, but using absolute paths trips up compiler proxies. If the script supports relative depfile paths, I'd recommend just using relative paths from the get go.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was cargo-culted from another template - it seems to make dart happy, which doesn't support compiler proxies so... I guess it's ok?

"--output=" + rebase_path(kernel_output),
]

if (is_debug) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused if you meant is_debug to mean unopt instead of the debug runtime mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably rename this to is_unopt. But that's what it means - it's distinct from the runtime mode.

flutter_prebuilt_dart_sdk = false
}

is_aot = flutter_runtime_mode == "profile" || flutter_runtime_mode == "release"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't hold for Fuchsia. I don't think we should add this to the common config if its not actually true everywhere.

# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This file has rules for making Dart packages and Dart-based Mojo applications.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider updating this comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed this earlier - done

args += [ "--enable_asserts" ]
}

if (!is_aot) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think positive: if (is_aot) { ... } else { ... }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

} else if (is_ios) {
_flutter_assets_dir =
"$root_out_dir/scenario_app/Scenarios/App.framework/flutter_assets"
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest adding a final else clause that contains only an assert(false, error message).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


kernel_target = "_${target_name}_kernel"
snapshot_target = "_${target_name}_snapshot"
is_aot =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flutter_runtime_mode can also be jit_release. It might simplify things for Fuchsia to use that to signal that a release build is using JIT rather than AOT (if it isn't like that already.)

vm_args = [
"--depfile=$abs_depfile",
"--depfile_output_filename=$rebased_output",
"--disable-dart-dev",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this flag need to come first?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know - it's how the VM gets invoked today though and it doesn't complain?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just asked around. It did have to come first at some point in the past, but it can go anywhere now.

import("//flutter/common/config.gni")
import("//third_party/dart/build/dart/dart_action.gni")

# Creates a dart kernel (dill) file suitalbe for use with gen_snapshot.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the template does more than just generate the .dill file. For AOT, it generates the AOT snapshot, and in non-AOT it generates an app-jit snapshot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the comment.

package_config = rebase_path(invoker.package_config)

platform_dill = "$root_out_dir/flutter_patched_sdk/platform_strong.dill"
gen_kernel_script = "//third_party/dart/pkg/vm/bin/gen_kernel.dart"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why gen_kernel and not //flutter/flutter_frontend_server? Using the flutter_frontend_server would more closely mimic how the flutter_tool compiles Dart: https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/compile.dart#L268

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - done. Although this is a small change in behavior, since before the scenario app was not using the flutter_frontend_server.

flutter_patched_sdk = rebase_path("$root_out_dir/flutter_patched_sdk")

deps = [
"//flutter/flutter_frontend_server:frontend_server",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was previously only built when targeting the host. It's built for those configurations as an app-jit snapshot for fast startup because it's distributed as an engine artifact for use by end-users. During an iOS/Android build, if it's only being used for a small number of targets, then it will take longer to build the app-jit snapshot than the time it saves by starting up more quickly. That being the case, I'd suggest running this from source using prebuilt_dart_action().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, will change - I noticed the build time went up doing it this way :\

vm_args = [
"--depfile=$abs_depfile",
"--depfile_output_filename=$rebased_output",
"--disable-dart-dev",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just asked around. It did have to come first at some point in the past, but it can go anywhere now.


import("//flutter/common/config.gni")

is_aot = flutter_runtime_mode == "profile" || flutter_runtime_mode == "release"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to assert at the top-level of this file that the target OS is iOS or Android?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

# This file is suitable for use within the tree. A different _embedder.yaml
# is generated by the BUILD.gn in this directory. Changes here must be
# mirrored there.
# This file is generated by //flutter/sky/packages/sky_engine:_embedder_yaml
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused by this comment. Is the behavior any different than before this change? If so, are there some changes to the BUILD.gn file that didn't get pushed?

Also, weren't there some other users of this file aside from the scenario apps? If not, and this file is only ever used out of the build output directory, and not directly, then this file is more like a template, and so we should rename it to something like _embedder.yaml.tmpl.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something is weird with my git checkout here - this file shouldn't hav ebeen modified.

import("//flutter/common/config.gni")
import("//third_party/dart/build/dart/dart_action.gni")

# Creates a dart kernel (dill) file suitalbe for use with gen_snapshot, as well
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: suitable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

"app/src/main/java/dev/flutter/scenarios/TextPlatformViewActivity.java",
"app/src/main/java/dev/flutter/scenarios/TextPlatformViewFactory.java",
"app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java",
"build.gradle",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you think about globbing under app/src?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GN does not like globs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(gradle will still build the files anyway, but GN won't be aware of changes to unmentioned ones dirtying the build)

# found in the LICENSE file.

"""
Invokes gradlew for building the scenario_app from GN/Ninja.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does gn have a way to run a target? If yes, is this wrapper script still needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GN knows how to run compiler binaries with some help, and it knows how to run python scripts.

This is actually really hacky - we shouldn't be invoking gradle from GN, but refactoring that will take more work and we're no worse off than we were before invoking gradle from a shell script.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it know how to run a bash script? If that's the case, then gradlew directly should work, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't work on Windows.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could use gradlew.bat on Windows

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which is all this python script is doing

cd "$SCRIPT_DIR/android"
GRADLE_USER_HOME="$PWD/android/gradle-home/.cache"
set -o pipefail && ./gradlew app:verifyDebugAndroidTestScreenshotTest --gradle-user-home "$GRADLE_USER_HOME"
set -o pipefail && ./gradlew app:verifyDebugAndroidTestScreenshotTest \
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it can be moved to gn too, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This actually runs unit tests. GN builds things, it doesn't run them.

@dnfield dnfield requested review from blasten and zanderso July 12, 2021 23:36
Copy link
Member

@zanderso zanderso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dnfield
Copy link
Contributor Author

dnfield commented Jul 13, 2021

@blasten @jmagman - I'm going to land this, happy to follow up if there are any outstanding issues/improvements wanted on Android/iOS

@dnfield dnfield merged commit bc2cf93 into flutter:master Jul 13, 2021
@dnfield
Copy link
Contributor Author

dnfield commented Jul 13, 2021

I also strongly suspect there are variants of this built on post not built in presubmits - I'll be watching to make sure this passes.

@dnfield dnfield deleted the scenario_pub branch July 13, 2021 16:12
@zanderso
Copy link
Member

@dnfield Please also keep an eye on the overall time on the builders. This should probably have little or no effect, but let's make sure.

zanderso added a commit that referenced this pull request Jul 13, 2021
zanderso added a commit that referenced this pull request Jul 13, 2021
dnfield added a commit to dnfield/engine that referenced this pull request Jul 13, 2021
dnfield added a commit that referenced this pull request Jul 13, 2021
* Revert "Revert "Build rules for scenario_app (#27302)" (#27358)"

This reverts commit 99f8791.

* Ignore *.*framework in copy_trees
@dnfield
Copy link
Contributor Author

dnfield commented Jul 13, 2021

Bots are taking slightly longer with an initial run on this - although it's hard to say why. For example, bot update took longer on this patch, but this patch has nothing to do with that step.

Is there some dashboard where I can see the timeframes of this stuff? @keyonghan might know - it's a little hard to track this through the LUCI Milo UI.

@zanderso
Copy link
Member

@dnfield Long Running Builders in the go/flutter-infra-metrics dashboard. You can play with the filters on the chart to select the builders and timeframe that you're interested in.

engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jul 13, 2021
moffatman pushed a commit to moffatman/engine that referenced this pull request Aug 5, 2021
moffatman pushed a commit to moffatman/engine that referenced this pull request Aug 5, 2021
moffatman pushed a commit to moffatman/engine that referenced this pull request Aug 5, 2021
* Revert "Revert "Build rules for scenario_app (flutter#27302)" (flutter#27358)"

This reverts commit 99f8791.

* Ignore *.*framework in copy_trees
naudzghebre pushed a commit to naudzghebre/engine that referenced this pull request Sep 2, 2021
naudzghebre pushed a commit to naudzghebre/engine that referenced this pull request Sep 2, 2021
naudzghebre pushed a commit to naudzghebre/engine that referenced this pull request Sep 2, 2021
* Revert "Revert "Build rules for scenario_app (flutter#27302)" (flutter#27358)"

This reverts commit 99f8791.

* Ignore *.*framework in copy_trees
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scenario App Unit Tests run with a previous engine build

4 participants