From 9c550c72224b5b849b951fd70cbc9365f3897db4 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 26 Sep 2024 12:53:13 -0700 Subject: [PATCH 1/5] Start adding command_executable(...) --- build/dart/internal/command_executable.gni | 50 ++++++++++++++++++++++ build/dart/internal/command_executable.py | 31 ++++++++++++++ build/dart/internal/tests/BUILD.gn | 9 ++++ 3 files changed, 90 insertions(+) create mode 100644 build/dart/internal/command_executable.gni create mode 100644 build/dart/internal/command_executable.py create mode 100644 build/dart/internal/tests/BUILD.gn diff --git a/build/dart/internal/command_executable.gni b/build/dart/internal/command_executable.gni new file mode 100644 index 0000000000000..aec140b267ce9 --- /dev/null +++ b/build/dart/internal/command_executable.gni @@ -0,0 +1,50 @@ +# 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. + +# Generates an executable that runs a static command and set of arguments. +# +# Parameters: +# command (required): +# The command to run, which is typically an absolute path to an executable. +# +# args (optional): +# Arguments to pass to the command. +# +# output (optional): +# Overrides the full output path. +template("command_executable") { + assert(defined(invoker.command), "Must specify 'command'") + + # The command to run. + command = invoker.command + + # The arguments to pass to the command + cmd_args = [] + if (defined(invoker.args)) { + cmd_args += invoker.args + } + + # The output path. + output = "$root_gen_dir/$target_name" + if (defined(invoker.output)) { + output = invoker.output + } + + # Concatenate the arguments. + flat_args = join(" ", cmd_args) + + # Run build_cmd.py to generate the file and make it executable. + action(target_name) { + script = "//flutter/build/dart/internal/command_executable.py" + outputs = [ output ] + args = [ + "--output", + output, + "--command", + command, + "--args", + flat_args, + ] + } +} diff --git a/build/dart/internal/command_executable.py b/build/dart/internal/command_executable.py new file mode 100644 index 0000000000000..47da4734da3a9 --- /dev/null +++ b/build/dart/internal/command_executable.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# 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. + +"""Generates a shell or batch script to run a command.""" + +import argparse + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--output', required=True, help='Output file') + parser.add_argument('--command', required=True, help='Command to run') + parser.add_argument('--args', required=True, help='Arguments to the command') + args = parser.parse_args() + + with open(args.output, 'w') as f: + f.write('#!/bin/sh\n') + f.write('set -e\n') + f.write('set -x\n') + f.write(args.command) + f.write(' ') + f.write(args.args) + f.write('\n') + + # Make the script executable. + os.chmod(args.output, 0o755) + +if __name__ == '__main__': + main() diff --git a/build/dart/internal/tests/BUILD.gn b/build/dart/internal/tests/BUILD.gn new file mode 100644 index 0000000000000..752c40bda62cf --- /dev/null +++ b/build/dart/internal/tests/BUILD.gn @@ -0,0 +1,9 @@ +# 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/internal/command_executable.gni") + +command_executable("tests") { + command = "dart" +} From f0d019dd2b70a643fc7dd809e790744d6a6e4d1e Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 26 Sep 2024 17:03:20 -0700 Subject: [PATCH 2/5] Generate a shell script. --- BUILD.gn | 3 + build/dart/internal/command_executable.gni | 50 ---------------- build/dart/internal/command_executable.py | 31 ---------- build/dart/internal/gen_dartcli_call.gni | 39 +++++++++++++ build/dart/internal/gen_executable_call.gni | 62 ++++++++++++++++++++ build/dart/internal/gen_executable_call.py | 64 +++++++++++++++++++++ build/dart/internal/tests/BUILD.gn | 9 --- build/dart/test/BUILD.gn | 27 +++++++++ tools/engine_tool/BUILD.gn | 15 +++++ 9 files changed, 210 insertions(+), 90 deletions(-) delete mode 100644 build/dart/internal/command_executable.gni delete mode 100644 build/dart/internal/command_executable.py create mode 100644 build/dart/internal/gen_dartcli_call.gni create mode 100644 build/dart/internal/gen_executable_call.gni create mode 100644 build/dart/internal/gen_executable_call.py delete mode 100644 build/dart/internal/tests/BUILD.gn create mode 100644 build/dart/test/BUILD.gn create mode 100644 tools/engine_tool/BUILD.gn diff --git a/BUILD.gn b/BUILD.gn index 6d096a5aaff53..c810a794d8601 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -129,8 +129,11 @@ group("flutter") { if (build_engine_artifacts) { public_deps += [ + "//flutter/build/dart/test:gen_dartcli_call", + "//flutter/build/dart/test:gen_executable_call", "//flutter/shell/testing", "//flutter/tools/const_finder", + "//flutter/tools/engine_tool:tests", "//flutter/tools/font_subset", ] } diff --git a/build/dart/internal/command_executable.gni b/build/dart/internal/command_executable.gni deleted file mode 100644 index aec140b267ce9..0000000000000 --- a/build/dart/internal/command_executable.gni +++ /dev/null @@ -1,50 +0,0 @@ -# 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. - -# Generates an executable that runs a static command and set of arguments. -# -# Parameters: -# command (required): -# The command to run, which is typically an absolute path to an executable. -# -# args (optional): -# Arguments to pass to the command. -# -# output (optional): -# Overrides the full output path. -template("command_executable") { - assert(defined(invoker.command), "Must specify 'command'") - - # The command to run. - command = invoker.command - - # The arguments to pass to the command - cmd_args = [] - if (defined(invoker.args)) { - cmd_args += invoker.args - } - - # The output path. - output = "$root_gen_dir/$target_name" - if (defined(invoker.output)) { - output = invoker.output - } - - # Concatenate the arguments. - flat_args = join(" ", cmd_args) - - # Run build_cmd.py to generate the file and make it executable. - action(target_name) { - script = "//flutter/build/dart/internal/command_executable.py" - outputs = [ output ] - args = [ - "--output", - output, - "--command", - command, - "--args", - flat_args, - ] - } -} diff --git a/build/dart/internal/command_executable.py b/build/dart/internal/command_executable.py deleted file mode 100644 index 47da4734da3a9..0000000000000 --- a/build/dart/internal/command_executable.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 -# -# 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. - -"""Generates a shell or batch script to run a command.""" - -import argparse - -def main(): - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument('--output', required=True, help='Output file') - parser.add_argument('--command', required=True, help='Command to run') - parser.add_argument('--args', required=True, help='Arguments to the command') - args = parser.parse_args() - - with open(args.output, 'w') as f: - f.write('#!/bin/sh\n') - f.write('set -e\n') - f.write('set -x\n') - f.write(args.command) - f.write(' ') - f.write(args.args) - f.write('\n') - - # Make the script executable. - os.chmod(args.output, 0o755) - -if __name__ == '__main__': - main() diff --git a/build/dart/internal/gen_dartcli_call.gni b/build/dart/internal/gen_dartcli_call.gni new file mode 100644 index 0000000000000..8687da00de887 --- /dev/null +++ b/build/dart/internal/gen_dartcli_call.gni @@ -0,0 +1,39 @@ +# 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/internal/gen_executable_call.gni") +import("//flutter/common/config.gni") + +# Generates an executable that runs `dart` with a command and set of arguments. +# +# Parameters: +# args (optional): +# Arguments to pass to the Dart CLI. +# +# cwd (optional): +# The working directory for the command. +# +# output (optional): +# Overrides the full output path. +# Defaults to $root_out_dir/gen/$target_path/$target_name; for example +# //flutter/foo/bar emits a binary at out/{variant}/gen/flutter/foo/bar. +template("gen_dartcli_call") { + # Build a reference to the Dart CLI (depending on prebuilt or source). + ext = "" + if (is_win) { + ext = ".exe" + } + dart = rebase_path("$host_prebuilt_dart_sdk/bin/dart$ext") + + # Actually generate the shell script. + gen_executable_call(target_name) { + command = rebase_path(dart) + forward_variables_from(invoker, + [ + "args", + "cwd", + "output", + ]) + } +} diff --git a/build/dart/internal/gen_executable_call.gni b/build/dart/internal/gen_executable_call.gni new file mode 100644 index 0000000000000..5a11da611df35 --- /dev/null +++ b/build/dart/internal/gen_executable_call.gni @@ -0,0 +1,62 @@ +# 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. + +# Generates an executable that runs a command and set of arguments. +# +# Parameters: +# command (required): +# The command to run, which is typically an absolute path to an executable. +# +# args (optional): +# Arguments to pass to the command. +# +# cwd (optional): +# The working directory for the command. +# +# output (optional): +# Overrides the full output path. +# Defaults to $root_out_dir/gen/$target_path/$target_name; for example +# //flutter/foo/bar emits a binary at out/{variant}/gen/flutter/foo/bar. +template("gen_executable_call") { + assert(defined(invoker.command), "Must specify 'command'") + + # The command to run. + command = invoker.command + + # The output path. + output = "$root_gen_dir/$target_name" + if (defined(invoker.output)) { + output = invoker.output + } else { + # Construct the output path. + output = get_label_info(target_name, "target_gen_dir") + } + + # Build the command line arguments. + call_args = [ + "--output", + rebase_path(output), + "--command", + command, + ] + if (defined(invoker.cwd)) { + call_args += [ + "--cwd", + rebase_path(invoker.cwd), + ] + } + if (defined(invoker.args)) { + call_args += [ + "--", + string_join(" ", invoker.args), + ] + } + + # Run build_cmd.py to generate the file and make it executable. + action(target_name) { + script = "//flutter/build/dart/internal/gen_executable_call.py" + outputs = [ output ] + args = call_args + } +} diff --git a/build/dart/internal/gen_executable_call.py b/build/dart/internal/gen_executable_call.py new file mode 100644 index 0000000000000..4595baf004bcb --- /dev/null +++ b/build/dart/internal/gen_executable_call.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# +# 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. + +"""Generates a shell or batch script to run a command.""" + +import argparse +import os +import string + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--output', required=True, help='Output file') + parser.add_argument('--command', required=True, help='Command to run') + parser.add_argument('--cwd', required=False, help='Working directory') + parser.add_argument('rest', nargs='*', help='Arguments to pass to the command') + + # Rest of the arguments are passed to the command. + args = parser.parse_args() + + out_path = os.path.dirname(args.output) + if not os.path.exists(out_path): + os.makedirs(out_path) + + script = string.Template('''#!/bin/sh + +set -e + +# Needed because if it is set, cd may print the path it changed to. +unset CDPATH + +# Store the current working directory. +prev_cwd=$$(pwd) + +# Set a trap to restore the working directory. +trap 'cd "$$prev_cwd"' EXIT + +CD_PATH="$cwd" +if [ -n "$$CD_PATH" ]; then + cd "$$CD_PATH" +fi + +$command "$args" +''') + + # Convert args into an escaped string. + escaped = [arg.replace('"', '\\"') for arg in args.rest] + + params = { + 'command': args.command, + 'args': '" "'.join(escaped), + 'cwd': args.cwd if args.cwd else '', + } + + with open(args.output, 'w') as f: + f.write(script.substitute(params)) + + # Make the script executable. + os.chmod(args.output, 0o755) + +if __name__ == '__main__': + main() diff --git a/build/dart/internal/tests/BUILD.gn b/build/dart/internal/tests/BUILD.gn deleted file mode 100644 index 752c40bda62cf..0000000000000 --- a/build/dart/internal/tests/BUILD.gn +++ /dev/null @@ -1,9 +0,0 @@ -# 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/internal/command_executable.gni") - -command_executable("tests") { - command = "dart" -} diff --git a/build/dart/test/BUILD.gn b/build/dart/test/BUILD.gn new file mode 100644 index 0000000000000..fe00229c46415 --- /dev/null +++ b/build/dart/test/BUILD.gn @@ -0,0 +1,27 @@ +# 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/internal/gen_dartcli_call.gni") +import("//flutter/build/dart/internal/gen_executable_call.gni") + +# Manual test targets that can be used to iterate on individual rules. + +# ninja -C ../out/host_debug flutter/build/dart/test:gen_executable_call +# ../out/host_debug/gen/flutter/build/dart/test/gen_executable_call +# +# Expected output: "Hello, World!" +gen_executable_call("gen_executable_call") { + command = "echo" + args = [ "Hello, World!" ] +} + +# ninja -C ../out/host_debug flutter/build/dart/test:gen_dartcli_call +# ../out/host_debug/gen/flutter/build/dart/test/gen_executable_call +# +# Expected output: Dart SDK version: 3.6.0-273.0.dev (dev) +# +# ... or something like ^, obviously it will constantly change as the SDK rolls. +gen_dartcli_call("gen_dartcli_call") { + args = [ "--version" ] +} diff --git a/tools/engine_tool/BUILD.gn b/tools/engine_tool/BUILD.gn new file mode 100644 index 0000000000000..9b36d0e669823 --- /dev/null +++ b/tools/engine_tool/BUILD.gn @@ -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("//flutter/build/dart/internal/gen_dartcli_call.gni") + +# TODO(matanl): WIP in https://github.com/flutter/flutter/issues/155769. +# +# Example usage: +# ninja -C ../out/host_debug flutter/tools/engine_tool:tests +# ../out/host_debug/gen/flutter/tools/engine_tool/tests +gen_dartcli_call("tests") { + args = [ "test" ] + cwd = "//flutter/tools/engine_tool" +} From 9ae548abe80f39eb4cf4054091cc1cd13aa00e4a Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 26 Sep 2024 17:03:39 -0700 Subject: [PATCH 3/5] ++ --- build/dart/internal/gen_executable_call.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/build/dart/internal/gen_executable_call.py b/build/dart/internal/gen_executable_call.py index 4595baf004bcb..8b99ff50be2ef 100644 --- a/build/dart/internal/gen_executable_call.py +++ b/build/dart/internal/gen_executable_call.py @@ -10,13 +10,14 @@ import os import string + def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--output', required=True, help='Output file') parser.add_argument('--command', required=True, help='Command to run') parser.add_argument('--cwd', required=False, help='Working directory') parser.add_argument('rest', nargs='*', help='Arguments to pass to the command') - + # Rest of the arguments are passed to the command. args = parser.parse_args() @@ -24,7 +25,8 @@ def main(): if not os.path.exists(out_path): os.makedirs(out_path) - script = string.Template('''#!/bin/sh + script = string.Template( + '''#!/bin/sh set -e @@ -43,15 +45,16 @@ def main(): fi $command "$args" -''') +''' + ) # Convert args into an escaped string. escaped = [arg.replace('"', '\\"') for arg in args.rest] params = { - 'command': args.command, - 'args': '" "'.join(escaped), - 'cwd': args.cwd if args.cwd else '', + 'command': args.command, + 'args': '" "'.join(escaped), + 'cwd': args.cwd if args.cwd else '', } with open(args.output, 'w') as f: @@ -60,5 +63,6 @@ def main(): # Make the script executable. os.chmod(args.output, 0o755) + if __name__ == '__main__': main() From 5dc249c60de21662e8dedf65e3af6b8c0bb3c787 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 27 Sep 2024 10:35:09 -0700 Subject: [PATCH 4/5] Chris had good feedbacks. --- build/dart/internal/gen_executable_call.py | 14 ++------------ build/dart/test/BUILD.gn | 9 +++++++++ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/build/dart/internal/gen_executable_call.py b/build/dart/internal/gen_executable_call.py index 8b99ff50be2ef..7183fc3a07308 100644 --- a/build/dart/internal/gen_executable_call.py +++ b/build/dart/internal/gen_executable_call.py @@ -30,19 +30,9 @@ def main(): set -e -# Needed because if it is set, cd may print the path it changed to. -unset CDPATH - -# Store the current working directory. -prev_cwd=$$(pwd) - # Set a trap to restore the working directory. -trap 'cd "$$prev_cwd"' EXIT - -CD_PATH="$cwd" -if [ -n "$$CD_PATH" ]; then - cd "$$CD_PATH" -fi +trap "popd > /dev/null" EXIT +pushd "$cwd" > /dev/null $command "$args" ''' diff --git a/build/dart/test/BUILD.gn b/build/dart/test/BUILD.gn index fe00229c46415..7c4a557bf586b 100644 --- a/build/dart/test/BUILD.gn +++ b/build/dart/test/BUILD.gn @@ -16,6 +16,15 @@ gen_executable_call("gen_executable_call") { args = [ "Hello, World!" ] } +# ninja -C ../out/host_debug flutter/build/dart/test:gen_executable_call_with_cwd +# ../out/host_debug/gen/flutter/build/dart/test/gen_executable_call_with_cwd +# +# Expected output: {varies}/flutter/build/dart/test +gen_executable_call("gen_executable_call_with_cwd") { + command = "echo \$PWD" + cwd = "//flutter/build/dart/test" +} + # ninja -C ../out/host_debug flutter/build/dart/test:gen_dartcli_call # ../out/host_debug/gen/flutter/build/dart/test/gen_executable_call # From ddce0522ab4856da1c8e23c7e3a10ec5f577b214 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 30 Sep 2024 12:35:02 -0700 Subject: [PATCH 5/5] Tweak generation script. --- build/dart/internal/gen_dartcli_call.gni | 9 ++++++++- build/dart/internal/gen_executable_call.py | 7 ++----- build/dart/test/BUILD.gn | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/build/dart/internal/gen_dartcli_call.gni b/build/dart/internal/gen_dartcli_call.gni index 8687da00de887..f7ae2ad40d3fe 100644 --- a/build/dart/internal/gen_dartcli_call.gni +++ b/build/dart/internal/gen_dartcli_call.gni @@ -26,12 +26,19 @@ template("gen_dartcli_call") { } dart = rebase_path("$host_prebuilt_dart_sdk/bin/dart$ext") + # Add default arguments to the Dart CLI. + dart_args = [] + if (defined(invoker.args)) { + dart_args += invoker.args + } + dart_args += [ "--suppress-analytics" ] + # Actually generate the shell script. gen_executable_call(target_name) { command = rebase_path(dart) + args = dart_args forward_variables_from(invoker, [ - "args", "cwd", "output", ]) diff --git a/build/dart/internal/gen_executable_call.py b/build/dart/internal/gen_executable_call.py index 7183fc3a07308..69ce53a1ef663 100644 --- a/build/dart/internal/gen_executable_call.py +++ b/build/dart/internal/gen_executable_call.py @@ -34,16 +34,13 @@ def main(): trap "popd > /dev/null" EXIT pushd "$cwd" > /dev/null -$command "$args" +$command $args ''' ) - # Convert args into an escaped string. - escaped = [arg.replace('"', '\\"') for arg in args.rest] - params = { 'command': args.command, - 'args': '" "'.join(escaped), + 'args': ' '.join(args.rest), 'cwd': args.cwd if args.cwd else '', } diff --git a/build/dart/test/BUILD.gn b/build/dart/test/BUILD.gn index 7c4a557bf586b..c33392a83c7b7 100644 --- a/build/dart/test/BUILD.gn +++ b/build/dart/test/BUILD.gn @@ -26,7 +26,7 @@ gen_executable_call("gen_executable_call_with_cwd") { } # ninja -C ../out/host_debug flutter/build/dart/test:gen_dartcli_call -# ../out/host_debug/gen/flutter/build/dart/test/gen_executable_call +# ../out/host_debug/gen/flutter/build/dart/test/gen_dartcli_call # # Expected output: Dart SDK version: 3.6.0-273.0.dev (dev) #