From 936d29774d9a6a71a246ce044f0817e4d33b43f4 Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Thu, 12 Oct 2023 20:20:41 -0700 Subject: [PATCH] Revert "Remove the frontend server wrapper (#46440)" This reverts commit f020067363903778090a2a121d16cf4d4ecb20b8. --- build/dart/rules.gni | 205 ++++++++--------------- common/config.gni | 19 +-- flutter_frontend_server/BUILD.gn | 25 +-- flutter_frontend_server/README.md | 71 ++++++++ flutter_frontend_server/bin/starter.dart | 15 ++ flutter_frontend_server/lib/server.dart | 91 ++++++++++ flutter_frontend_server/pubspec.yaml | 84 +++++++++- testing/dart/BUILD.gn | 10 +- testing/dart/compile_test.gni | 91 ++++++++++ testing/dart/observatory/BUILD.gn | 10 +- testing/smoke_test_failure/BUILD.gn | 10 +- testing/testing.gni | 96 +++++++++-- tools/gn | 12 +- 13 files changed, 538 insertions(+), 201 deletions(-) create mode 100644 flutter_frontend_server/README.md create mode 100644 flutter_frontend_server/bin/starter.dart create mode 100644 flutter_frontend_server/lib/server.dart create mode 100644 testing/dart/compile_test.gni diff --git a/build/dart/rules.gni b/build/dart/rules.gni index ba209f0b50b0b..00b801b2c204f 100644 --- a/build/dart/rules.gni +++ b/build/dart/rules.gni @@ -10,115 +10,21 @@ import("//flutter/common/config.gni") import("//third_party/dart/build/dart/dart_action.gni") import("//third_party/dart/sdk_args.gni") -# Generates a Dart kernel snapshot using flutter_frontend_server. -# -# Arguments -# main_dart (required): -# The Dart entrypoint file. -# -# kernel_output (required): -# The path to the output kernel snapshot in the out directory. -# -# package_config (optional): -# The path to the package_config.json file. -# -# deps (optional): -# Additional dependencies. Dependencies on the frontend server and -# Flutter's platform.dill are included by default. This rule creates and -# uses a depfile, so listing all Dart sources is not necessary. -# -# extra_args (optional): -# Additional frontend server command line arguments. -template("flutter_frontend_server") { - assert(defined(invoker.main_dart), "The Dart test file must be specified.") - assert(defined(invoker.kernel_output), - "The Dart Kernel file location must be specified.") - - kernel_output = invoker.kernel_output - - common_deps = [ - "//flutter/flutter_frontend_server:frontend_server", - "//flutter/lib/snapshot:strong_platform", - ] - if (defined(invoker.deps)) { - common_deps += invoker.deps - } - - extra_args = [] - if (defined(invoker.extra_args)) { - extra_args += invoker.extra_args - } - - packages_args = [] - if (defined(invoker.package_config)) { - packages_args += [ - "--packages", - rebase_path(invoker.package_config), - ] - } - - snapshot_depfile = "$kernel_output.d" - - common_vm_args = [ "--disable-dart-dev" ] - - flutter_patched_sdk = rebase_path("$root_out_dir/flutter_patched_sdk") - - common_args = extra_args + packages_args + [ - "--sdk-root", - flutter_patched_sdk, - "--target=flutter", - "--depfile", - rebase_path(snapshot_depfile), - "--output-dill", - rebase_path(invoker.kernel_output), - rebase_path(invoker.main_dart), - ] - - if (flutter_prebuilt_dart_sdk) { - action(target_name) { - forward_variables_from(invoker, - [ - "visibility", - "testonly", - ], - [ "pool" ]) - deps = common_deps - pool = "//flutter/build/dart:dart_pool" - script = "//build/gn_run_binary.py" - inputs = [ invoker.main_dart ] - outputs = [ invoker.kernel_output ] - depfile = snapshot_depfile - - ext = "" - if (is_win) { - ext = ".exe" - } - dart = rebase_path("$host_prebuilt_dart_sdk/bin/dart$ext", root_out_dir) - frontend_server = - rebase_path("$root_gen_dir/frontend_server.dart.snapshot") - - args = [ dart ] + common_vm_args + [ frontend_server ] + common_args - } - } else { - dart_action(target_name) { - forward_variables_from(invoker, - [ - "visibility", - "testonly", - ], - [ "pool" ]) - deps = common_deps - pool = "//flutter/build/dart:dart_pool" - script = "$root_gen_dir/frontend_server.dart.snapshot" - packages = rebase_path(invoker.package_config) - inputs = [ invoker.main_dart ] - outputs = [ invoker.kernel_output ] - depfile = snapshot_depfile - vm_args = common_vm_args - args = common_args - } - } -} +frontend_server_files = + exec_script("//third_party/dart/tools/list_dart_files.py", + [ + "absolute", + rebase_path("//flutter/flutter_frontend_server"), + ], + "list lines") + +frontend_server_files += + exec_script("//third_party/dart/tools/list_dart_files.py", + [ + "absolute", + rebase_path("//third_party/dart/pkg"), + ], + "list lines") # Creates a dart kernel (dill) file suitable for use with gen_snapshot, as well # as the app-jit, aot-elf, or aot-assembly snapshot for targeting Flutter on @@ -142,38 +48,61 @@ template("flutter_snapshot") { kernel_output = "$target_gen_dir/kernel_blob.bin" - extra_frontend_server_args = [] - if (is_aot) { - extra_frontend_server_args += [ - "--aot", - "--tfa", + prebuilt_dart_action(kernel_target) { + script = "//flutter/flutter_frontend_server/bin/starter.dart" + + main_dart = rebase_path(invoker.main_dart) + package_config = rebase_path(invoker.package_config) + flutter_patched_sdk = rebase_path("$root_out_dir/flutter_patched_sdk") + + deps = [ "//flutter/lib/snapshot:strong_platform" ] + + inputs = [ + main_dart, + package_config, + ] + frontend_server_files + + outputs = [ kernel_output ] + + depfile = "$kernel_output.d" + abs_depfile = rebase_path(depfile) + vm_args = [ "--disable-dart-dev" ] + + args = [ + "--depfile=$abs_depfile", + "--packages=" + rebase_path(package_config), + "--target=flutter", + "--sdk-root=" + flutter_patched_sdk, + "--output-dill=" + rebase_path(kernel_output, root_build_dir), ] - } else { - # --no-link-platform is only valid when --aot isn't specified - extra_frontend_server_args += [ "--no-link-platform" ] - } - if (defined(invoker.product) && invoker.product) { - # Setting this flag in a non-product release build for AOT (a "profile" - # build) causes the vm service isolate code to be tree-shaken from an app. - # See the pragma on the entrypoint here: - # - # https://github.com/dart-lang/sdk/blob/main/sdk/lib/_internal/vm/bin/vmservice_io.dart#L240 - # - # Also, this define excludes debugging and profiling code from Flutter. - extra_frontend_server_args += [ "-Ddart.vm.product=true" ] - } else { - if (flutter_runtime_mode == "profile") { - # The following define excludes debugging code from Flutter. - extra_frontend_server_args += [ "-Ddart.vm.profile=true" ] + if (is_aot) { + args += [ + "--aot", + "--tfa", + ] + } else { + # --no-link-platform is only valid when --aot isn't specified + args += [ "--no-link-platform" ] + } + + if (defined(invoker.product) && invoker.product) { + # Setting this flag in a non-product release build for AOT (a "profile" + # build) causes the vm service isolate code to be tree-shaken from an app. + # See the pragma on the entrypoint here: + # + # https://github.com/dart-lang/sdk/blob/main/sdk/lib/_internal/vm/bin/vmservice_io.dart#L240 + # + # Also, this define excludes debugging and profiling code from Flutter. + args += [ "-Ddart.vm.product=true" ] + } else { + if (flutter_runtime_mode == "profile") { + # The following define excludes debugging code from Flutter. + args += [ "-Ddart.vm.profile=true" ] + } } - } - flutter_frontend_server(kernel_target) { - main_dart = invoker.main_dart - package_config = invoker.package_config - kernel_output = kernel_output - extra_args = extra_frontend_server_args + args += [ rebase_path(main_dart) ] } compiled_action(snapshot_target) { @@ -342,7 +271,7 @@ template("application_snapshot") { # Ensure the compiled appliation (e.g. frontend-server, ...) will use this # Dart SDK hash when consuming/producing kernel. # - # (Instead of ensuring every user of the "application_snapshot" passes its + # (Instead of ensuring every user of the "application_snapshot" passes it's # own) snapshot_vm_args += [ "-Dsdk_hash=$sdk_hash" ] diff --git a/common/config.gni b/common/config.gni index 41439fed9dc82..56035f10a3961 100644 --- a/common/config.gni +++ b/common/config.gni @@ -113,27 +113,18 @@ if (flutter_prebuilt_dart_sdk) { _host_os_name = "windows" } - # When building 32-bit Android development artifacts for Windows host (like - # gen_snapshot), the host_cpu is set to x86. However, the correct prebuilt - # Dart SDK to use during this build is still the 64-bit one. - _host_cpu = host_cpu - if (host_os == "win" && host_cpu == "x86") { - _host_cpu = "x64" - } - _target_prebuilt_dart_sdk_config = "$_target_os_name-$target_cpu" - _host_prebuilt_dart_sdk_config = "$_host_os_name-$_host_cpu" + _host_prebuilt_dart_sdk_config = "$_host_os_name-$host_cpu" target_prebuilt_dart_sdk = "//flutter/prebuilts/$_target_prebuilt_dart_sdk_config/dart-sdk" host_prebuilt_dart_sdk = "//flutter/prebuilts/$_host_prebuilt_dart_sdk_config/dart-sdk" - # There is no prebuilt Dart SDK targeting Fuchsia, iOS, and Android, but we - # also don't need one, so even when the build is targeting one of these - # platforms, we use the prebuilt Dart SDK for the host. - if (current_toolchain == host_toolchain || target_os == "android" || - target_os == "fuchsia" || target_os == "ios" || target_os == "wasm") { + # There is no prebuilt Dart SDK targeting Fuchsia, but we also don't need + # one, so even when the build is targeting Fuchsia, use the prebuilt + # Dart SDK for the host. + if (current_toolchain == host_toolchain || is_fuchsia || is_wasm) { prebuilt_dart_sdk = host_prebuilt_dart_sdk prebuilt_dart_sdk_config = _host_prebuilt_dart_sdk_config } else { diff --git a/flutter_frontend_server/BUILD.gn b/flutter_frontend_server/BUILD.gn index e389148ba36da..9e986066595ab 100644 --- a/flutter_frontend_server/BUILD.gn +++ b/flutter_frontend_server/BUILD.gn @@ -2,18 +2,19 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//flutter/common/config.gni") +import("//flutter/build/dart/rules.gni") -copy("frontend_server") { - if (flutter_prebuilt_dart_sdk) { - snapshot = - "$host_prebuilt_dart_sdk/bin/snapshots/frontend_server.dart.snapshot" - } else { - deps = [ "//flutter/build/dart:dart_sdk" ] - snapshot = - "$root_out_dir/dart-sdk/bin/snapshots/frontend_server.dart.snapshot" - } +application_snapshot("frontend_server") { + main_dart = "bin/starter.dart" + deps = [ "//flutter/lib/snapshot:kernel_platform_files" ] - sources = [ snapshot ] - outputs = [ "$root_gen_dir/frontend_server.dart.snapshot" ] + package_config = rebase_path(".dart_tool/package_config.json") + flutter_patched_sdk = rebase_path("$root_out_dir/flutter_patched_sdk") + training_args = [ + "--train", + "--sdk-root=$flutter_patched_sdk", + rebase_path(main_dart), + ] + + inputs = frontend_server_files } diff --git a/flutter_frontend_server/README.md b/flutter_frontend_server/README.md new file mode 100644 index 0000000000000..3007831b924c6 --- /dev/null +++ b/flutter_frontend_server/README.md @@ -0,0 +1,71 @@ +# Frontend Server + +Frontend server is simple wrapper around Dart Frontend. It is a Dart application +that compiles Dart source into Dart Kernel binary (.dill-file). +Documentation on Dart Kernel (semantic, binary format, etc) can be found here: +https://github.com/dart-lang/sdk/wiki/Kernel-Documentation. + +Frontend server runs in two modes: + - immediate mode, where Dart source file name is provided as command line + argument; + - interactive mode, where communication is happening over stdin/stdout. + +## Interactive mode instructions + +### Compile/Recompile +``` +compile +``` + Compiles Dart source file with Dart Frontend. Replies with `result` response. + +``` +recompile + + +... + +``` + Incrementally recompiles Dart program previously compiled in current session, taking into account + changes in the listed files. Replies with `result` response. + + Relative paths should be relative to current working directory for the shell that launched + Frontend Server. + +### Accept/Reject +``` +accept +``` + Accepts results of incremental compilation, so that on next recompilation request Dart Frontend + will not include these recompiled files. +``` +reject +``` + Rejects results of incremental compilation, so that on next recompilation request Dart Frontend + will include compilation results from previously rejected recompilation in addition to what it + will recompile based on newly changed files. + Small technical detail is that Dart Frontend will not recompile files from previously rejected + recompilation attempts (unless they were changed since then), it will just include appropriate + kernel binaries it kept around from those previously rejected compilation requests. + + One use of `accept` and `reject` instructions is in the context of Dart VM hot-reload. Dart VM can + reject user-provided incremental change to what is currently running. It could happen for variety + of Dart VM internal reasons. For example, if incremental update changes some `class` to `enum`, + such update can not be hot-reloaded by VM at this point, will be rejected. + +### Quit +``` +quit +``` + Stops the server. + +## Response from the server + +``` +result + + [] +``` +Response from the Dart Frontend compiler is bracketed by `` tags. If the compiler +was able to produce a Dart Kernel file, the name of this file `` is provided too. +If the compiler encountered unrecoverable errors, there will be no output file name provided. + diff --git a/flutter_frontend_server/bin/starter.dart b/flutter_frontend_server/bin/starter.dart new file mode 100644 index 0000000000000..e839087dd5d04 --- /dev/null +++ b/flutter_frontend_server/bin/starter.dart @@ -0,0 +1,15 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +import 'dart:io'; + +import 'package:flutter_frontend_server/server.dart'; + +Future main(List args) async { + final int exitCode = await starter(args); + if (exitCode != 0) { + exit(exitCode); + } +} diff --git a/flutter_frontend_server/lib/server.dart b/flutter_frontend_server/lib/server.dart new file mode 100644 index 0000000000000..8733c5b7a9070 --- /dev/null +++ b/flutter_frontend_server/lib/server.dart @@ -0,0 +1,91 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: avoid_print + + +import 'dart:async'; +import 'dart:io' hide FileSystemEntity; + +import 'package:args/args.dart'; +import 'package:frontend_server/frontend_server.dart' as frontend + show + CompilerInterface, + FrontendCompiler, + argParser, + listenAndCompile, + usage; +import 'package:path/path.dart' as path; + +/// Entry point for this module, that creates `FrontendCompiler` instance and +/// processes user input. +/// `compiler` is an optional parameter so it can be replaced with mocked +/// version for testing. +Future starter( + List args, { + frontend.CompilerInterface? compiler, + Stream>? input, + StringSink? output, +}) async { + ArgResults options; + try { + options = frontend.argParser.parse(args); + } catch (error) { + print('ERROR: $error\n'); + print(frontend.usage); + return 1; + } + + if (options['train'] as bool) { + if (!options.rest.isNotEmpty) { + throw Exception('Must specify input.dart'); + } + + final String input = options.rest[0]; + final String sdkRoot = options['sdk-root'] as String; + final Directory temp = + Directory.systemTemp.createTempSync('train_frontend_server'); + try { + for (int i = 0; i < 3; i++) { + final String outputTrainingDill = path.join(temp.path, 'app.dill'); + options = frontend.argParser.parse([ + '--incremental', + '--sdk-root=$sdkRoot', + '--output-dill=$outputTrainingDill', + '--target=flutter', + '--track-widget-creation', + '--enable-asserts', + ]); + compiler ??= frontend.FrontendCompiler(output); + + await compiler.compile(input, options); + compiler.acceptLastDelta(); + await compiler.recompileDelta(); + compiler.acceptLastDelta(); + compiler.resetIncrementalCompiler(); + await compiler.recompileDelta(); + compiler.acceptLastDelta(); + await compiler.recompileDelta(); + compiler.acceptLastDelta(); + } + return 0; + } finally { + temp.deleteSync(recursive: true); + } + } + + compiler ??= frontend.FrontendCompiler(output, + useDebuggerModuleNames: options['debugger-module-names'] as bool, + emitDebugMetadata: options['experimental-emit-debug-metadata'] as bool, + unsafePackageSerialization: + options['unsafe-package-serialization'] as bool); + + if (options.rest.isNotEmpty) { + return await compiler.compile(options.rest[0], options) ? 0 : 254; + } + + final Completer completer = Completer(); + frontend.listenAndCompile(compiler, input ?? stdin, options, completer); + return completer.future; +} diff --git a/flutter_frontend_server/pubspec.yaml b/flutter_frontend_server/pubspec.yaml index 16fd3ad7ee566..2f0d37c5583b7 100644 --- a/flutter_frontend_server/pubspec.yaml +++ b/flutter_frontend_server/pubspec.yaml @@ -20,20 +20,102 @@ homepage: https://flutter.dev environment: sdk: '>=3.2.0-0 <4.0.0' +dependencies: + args: any + frontend_server: any + path: any + dev_dependencies: litetest: any - path: any dependency_overrides: + _fe_analyzer_shared: + path: ../../third_party/dart/pkg/_fe_analyzer_shared + _js_interop_checks: + path: ../../third_party/dart/pkg/_js_interop_checks + args: + path: ../../third_party/dart/third_party/pkg/args + async: + path: ../../third_party/dart/third_party/pkg/async async_helper: path: ../../third_party/dart/pkg/async_helper + bazel_worker: + path: ../../third_party/dart/third_party/pkg/bazel_worker + build_integration: + path: ../../third_party/dart/pkg/build_integration + collection: + path: ../../third_party/dart/third_party/pkg/collection + compiler: + path: ../../third_party/dart/pkg/compiler + crypto: + path: ../../third_party/dart/third_party/pkg/crypto + dart_internal: + path: ../../third_party/dart/pkg/dart_internal + dart2js_info: + path: ../../third_party/dart/pkg/dart2js_info + dart2wasm: + path: ../../third_party/dart/pkg/dart2wasm + dev_compiler: + path: ../../third_party/dart/pkg/dev_compiler expect: path: ../../third_party/dart/pkg/expect + ffi: + path: ../../third_party/dart/third_party/pkg/ffi + fixnum: + path: ../../third_party/dart/third_party/pkg/fixnum + front_end: + path: ../../third_party/dart/pkg/front_end + frontend_server: + path: ../../third_party/dart/pkg/frontend_server + http_parser: + path: ../../third_party/dart/third_party/pkg/http_parser + js_ast: + path: ../../third_party/dart/pkg/js_ast + js_runtime: + path: ../../third_party/dart/pkg/js_runtime + js_shared: + path: ../../third_party/dart/pkg/js_shared + kernel: + path: ../../third_party/dart/pkg/kernel litetest: path: ../testing/litetest meta: path: ../../third_party/dart/pkg/meta + mmap: + path: ../../third_party/dart/pkg/mmap + package_config: + path: ../../third_party/dart/third_party/pkg/package_config path: path: ../../third_party/dart/third_party/pkg/path + protobuf: + path: ../../third_party/dart/third_party/pkg/protobuf/protobuf + shelf: + path: ../../third_party/dart/third_party/pkg/shelf/pkgs/shelf smith: path: ../../third_party/dart/pkg/smith + source_maps: + path: ../../third_party/dart/third_party/pkg/source_maps + source_span: + path: ../../third_party/dart/third_party/pkg/source_span + stack_trace: + path: ../../third_party/dart/third_party/pkg/stack_trace + stream_channel: + path: ../../third_party/dart/third_party/pkg/stream_channel + string_scanner: + path: ../../third_party/dart/third_party/pkg/string_scanner + term_glyph: + path: ../../third_party/dart/third_party/pkg/term_glyph + typed_data: + path: ../../third_party/dart/third_party/pkg/typed_data + usage: + path: ../../third_party/dart/third_party/pkg/usage + vm: + path: ../../third_party/dart/pkg/vm + vm_service: + path: ../../third_party/dart/pkg/vm_service + vm_snapshot_analysis: + path: ../../third_party/dart/pkg/vm_snapshot_analysis + wasm_builder: + path: ../../third_party/dart/pkg/wasm_builder + yaml: + path: ../../third_party/dart/third_party/pkg/yaml diff --git a/testing/dart/BUILD.gn b/testing/dart/BUILD.gn index d9bd962168333..2e1bb1ad38f67 100644 --- a/testing/dart/BUILD.gn +++ b/testing/dart/BUILD.gn @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//flutter/build/dart/rules.gni") +import("//flutter/testing/dart/compile_test.gni") tests = [ "assets_test.dart", @@ -48,10 +48,10 @@ tests = [ ] foreach(test, tests) { - flutter_frontend_server("compile_$test") { - main_dart = test - kernel_output = "$root_gen_dir/$test.dill" - package_config = ".dart_tool/package_config.json" + compile_flutter_dart_test("compile_$test") { + dart_file = test + dart_kernel = "$root_gen_dir/$test.dill" + packages = ".dart_tool/package_config.json" } } diff --git a/testing/dart/compile_test.gni b/testing/dart/compile_test.gni new file mode 100644 index 0000000000000..fbdf76ea849da --- /dev/null +++ b/testing/dart/compile_test.gni @@ -0,0 +1,91 @@ +# Copyright 2013 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/compiled_action.gni") +import("//flutter/common/config.gni") +import("//third_party/dart/build/dart/dart_action.gni") +import("//third_party/dart/sdk_args.gni") + +import("//third_party/dart/build/dart/dart_action.gni") + +# Generates a Dart kernel snapshot using flutter_frontend_server. +# +# Arguments +# dart_main (required): The Main Dart file. +# +# dart_kernel (required): The path to the output kernel snapshot in the out +# directory. +# +# packages (required): The path to the .packages file. +template("compile_flutter_dart_test") { + assert(defined(invoker.dart_file), "The Dart test file must be specified.") + assert(defined(invoker.dart_kernel), + "The Dart Kernel file location must be specified.") + assert(defined(invoker.packages), + "The path to the .packages file must be specified.") + + common_deps = [ + "//flutter/flutter_frontend_server:frontend_server", + "//flutter/lib/snapshot:strong_platform", + ] + if (defined(invoker.deps)) { + common_deps += invoker.deps + } + + snapshot_depfile = + "$root_gen_dir/flutter/testing/snapshot_$target_name.depfile.d" + + common_vm_args = [ "--disable-dart-dev" ] + + flutter_patched_sdk = rebase_path("$root_out_dir/flutter_patched_sdk") + + common_args = [ + "--sound-null-safety", + "--sdk-root", + flutter_patched_sdk, + "--target=flutter", + "--packages", + rebase_path(invoker.packages), + "--depfile", + rebase_path(snapshot_depfile), + "--output-dill", + rebase_path(invoker.dart_kernel, root_out_dir), + rebase_path(invoker.dart_file), + ] + + if (flutter_prebuilt_dart_sdk) { + action(target_name) { + testonly = true + deps = common_deps + pool = "//flutter/build/dart:dart_pool" + script = "//build/gn_run_binary.py" + inputs = [ invoker.dart_file ] + outputs = [ invoker.dart_kernel ] + depfile = snapshot_depfile + + ext = "" + if (is_win) { + ext = ".exe" + } + dart = rebase_path("$host_prebuilt_dart_sdk/bin/dart$ext", root_out_dir) + frontend_server = + rebase_path("$root_gen_dir/frontend_server.dart.snapshot") + + args = [ dart ] + common_vm_args + [ frontend_server ] + common_args + } + } else { + dart_action(target_name) { + testonly = true + deps = common_deps + pool = "//flutter/build/dart:dart_pool" + script = "$root_gen_dir/frontend_server.dart.snapshot" + packages = rebase_path(invoker.packages) + inputs = [ invoker.dart_file ] + outputs = [ invoker.dart_kernel ] + depfile = snapshot_depfile + vm_args = common_vm_args + args = common_args + } + } +} diff --git a/testing/dart/observatory/BUILD.gn b/testing/dart/observatory/BUILD.gn index 35c573a85a4db..a0e6afbe6be17 100644 --- a/testing/dart/observatory/BUILD.gn +++ b/testing/dart/observatory/BUILD.gn @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//flutter/build/dart/rules.gni") +import("//flutter/testing/dart/compile_test.gni") tests = [ "skp_test.dart", @@ -12,10 +12,10 @@ tests = [ ] foreach(test, tests) { - flutter_frontend_server("compile_$test") { - main_dart = test - kernel_output = "$root_gen_dir/$test.dill" - package_config = "../.dart_tool/package_config.json" + compile_flutter_dart_test("compile_$test") { + dart_file = test + dart_kernel = "$root_gen_dir/$test.dill" + packages = "../.dart_tool/package_config.json" } } diff --git a/testing/smoke_test_failure/BUILD.gn b/testing/smoke_test_failure/BUILD.gn index 1ce144ecc523a..8110ea199fa16 100644 --- a/testing/smoke_test_failure/BUILD.gn +++ b/testing/smoke_test_failure/BUILD.gn @@ -2,15 +2,15 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//flutter/build/dart/rules.gni") +import("//flutter/testing/dart/compile_test.gni") tests = [ "fail_test.dart" ] foreach(test, tests) { - flutter_frontend_server("compile_$test") { - main_dart = test - kernel_output = "$root_gen_dir/$test.dill" - package_config = ".dart_tool/package_config.json" + compile_flutter_dart_test("compile_$test") { + dart_file = test + dart_kernel = "$root_gen_dir/$test.dill" + packages = ".dart_tool/package_config.json" } } diff --git a/testing/testing.gni b/testing/testing.gni index cf59753e51dc7..7059bc15f017b 100644 --- a/testing/testing.gni +++ b/testing/testing.gni @@ -3,8 +3,9 @@ # found in the LICENSE file. import("//build/compiled_action.gni") -import("//flutter/build/dart/rules.gni") import("//flutter/common/config.gni") +import("//third_party/dart/build/dart/dart_action.gni") +import("//third_party/dart/sdk_args.gni") is_aot_test = flutter_runtime_mode == "profile" || flutter_runtime_mode == "release" @@ -50,6 +51,48 @@ template("fixtures_location") { } } +# Invokes the frontend server using the built Dart SDK or the prebuilt Dart SDK +# as appropriate. +# +# Parameters: +# The parameters testonly, deps, inputs, outputs, depfile, and args are +# forwarded from the invoker either to an 'action' target or a 'dart_action' +# target depending on whether a prebuilt Dart SDK is used or not, +# respectively. +template("_frontend_server") { + if (flutter_prebuilt_dart_sdk) { + action(target_name) { + testonly = invoker.testonly + deps = invoker.deps + script = "//build/gn_run_binary.py" + inputs = invoker.inputs + outputs = invoker.outputs + depfile = invoker.depfile + pool = "//flutter/build/dart:dart_pool" + + ext = "" + if (is_win) { + ext = ".exe" + } + dart = rebase_path("$host_prebuilt_dart_sdk/bin/dart$ext", root_out_dir) + frontend_server = rebase_path( + "$host_prebuilt_dart_sdk/bin/snapshots/frontend_server.dart.snapshot") + + args = [ + dart, + frontend_server, + ] + invoker.args + } + } else { + dart_action(target_name) { + forward_variables_from(invoker, "*") + deps += [ "//third_party/dart/utils/kernel-service:frontend_server" ] + script = "$root_out_dir/frontend_server.dart.snapshot" + pool = "//flutter/build/dart:dart_pool" + } + } +} + # Generates the Dart kernel snapshot. # # Arguments @@ -64,26 +107,45 @@ template("dart_snapshot_kernel") { assert(defined(invoker.dart_kernel), "The Dart Kernel file location must be specified") - args = [] - if (flutter_runtime_mode == "release" || - flutter_runtime_mode == "jit_release") { - args += [ "-Ddart.vm.product=true" ] - } + _frontend_server(target_name) { + testonly = true - if (is_aot_test) { - args += [ - "--aot", + deps = [ "//flutter/lib/snapshot:strong_platform" ] - # type flow analysis - "--tfa", + inputs = [ invoker.dart_main ] + + outputs = [ invoker.dart_kernel ] + + snapshot_depfile = "$target_gen_dir/snapshot_$target_name.depfile.d" + depfile = snapshot_depfile + + args = [ + "--sdk-root", + rebase_path("$root_out_dir/flutter_patched_sdk"), + "--target", + "flutter", + "--sound-null-safety", + "--output-dill", + rebase_path(invoker.dart_kernel, root_out_dir), + "--depfile", + rebase_path(snapshot_depfile), ] - } - flutter_frontend_server(target_name) { - testonly = true - main_dart = invoker.dart_main - kernel_output = invoker.dart_kernel - extra_args = args + if (flutter_runtime_mode == "release" || + flutter_runtime_mode == "jit_release") { + args += [ "-Ddart.vm.product=true" ] + } + + if (is_aot_test) { + args += [ + "--aot", + + # type flow analysis + "--tfa", + ] + } + + args += [ rebase_path(invoker.dart_main) ] } } diff --git a/tools/gn b/tools/gn index 4eed7044d185f..196219d35d611 100755 --- a/tools/gn +++ b/tools/gn @@ -106,12 +106,16 @@ def is_host_build(args): # Determines whether a prebuilt Dart SDK can be used instead of building one. +# We can use a prebuilt Dart SDK when: +# 1. It is a host build, a build targeting Fuchsia, or a build targeting desktop. +# 2. The prebuilt SDK exists under //flutter/prebuilts/$OS-$ARCH. def can_use_prebuilt_dart(args): prebuilt = None - # When doing a 'host' build (args.target_os is None), or a build when the - # target OS and host OS are different, the prebuilt Dart SDK is the Dart SDK - # for the host system's OS and archetecture. - if args.target_os is None or args.target_os in ['android', 'ios', 'fuchsia']: + # In a Fuchsia build, we can use a prebuilt Dart SDK for the host to build + # platform agnostic artifacts (e.g. kernel snapshots), and a Dart SDK + # targeting Fuchsia is not needed. So, it is safe to say that the prebuilt + # Dart SDK in a Fuchsia build is the host prebuilt Dart SDK. + if args.target_os is None or args.target_os == 'fuchsia': if sys.platform.startswith(('cygwin', 'win')): prebuilt = 'windows-x64' elif sys.platform == 'darwin':