From f6ca98bf99c1fdc3448a0188fa4875ca44a352ca Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Thu, 18 Apr 2024 17:33:16 -0700 Subject: [PATCH 1/4] Add dart_executable gn rule Adds a dart_executable rule that compiles Dart code to an ELF, Mach-O, or PE binary. Can be used to build tools written in Dart, or Dart unit tests. Issue: https://github.com/flutter/flutter/issues/147013 --- BUILD.gn | 1 + build/dart/rules.gni | 98 ++++++++++++++++++++++++++++++++++++++ tools/engine_tool/BUILD.gn | 88 ++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 tools/engine_tool/BUILD.gn diff --git a/BUILD.gn b/BUILD.gn index ac8d81872d19a..80473d5471d1e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -131,6 +131,7 @@ group("flutter") { public_deps += [ "//flutter/shell/testing", "//flutter/tools/const_finder", + "//flutter/tools/engine_tool", "//flutter/tools/font_subset", ] } diff --git a/build/dart/rules.gni b/build/dart/rules.gni index 753ac4f14e308..2bd70ccf4f90c 100644 --- a/build/dart/rules.gni +++ b/build/dart/rules.gni @@ -409,3 +409,101 @@ template("application_snapshot") { } } } + +# Generates a Dart executable using `dart compile exe` +# +# Arguments +# main_dart (required): +# The Dart entrypoint file. +# +# package_config (required): +# The packages.json file for the app. +# +# output (optional): +# The output executable name. By default, the target name. On Windows, an +# 'exe' is automatically appended. +# +# 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. +template("dart_executable") { + assert(defined(invoker.main_dart), "Must specify 'main_dart'") + + main_dart = invoker.main_dart + + package_config = rebase_path(".dart_tool/package_config.json") + if (defined(invoker.package_config)) { + package_config = rebase_path(invoker.package_config) + } + name = target_name + + extra_deps = [] + if (defined(invoker.deps)) { + extra_deps += invoker.deps + } + + extra_inputs = [ main_dart ] + if (defined(invoker.inputs)) { + extra_inputs += invoker.inputs + } + extra_inputs += [ package_config ] + + ext = "" + if (is_win) { + ext = ".exe" + } + output = "$target_gen_dir/$name$ext" + if (defined(invoker.output)) { + output = invoker.output + } + + exe_vm_args = [ "--deterministic" ] + if (defined(invoker.vm_args)) { + exe_vm_args += invoker.vm_args + } + + abs_output = rebase_path(output) + exe_vm_args += [ + "compile", + "exe", + "--packages=$package_config", + "--output=$abs_output", + ] + + if (flutter_prebuilt_dart_sdk) { + action(target_name) { + forward_variables_from(invoker, + [ + "testonly", + "visibility", + ]) + deps = extra_deps + script = "//build/gn_run_binary.py" + inputs = extra_inputs + outputs = [ output ] + pool = "//flutter/build/dart:dart_pool" + + dart = rebase_path("$host_prebuilt_dart_sdk/bin/dart$ext", root_build_dir) + + args = [ dart ] + args += exe_vm_args + args += [ rebase_path(main_dart) ] + } + } else { + dart_action(target_name) { + forward_variables_from(invoker, + [ + "testonly", + "visibility", + ]) + script = main_dart + pool = "//flutter/build/dart:dart_pool" + deps = extra_deps + inputs = extra_inputs + outputs = [ output ] + vm_args = exe_vm_args + args = [] + } + } +} diff --git a/tools/engine_tool/BUILD.gn b/tools/engine_tool/BUILD.gn new file mode 100644 index 0000000000000..92998715dec6a --- /dev/null +++ b/tools/engine_tool/BUILD.gn @@ -0,0 +1,88 @@ +# 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("//flutter/build/dart/rules.gni") + +dart_executable("engine_tool") { + main_dart = "bin/et.dart" + output = "$root_out_dir/et" +} + +group("tests") { + testonly = true + public_deps = [ + ":build_command_test", + ":entry_point_test", + ":fetch_command_test", + ":format_command_test", + ":gn_utils_test", + ":lint_command_test", + ":logger_test", + ":proc_utils_test", + ":query_command_test", + ":run_command_test", + ":test_command_test", + ":worker_pool_test", + ] +} + +dart_executable("build_command_test") { + testonly = true + main_dart = "test/build_command_test.dart" +} + +dart_executable("entry_point_test") { + testonly = true + main_dart = "test/entry_point_test.dart" +} + +dart_executable("fetch_command_test") { + testonly = true + main_dart = "test/fetch_command_test.dart" +} + +dart_executable("format_command_test") { + testonly = true + main_dart = "test/format_command_test.dart" +} + +dart_executable("gn_utils_test") { + testonly = true + main_dart = "test/gn_utils_test.dart" +} + +dart_executable("lint_command_test") { + testonly = true + main_dart = "test/lint_command_test.dart" +} + +dart_executable("logger_test") { + testonly = true + main_dart = "test/logger_test.dart" +} + +dart_executable("proc_utils_test") { + testonly = true + main_dart = "test/proc_utils_test.dart" +} + +dart_executable("query_command_test") { + testonly = true + main_dart = "test/query_command_test.dart" +} + +dart_executable("run_command_test") { + testonly = true + main_dart = "test/run_command_test.dart" +} + +dart_executable("test_command_test") { + testonly = true + main_dart = "test/test_command_test.dart" +} + +dart_executable("worker_pool_test") { + testonly = true + main_dart = "test/worker_pool_test.dart" +} From df33a5543a49385105dba58b75ba8b1699a38304 Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Thu, 18 Apr 2024 22:32:01 -0700 Subject: [PATCH 2/4] Add action_type = dart_executable metadata --- build/dart/rules.gni | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build/dart/rules.gni b/build/dart/rules.gni index 2bd70ccf4f90c..f9e41673a8991 100644 --- a/build/dart/rules.gni +++ b/build/dart/rules.gni @@ -489,6 +489,9 @@ template("dart_executable") { args = [ dart ] args += exe_vm_args args += [ rebase_path(main_dart) ] + metadata = { + action_type = [ "dart_executable" ] + } } } else { dart_action(target_name) { @@ -504,6 +507,9 @@ template("dart_executable") { outputs = [ output ] vm_args = exe_vm_args args = [] + metadata = { + action_type = [ "dart_executable" ] + } } } } From f25a33f348614346d9920c00cfecd1da50ab1c5d Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Fri, 19 Apr 2024 19:31:31 -0700 Subject: [PATCH 3/4] Make package_config optional --- build/dart/rules.gni | 30 ++++++++++++++++++++---------- tools/engine_tool/BUILD.gn | 12 ++++++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/build/dart/rules.gni b/build/dart/rules.gni index f9e41673a8991..c58978333c01a 100644 --- a/build/dart/rules.gni +++ b/build/dart/rules.gni @@ -410,14 +410,24 @@ template("application_snapshot") { } } -# Generates a Dart executable using `dart compile exe` +# Generates an executable from Dart code using `dart compile exe`. +# +# This rule is primarily intended to be used to compile test targets for use +# by engine developers to build and run test code written in Dart in the engine +# repo, in particular via the `et` tool. It is NOT intended for use in +# generating production-ready user-facing binaries. +# +# See: //flutter/tools/engine_tool for more information on `et`. # # Arguments # main_dart (required): # The Dart entrypoint file. # -# package_config (required): -# The packages.json file for the app. +# package_config (optional): +# The packages.json file for the Dart package (if any). Required when +# building libraries that are part of packages with Dart dependencies. +# Not needed when building standalone Dart code that is not part of a +# package. # # output (optional): # The output executable name. By default, the target name. On Windows, an @@ -432,22 +442,20 @@ template("dart_executable") { main_dart = invoker.main_dart - package_config = rebase_path(".dart_tool/package_config.json") - if (defined(invoker.package_config)) { - package_config = rebase_path(invoker.package_config) - } name = target_name extra_deps = [] if (defined(invoker.deps)) { extra_deps += invoker.deps } - extra_inputs = [ main_dart ] if (defined(invoker.inputs)) { extra_inputs += invoker.inputs } - extra_inputs += [ package_config ] + if (defined(invoker.package_config)) { + package_config = rebase_path(invoker.package_config) + extra_inputs += [ package_config ] + } ext = "" if (is_win) { @@ -467,9 +475,11 @@ template("dart_executable") { exe_vm_args += [ "compile", "exe", - "--packages=$package_config", "--output=$abs_output", ] + if (defined(package_config)) { + exe_vm_args += [ "--packages=$package_config" ] + } if (flutter_prebuilt_dart_sdk) { action(target_name) { diff --git a/tools/engine_tool/BUILD.gn b/tools/engine_tool/BUILD.gn index 92998715dec6a..f4703a89ce67d 100644 --- a/tools/engine_tool/BUILD.gn +++ b/tools/engine_tool/BUILD.gn @@ -30,59 +30,71 @@ group("tests") { dart_executable("build_command_test") { testonly = true main_dart = "test/build_command_test.dart" + package_config = ".dart_tool/package_config.json" } dart_executable("entry_point_test") { testonly = true main_dart = "test/entry_point_test.dart" + package_config = ".dart_tool/package_config.json" } dart_executable("fetch_command_test") { testonly = true main_dart = "test/fetch_command_test.dart" + package_config = ".dart_tool/package_config.json" } dart_executable("format_command_test") { testonly = true main_dart = "test/format_command_test.dart" + package_config = ".dart_tool/package_config.json" } dart_executable("gn_utils_test") { testonly = true main_dart = "test/gn_utils_test.dart" + package_config = ".dart_tool/package_config.json" } dart_executable("lint_command_test") { testonly = true main_dart = "test/lint_command_test.dart" + package_config = ".dart_tool/package_config.json" } dart_executable("logger_test") { testonly = true main_dart = "test/logger_test.dart" + package_config = ".dart_tool/package_config.json" } dart_executable("proc_utils_test") { testonly = true main_dart = "test/proc_utils_test.dart" + package_config = ".dart_tool/package_config.json" } dart_executable("query_command_test") { testonly = true main_dart = "test/query_command_test.dart" + package_config = ".dart_tool/package_config.json" } dart_executable("run_command_test") { testonly = true main_dart = "test/run_command_test.dart" + package_config = ".dart_tool/package_config.json" } dart_executable("test_command_test") { testonly = true main_dart = "test/test_command_test.dart" + package_config = ".dart_tool/package_config.json" } dart_executable("worker_pool_test") { testonly = true main_dart = "test/worker_pool_test.dart" + package_config = ".dart_tool/package_config.json" } From 513dc77501faf2e5cb8fb45b51637f9313f39ffc Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Tue, 23 Apr 2024 10:58:10 -0700 Subject: [PATCH 4/4] root_build_dir-relative rebase --- build/dart/rules.gni | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dart/rules.gni b/build/dart/rules.gni index c58978333c01a..b6add28f55e94 100644 --- a/build/dart/rules.gni +++ b/build/dart/rules.gni @@ -453,7 +453,7 @@ template("dart_executable") { extra_inputs += invoker.inputs } if (defined(invoker.package_config)) { - package_config = rebase_path(invoker.package_config) + package_config = rebase_path(invoker.package_config, root_build_dir) extra_inputs += [ package_config ] } @@ -471,7 +471,7 @@ template("dart_executable") { exe_vm_args += invoker.vm_args } - abs_output = rebase_path(output) + abs_output = rebase_path(output, root_build_dir) exe_vm_args += [ "compile", "exe",