diff --git a/.clang-tidy b/.clang-tidy index 7210342bdc213..b74be267bc42f 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -61,4 +61,4 @@ CheckOptions: # updated. # # tl;dr: I'm sorry. -HeaderFilterRegex: "[..\/]+\/flutter\/(assets|benchmarking|build|ci|common|display_list|docs|examples|flow|flutter_frontend_server|flutter_vma|fml|impeller|lib|runtime|shell|skia|sky|testing|tools|vulkan|wasm|web_sdk)\/.*" +HeaderFilterRegex: "[..\/]+\/flutter\/(assets|benchmarking|bin|build|ci|common|display_list|docs|examples|flow|flutter_frontend_server|flutter_vma|fml|impeller|lib|runtime|shell|skia|sky|testing|tools|vulkan|wasm|web_sdk)\/.*" diff --git a/bin/et b/bin/et new file mode 100755 index 0000000000000..54da8248cf034 --- /dev/null +++ b/bin/et @@ -0,0 +1,68 @@ +#!/bin/bash +# +# 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. + +set -e + +# Needed because if it is set, cd may print the path it changed to. +unset CDPATH + +# On Mac OS, readlink -f doesn't work, so follow_links traverses the path one +# link at a time, and then cds into the link destination and find out where it +# ends up. +# +# The function is enclosed in a subshell to avoid changing the working directory +# of the caller. +function follow_links() ( + cd -P "$(dirname -- "$1")" + file="$PWD/$(basename -- "$1")" + while [[ -h "$file" ]]; do + cd -P "$(dirname -- "$file")" + file="$(readlink -- "$file")" + cd -P "$(dirname -- "$file")" + file="$PWD/$(basename -- "$file")" + done + echo "$file" +) + +SCRIPT_DIR=$(follow_links "$(dirname -- "${BASH_SOURCE[0]}")") +ENGINE_DIR="$(cd "$SCRIPT_DIR/.."; pwd -P)" + +case "$(uname -s)" in + Linux) + OS="linux" + ;; + Darwin) + OS="macos" + ;; + *) + echo "The host platform is not supported by this tool" + exit 1 +esac + +case "$(uname -m)" in + arm64) + CPU="arm64" + ;; + x86_64) + CPU="x64" + ;; + *) + echo "The host platform is not supported by this tool" + exit 1 +esac + +PLATFORM="${OS}-${CPU}" +DART_SDK_DIR="${ENGINE_DIR}/prebuilts/${PLATFORM}/dart-sdk" +DART="${DART_SDK_DIR}/bin/dart" + +cd "${ENGINE_DIR}/tools/engine_tool" + +if [ ! -d ".dart_tool" ]; then + echo "You must run 'gclient sync -D' before using this tool." + exit 1 +fi + +"${DART}" --disable-dart-dev bin/et.dart "$@" diff --git a/tools/engine_tool/README.md b/tools/engine_tool/README.md new file mode 100644 index 0000000000000..496824acdcb8d --- /dev/null +++ b/tools/engine_tool/README.md @@ -0,0 +1,61 @@ +# The Engine Tool + +This is a command line Dart program that automates workflows in the +`flutter/engine` repository. + +### Prerequisites + +The tool requires an initial `gclient sync -D` as described in the [repo setup +steps](https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment#getting-the-source) +before it will work. + +## Status + +The tool has the following commands. + +* `help` - Prints helpful information about commands and usage. +* `query builds` - Lists the CI builds described under `ci/builders` that the +host platform is capable of executing. + +### Missing features + +There are currently many missing features. Some overall goals are listed in the +GitHub issue [here](https://github.com/flutter/flutter/issues/132807). Some +desirable new features would do the following: + +* Support Windows hosts. +* Add a `doctor` command. +* Update the engine checkout so that engine developers no longer have to remeber +to run `gclient sync -D`. +* Build and test the engine using CI configurations locally, with the +possibility to override or add new build options and targets. +* Build engines using options coming only from the command line. +* List tests and run them locally, automatically building their dependencies +first. Automatically start emulators or simulators if they're needed to run a +test. +* Spawn individual builders remotely using `led` from `depot_tools`. +* Encapsulate all code formatters, checkers, linters, etc. for all languages. +* Find a compatible version of the flutter/flutter repo, check it out, and spawn +tests from that repo with a locally built engine to run on an emulator, +simulator or device. +* Use a real logging package for prettier terminal output. +* Wire the tool up to a package providing autocomplete like +[cli_completion](https://pub.dev/packages/cli_completion.). + +The way the current tooling in the engine repo works may need to be rewritten, +especially tests spawned by `run_tests.py`, in order to provide this interface. + +## Contributing + +* Follow the [Flutter style guide](https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo) +for Dart code that are relevant outside of the framework repo. It contains +conventions that go beyond code formatting, which +we'll follow even if using `dart format` in the future. +* Do not call directly into `dart:io` except from `main.dart`. Instead access +the system only through the `Enviroment` object. +* All commands must have unit tests. If some functionality needs a fake +implementation, then write a fake implementation. +* When adding or changing functionality, update this README.md file. +* *Begin with the end in mind* - Start working from what the interface provided +by this tool *should* be, then modify underlying scripts and tools to provide +APIs to support that. diff --git a/tools/engine_tool/bin/et.dart b/tools/engine_tool/bin/et.dart new file mode 100644 index 0000000000000..03994fb372249 --- /dev/null +++ b/tools/engine_tool/bin/et.dart @@ -0,0 +1,7 @@ +// 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 'package:engine_tool/main.dart' as m; + +void main(List args) => m.main(args); diff --git a/tools/engine_tool/lib/main.dart b/tools/engine_tool/lib/main.dart new file mode 100644 index 0000000000000..cd42035b63d8d --- /dev/null +++ b/tools/engine_tool/lib/main.dart @@ -0,0 +1,66 @@ +// 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:ffi' as ffi show Abi; +import 'dart:io' as io show Directory, exitCode, stderr, stdout; + +import 'package:engine_build_configs/engine_build_configs.dart'; +import 'package:engine_repo_tools/engine_repo_tools.dart'; +import 'package:path/path.dart' as p; +import 'package:platform/platform.dart'; +import 'package:process_runner/process_runner.dart'; + +import 'src/commands/command_runner.dart'; +import 'src/environment.dart'; + +void main(List args) async { + // Find the engine repo. + final Engine engine; + try { + engine = Engine.findWithin(); + } catch (e) { + io.stderr.writeln(e); + io.exitCode = 1; + return; + } + + // Find and parse the engine build configs. + final io.Directory buildConfigsDir = io.Directory(p.join( + engine.flutterDir.path, 'ci', 'builders', + )); + final BuildConfigLoader loader = BuildConfigLoader( + buildConfigsDir: buildConfigsDir, + ); + + // Treat it as an error if no build configs were found. The caller likely + // expected to find some. + final Map configs = loader.configs; + if (configs.isEmpty) { + io.stderr.writeln( + 'Error: No build configs found under ${buildConfigsDir.path}', + ); + io.exitCode = 1; + return; + } + if (loader.errors.isNotEmpty) { + loader.errors.forEach(io.stderr.writeln); + io.exitCode = 1; + } + + // Use the Engine and BuildConfig collection to build the CommandRunner. + final ToolCommandRunner runner = ToolCommandRunner( + environment: Environment( + abi: ffi.Abi.current(), + engine: engine, + platform: const LocalPlatform(), + processRunner: ProcessRunner(), + stderr: io.stderr, + stdout: io.stdout, + ), + configs: configs, + ); + + io.exitCode = await runner.run(args); + return; +} diff --git a/tools/engine_tool/lib/src/commands/command.dart b/tools/engine_tool/lib/src/commands/command.dart new file mode 100644 index 0000000000000..3e61ff388e4a1 --- /dev/null +++ b/tools/engine_tool/lib/src/commands/command.dart @@ -0,0 +1,18 @@ +// 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 'package:args/command_runner.dart'; + +import '../environment.dart'; + +/// The base class that all commands and subcommands should inherit from. +abstract base class CommandBase extends Command { + /// Constructs the base command. + CommandBase({ + required this.environment + }); + + /// The host system environment. + final Environment environment; +} diff --git a/tools/engine_tool/lib/src/commands/command_runner.dart b/tools/engine_tool/lib/src/commands/command_runner.dart new file mode 100644 index 0000000000000..57aea41e02807 --- /dev/null +++ b/tools/engine_tool/lib/src/commands/command_runner.dart @@ -0,0 +1,53 @@ +// 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 'package:args/command_runner.dart'; + +import 'package:engine_build_configs/engine_build_configs.dart'; + +import '../environment.dart'; +import 'query_command.dart'; + +/// The root command runner. +final class ToolCommandRunner extends CommandRunner { + /// Constructs the runner and populates commands, subcommands, and global + /// options and flags. + ToolCommandRunner({ + required this.environment, + required this.configs, + }) : super(toolName, toolDescription) { + addCommand(QueryCommand( + environment: environment, + configs: configs, + )); + } + + /// The name of the tool as reported in the tool's usage and help + /// messages. + static const String toolName = 'et'; + + /// The description of the tool reported in the tool's usage and help + /// messages. + static const String toolDescription = 'A command line tool for working on ' + 'the Flutter Engine.'; + + /// The host system environment. + final Environment environment; + + /// Build configurations loaded from the engine from under ci/builders. + final Map configs; + + @override + Future run(Iterable args) async { + try{ + return await runCommand(parse(args)) ?? 1; + } on FormatException catch (e) { + environment.stderr.writeln(e); + return 1; + } on UsageException catch (e) { + environment.stderr.writeln(e); + return 1; + } + } +} diff --git a/tools/engine_tool/lib/src/commands/query_command.dart b/tools/engine_tool/lib/src/commands/query_command.dart new file mode 100644 index 0000000000000..20c87e6540d96 --- /dev/null +++ b/tools/engine_tool/lib/src/commands/query_command.dart @@ -0,0 +1,138 @@ +// 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 'package:engine_build_configs/engine_build_configs.dart'; + +import 'command.dart'; + +const String _allFlag = 'all'; +const String _builderFlag = 'builder'; +const String _verboseFlag = 'verbose'; + +/// The root 'query' command. +final class QueryCommand extends CommandBase { + /// Constructs the 'query' command. + QueryCommand({ + required super.environment, + required this.configs, + }) { + // Add options here that are common to all queries. + argParser + ..addFlag( + _allFlag, + abbr: 'a', + help: 'List all results, even when not relevant on this platform', + negatable: false, + ) + ..addOption( + _builderFlag, + abbr: 'b', + help: 'Restrict the query to a single builder.', + allowed: [ + for (final MapEntry entry in configs.entries) + if (entry.value.canRunOn(environment.platform)) + entry.key, + ], + allowedHelp: { + // TODO(zanderso): Add human readable descriptions to the json files. + for (final MapEntry entry in configs.entries) + if (entry.value.canRunOn(environment.platform)) + entry.key: entry.value.path, + }, + ) + ..addFlag( + _verboseFlag, + abbr: 'v', + help: 'Respond to queries with extra information', + negatable: false, + ); + + addSubcommand(QueryBuildsCommand( + environment: environment, + configs: configs, + )); + } + + /// Build configurations loaded from the engine from under ci/builders. + final Map configs; + + @override + String get name => 'query'; + + @override + String get description => 'Provides information about build configurations ' + 'and tests.'; + + @override + Future run() async { + environment.stdout.write(usage); + return 0; + } +} + +/// The 'query builds' command. +final class QueryBuildsCommand extends CommandBase { + /// Constructs the 'query build' command. + QueryBuildsCommand({ + required super.environment, + required this.configs, + }); + + /// Build configurations loaded from the engine from under ci/builders. + final Map configs; + + @override + String get name => 'builds'; + + @override + String get description => 'Provides information about CI build ' + 'configurations'; + + @override + Future run() async { + // Loop through all configs, and log those that are compatible with the + // current platform. + final bool all = parent!.argResults![_allFlag]! as bool; + final String? builderName = parent!.argResults![_builderFlag] as String?; + final bool verbose = parent!.argResults![_verboseFlag] as bool; + if (!verbose) { + environment.stdout.writeln( + 'Add --verbose to see detailed information about each builder', + ); + environment.stdout.writeln(); + } + for (final String key in configs.keys) { + if (builderName != null && key != builderName) { + continue; + } + + final BuildConfig config = configs[key]!; + if (!config.canRunOn(environment.platform) && !all) { + continue; + } + + environment.stdout.writeln('"$key" builder:'); + for (final GlobalBuild build in config.builds) { + if (!build.canRunOn(environment.platform) && !all) { + continue; + } + environment.stdout.writeln(' "${build.name}" config'); + if (!verbose) { + continue; + } + environment.stdout.writeln(' gn flags:'); + for (final String flag in build.gn) { + environment.stdout.writeln(' $flag'); + } + if (build.ninja.targets.isNotEmpty) { + environment.stdout.writeln(' ninja targets:'); + for (final String target in build.ninja.targets) { + environment.stdout.writeln(' $target'); + } + } + } + } + return 0; + } +} diff --git a/tools/engine_tool/lib/src/environment.dart b/tools/engine_tool/lib/src/environment.dart new file mode 100644 index 0000000000000..f210977b02445 --- /dev/null +++ b/tools/engine_tool/lib/src/environment.dart @@ -0,0 +1,47 @@ +// 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:ffi' as ffi show Abi; + +import 'package:engine_repo_tools/engine_repo_tools.dart'; +import 'package:platform/platform.dart'; +import 'package:process_runner/process_runner.dart'; + +/// This class encapsulates information about the host system. +/// +/// Rather than being written directly against `dart:io`, implementations in the +/// tool should only access the system by way of the abstractions in this class. +/// This is so that unit tests can be hermetic by providing fake +/// implementations. +final class Environment { + /// Constructs the environment. + Environment({ + required this.abi, + required this.engine, + required this.platform, + required this.processRunner, + required this.stderr, + required this.stdout, + }); + + /// The host OS and architecture that the tool is running on. + final ffi.Abi abi; + + /// Information about paths in the engine repo. + final Engine engine; + + /// More detailed information about the host platform. + final Platform platform; + + /// Facility for commands to run subprocesses. + final ProcessRunner processRunner; + + // TODO(zanderso): Replace stderr and stdout with a real logger. + + /// A sink for error messages from commands. + final StringSink stderr; + + /// A sink for non-error messages from commands. + final StringSink stdout; +} diff --git a/tools/engine_tool/pubspec.yaml b/tools/engine_tool/pubspec.yaml new file mode 100644 index 0000000000000..b4e2713e7b156 --- /dev/null +++ b/tools/engine_tool/pubspec.yaml @@ -0,0 +1,65 @@ +# 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. + +name: engine_tool +publish_to: none +environment: + sdk: '>=3.2.0-0 <4.0.0' + +# Do not add any dependencies that require more than what is provided in +# //third_party/pkg, //third_party/dart/pkg, or +# //third_party/dart/third_party/pkg. In particular, package:test is not usable +# here. + +# If you do add packages here, make sure you can run `pub get --offline`, and +# check the .packages and .package_config to make sure all the paths are +# relative to this directory into //third_party/dart + +dependencies: + args: any + engine_build_configs: + path: ../pkg/engine_build_configs + engine_repo_tools: + path: ../pkg/engine_repo_tools + file: any + meta: any + path: any + platform: any + process_runner: any + +dev_dependencies: + async_helper: any + expect: any + litetest: any + process_fakes: + path: ../pkg/process_fakes + smith: any + +dependency_overrides: + 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 + collection: + path: ../../../third_party/dart/third_party/pkg/collection + expect: + path: ../../../third_party/dart/pkg/expect + file: + path: ../../../third_party/dart/third_party/pkg/file/packages/file + litetest: + path: ../../testing/litetest + meta: + path: ../../../third_party/dart/pkg/meta + path: + path: ../../../third_party/dart/third_party/pkg/path + platform: + path: ../../third_party/pkg/platform + process: + path: ../../third_party/pkg/process + process_runner: + path: ../../third_party/pkg/process_runner + smith: + path: ../../../third_party/dart/pkg/smith diff --git a/tools/engine_tool/test/fixtures.dart b/tools/engine_tool/test/fixtures.dart new file mode 100644 index 0000000000000..596609a1db977 --- /dev/null +++ b/tools/engine_tool/test/fixtures.dart @@ -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. + +String testConfig(String os) => ''' +{ + "builds": [ + { + "archives": [ + { + "name": "build_name", + "base_path": "base/path", + "type": "gcs", + "include_paths": ["include/path"], + "realm": "archive_realm" + } + ], + "drone_dimensions": [ + "os=$os" + ], + "gclient_variables": { + "variable": false + }, + "gn": ["--gn-arg", "--lto", "--goma", "--no-rbe"], + "name": "build_name", + "ninja": { + "config": "build_name", + "targets": ["ninja_target"] + }, + "tests": [ + { + "language": "python3", + "name": "build_name tests", + "parameters": ["--test-params"], + "script": "test/script.py", + "contexts": ["context"] + } + ], + "generators": { + "tasks": [ + { + "name": "generator_task", + "language": "python", + "parameters": ["--gen-param"], + "scripts": ["gen/script.py"] + } + ] + } + } + ], + "generators": { + "tasks": [ + { + "name": "global generator task", + "parameters": ["--global-gen-param"], + "script": "global/gen_script.dart", + "language": "dart" + } + ] + }, + "tests": [ + { + "name": "global test", + "recipe": "engine_v2/tester_engine", + "drone_dimensions": [ + "os=$os" + ], + "gclient_variables": { + "variable": false + }, + "dependencies": ["dependency"], + "test_dependencies": [ + { + "dependency": "test_dependency", + "version": "git_revision:3a77d0b12c697a840ca0c7705208e8622dc94603" + } + ], + "tasks": [ + { + "name": "global test task", + "parameters": ["--test-parameter"], + "script": "global/test/script.py" + } + ] + } + ] +} +'''; diff --git a/tools/engine_tool/test/query_command_test.dart b/tools/engine_tool/test/query_command_test.dart new file mode 100644 index 0000000000000..d2f678f1b273e --- /dev/null +++ b/tools/engine_tool/test/query_command_test.dart @@ -0,0 +1,130 @@ +// 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:convert' as convert; +import 'dart:ffi' as ffi show Abi; +import 'dart:io' as io; + +import 'package:engine_build_configs/engine_build_configs.dart'; +import 'package:engine_repo_tools/engine_repo_tools.dart'; +import 'package:engine_tool/src/commands/command_runner.dart'; +import 'package:engine_tool/src/environment.dart'; +import 'package:litetest/litetest.dart'; +import 'package:platform/platform.dart'; +import 'package:process_fakes/process_fakes.dart'; +import 'package:process_runner/process_runner.dart'; + +import 'fixtures.dart' as fixtures; + +void main() { + final Engine engine; + try { + engine = Engine.findWithin(); + } catch (e) { + io.stderr.writeln(e); + io.exitCode = 1; + return; + } + + final BuildConfig linuxTestConfig = BuildConfig.fromJson( + path: 'ci/builders/linux_test_config.json', + map: convert.jsonDecode(fixtures.testConfig('Linux')) as Map, + ); + + final BuildConfig macTestConfig = BuildConfig.fromJson( + path: 'ci/builders/mac_test_config.json', + map: convert.jsonDecode(fixtures.testConfig('Mac-12')) as Map, + ); + + final BuildConfig winTestConfig = BuildConfig.fromJson( + path: 'ci/builders/win_test_config.json', + map: convert.jsonDecode(fixtures.testConfig('Windows-11')) as Map, + ); + + final Map configs = { + 'linux_test_config': linuxTestConfig, + 'linux_test_config2': linuxTestConfig, + 'mac_test_config': macTestConfig, + 'win_test_config': winTestConfig, + }; + + Environment linuxEnv(StringBuffer stderr, StringBuffer stdout) { + return Environment( + abi: ffi.Abi.linuxX64, + engine: engine, + platform: FakePlatform(operatingSystem: Platform.linux), + processRunner: ProcessRunner( + processManager: FakeProcessManager(), + ), + stderr: stderr, + stdout: stdout, + ); + } + + test('query command returns builds for the host platform.', () async { + final StringBuffer stderr = StringBuffer(); + final StringBuffer stdout = StringBuffer(); + final Environment env = linuxEnv(stderr, stdout); + final ToolCommandRunner runner = ToolCommandRunner( + environment: env, + configs: configs, + ); + final int result = await runner.run([ + 'query', 'builds', + ]); + expect(result, equals(0)); + expect( + stdout.toString().trim().split('\n'), + equals([ + 'Add --verbose to see detailed information about each builder', + '', + '"linux_test_config" builder:', + ' "build_name" config', + '"linux_test_config2" builder:', + ' "build_name" config', + ]), + ); + }); + + test('query command with --builder returns only from the named builder.', () async { + final StringBuffer stderr = StringBuffer(); + final StringBuffer stdout = StringBuffer(); + final Environment env = linuxEnv(stderr, stdout); + final ToolCommandRunner runner = ToolCommandRunner( + environment: env, + configs: configs, + ); + final int result = await runner.run([ + 'query', 'builds', '--builder', 'linux_test_config', + ]); + expect(result, equals(0)); + expect( + stdout.toString().trim().split('\n'), + equals([ + 'Add --verbose to see detailed information about each builder', + '', + '"linux_test_config" builder:', + ' "build_name" config', + ]), + ); + }); + + test('query command with --all returns all builds.', () async { + final StringBuffer stderr = StringBuffer(); + final StringBuffer stdout = StringBuffer(); + final Environment env = linuxEnv(stderr, stdout); + final ToolCommandRunner runner = ToolCommandRunner( + environment: env, + configs: configs, + ); + final int result = await runner.run([ + 'query', 'builds', '--all', + ]); + expect(result, equals(0)); + expect( + stdout.toString().trim().split('\n').length, + equals(10), + ); + }); +} diff --git a/tools/pkg/engine_build_configs/lib/src/build_config.dart b/tools/pkg/engine_build_configs/lib/src/build_config.dart index 1cbdeeb95e63c..a38e50f3dfd91 100644 --- a/tools/pkg/engine_build_configs/lib/src/build_config.dart +++ b/tools/pkg/engine_build_configs/lib/src/build_config.dart @@ -150,6 +150,12 @@ final class BuildConfig extends BuildConfigBase { } return errors; } + + /// Returns true if any of the [GlobalBuild]s it contains can run on + /// `platform`, and false otherwise. + bool canRunOn(Platform platform) { + return builds.any((GlobalBuild b) => b.canRunOn(platform)); + } } /// A "build" is a dictionary with a gn command, a ninja command, zero or more diff --git a/tools/pub_get_offline.py b/tools/pub_get_offline.py index dd67b22e2f06d..ee42941cc5bf2 100644 --- a/tools/pub_get_offline.py +++ b/tools/pub_get_offline.py @@ -14,9 +14,7 @@ import subprocess import sys -SRC_ROOT = os.path.dirname( - os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -) +SRC_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) ENGINE_DIR = os.path.join(SRC_ROOT, 'flutter') ALL_PACKAGES = [ @@ -37,6 +35,7 @@ os.path.join(ENGINE_DIR, 'tools', 'build_bucket_golden_scraper'), os.path.join(ENGINE_DIR, 'tools', 'clang_tidy'), os.path.join(ENGINE_DIR, 'tools', 'const_finder'), + os.path.join(ENGINE_DIR, 'tools', 'engine_tool'), os.path.join(ENGINE_DIR, 'tools', 'gen_web_locale_keymap'), os.path.join(ENGINE_DIR, 'tools', 'githooks'), os.path.join(ENGINE_DIR, 'tools', 'golden_tests_harvester'), @@ -75,10 +74,7 @@ def check_package(package): print('Error: package "%s" was fetched from pub' % package_name) pub_count = pub_count + 1 if pub_count > 0: - print( - 'Error: %d packages were fetched from pub for %s' % - (pub_count, package) - ) + print('Error: %d packages were fetched from pub for %s' % (pub_count, package)) print( 'Please fix the pubspec.yaml for %s ' 'so that all dependencies are path dependencies' % package @@ -118,18 +114,13 @@ def find_unlisted_packages(): def main(): - dart_sdk_bin = os.path.join( - SRC_ROOT, 'third_party', 'dart', 'tools', 'sdks', 'dart-sdk', 'bin' - ) + dart_sdk_bin = os.path.join(SRC_ROOT, 'third_party', 'dart', 'tools', 'sdks', 'dart-sdk', 'bin') # Ensure all relevant packages are listed in ALL_PACKAGES. unlisted = find_unlisted_packages() if len(unlisted) > 0: for pkg in unlisted: - print( - 'The Dart package "%s" must be checked in flutter/tools/pub_get_offline.py' - % pkg - ) + print('The Dart package "%s" must be checked in flutter/tools/pub_get_offline.py' % pkg) return 1 dart = 'dart'