Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
]
}
Expand Down
46 changes: 46 additions & 0 deletions build/dart/internal/gen_dartcli_call.gni
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 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")

# 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,
[
"cwd",
"output",
])
}
}
62 changes: 62 additions & 0 deletions build/dart/internal/gen_executable_call.gni
Original file line number Diff line number Diff line change
@@ -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
}
}
55 changes: 55 additions & 0 deletions build/dart/internal/gen_executable_call.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/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')
Copy link
Member

Choose a reason for hiding this comment

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

I <3 rest vs args +1


# 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
Copy link
Contributor

Choose a reason for hiding this comment

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

dumb question because I get tripped up on this constantly. set -e makes sure that the exit code of this script is non zero if the dart test exit code is non zero right? Can you check that failed tests report non-zero exit codes through the shell script too?

Copy link
Member

@jtmcdole jtmcdole Sep 27, 2024

Choose a reason for hiding this comment

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

Any command or pipeline that has an error will exit the script automatically. Dart tests that fail set errno 1.


# Set a trap to restore the working directory.
trap "popd > /dev/null" EXIT
pushd "$cwd" > /dev/null

$command $args
'''
)

params = {
'command': args.command,
'args': ' '.join(args.rest),
'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()
36 changes: 36 additions & 0 deletions build/dart/test/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 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_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_dartcli_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" ]
}
15 changes: 15 additions & 0 deletions tools/engine_tool/BUILD.gn
Original file line number Diff line number Diff line change
@@ -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"
}