Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 05cb5d7

Browse files
authored
Refactor BuildPlan, better document and explain --config. (#56324)
Closes flutter/flutter#156591. Closes flutter/flutter#156355. I also moved some functions only used as implementation details :)
1 parent 3e14265 commit 05cb5d7

File tree

6 files changed

+152
-106
lines changed

6 files changed

+152
-106
lines changed

tools/engine_tool/BUILD.gn

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ group("tests") {
88
testonly = true
99
public_deps = [
1010
":build_command_test",
11+
":build_plan_test",
1112
":entry_point_test",
1213
":fetch_command_test",
1314
":flutter_tools_test",
@@ -40,6 +41,10 @@ dart_test("build_command_test") {
4041
main_dart = "test/commands/build_command_test.dart"
4142
}
4243

44+
dart_test("build_plan_test") {
45+
main_dart = "test/commands/build_plan_test.dart"
46+
}
47+
4348
dart_test("entry_point_test") {
4449
main_dart = "test/entry_point_test.dart"
4550
}

tools/engine_tool/lib/src/build_plan.dart

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:args/args.dart';
66
import 'package:collection/collection.dart';
77
import 'package:engine_build_configs/engine_build_configs.dart';
88
import 'package:meta/meta.dart';
9+
import 'package:platform/platform.dart';
910

1011
import 'build_utils.dart';
1112
import 'environment.dart';
@@ -162,28 +163,40 @@ final class BuildPlan {
162163
required Map<String, BuilderConfig> configs,
163164
}) {
164165
// Add --config.
165-
final builds = runnableBuilds(
166-
environment,
167-
configs,
168-
environment.verbose || !help,
166+
final builds = _extractBuilds(
167+
environment.platform,
168+
runnableConfigs: _runnableBuildConfigs(
169+
environment.platform,
170+
configsByName: configs,
171+
),
172+
hideCiSpecificBuilds: help && !environment.verbose,
169173
);
170174
debugCheckBuilds(builds);
171175
parser.addOption(
172176
_flagConfig,
173177
abbr: 'c',
174-
defaultsTo: () {
175-
if (builds.any((b) => b.name == 'host_debug')) {
176-
return 'host_debug';
177-
}
178-
return null;
179-
}(),
178+
help: ''
179+
'Selects a build configuration for the current platform.\n'
180+
'\n'
181+
'If omitted, et attempts '
182+
'to default to a suitable target platform. This is typically a '
183+
'"host_debug" build when building on a supported desktop OS, or a '
184+
'suitable build when targeting (via "et run") a flutter app.\n'
185+
'\n'
186+
'${environment.verbose ? ''
187+
'Since verbose mode was selected, both local development '
188+
'configurations and configurations that are typically only '
189+
'used on CI will be visible, including possible duplicates.' : ''
190+
'Configurations include (use --verbose for more details):'}',
180191
allowed: [
181192
for (final config in builds) mangleConfigName(environment, config.name),
182-
],
183-
allowedHelp: {
184-
for (final config in builds)
185-
mangleConfigName(environment, config.name): config.description,
186-
},
193+
]..sort(),
194+
allowedHelp: environment.verbose
195+
? {
196+
for (final config in builds)
197+
mangleConfigName(environment, config.name): config.description,
198+
}
199+
: null,
187200
);
188201

189202
// Add --lto.
@@ -361,3 +374,41 @@ enum BuildStrategy {
361374
const BuildStrategy(this._help);
362375
final String _help;
363376
}
377+
378+
typedef _ConfigsByName = Iterable<MapEntry<String, BuilderConfig>>;
379+
380+
/// Computes a list of build configs that can can execute on [environment].
381+
_ConfigsByName _runnableBuildConfigs(
382+
Platform platform, {
383+
required Map<String, BuilderConfig> configsByName,
384+
}) {
385+
return configsByName.entries.where((entry) {
386+
return entry.value.canRunOn(platform);
387+
});
388+
}
389+
390+
/// Extracts [Build]s from [runnableConfigs] that can execute on [platform].
391+
///
392+
/// If [hideCiSpecificBuilds], builds that are unlikely to be picked for local
393+
/// development (i.e. start with the prefix `ci/` by convention) are not
394+
/// returned in order to make command-line _help_ text shorter.
395+
List<Build> _extractBuilds(
396+
Platform platform, {
397+
required _ConfigsByName runnableConfigs,
398+
required bool hideCiSpecificBuilds,
399+
}) {
400+
return [
401+
for (final buildConfig in runnableConfigs)
402+
...buildConfig.value.builds.where(
403+
(build) {
404+
if (!build.canRunOn(platform)) {
405+
return false;
406+
}
407+
if (!hideCiSpecificBuilds) {
408+
return true;
409+
}
410+
return build.name.startsWith(platform.operatingSystem);
411+
},
412+
),
413+
];
414+
}

tools/engine_tool/lib/src/build_utils.dart

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,51 +11,6 @@ import 'environment.dart';
1111
import 'label.dart';
1212
import 'logger.dart';
1313

14-
/// A function that returns true or false when given a [BuilderConfig] and its
15-
/// name.
16-
typedef ConfigFilter = bool Function(String name, BuilderConfig config);
17-
18-
/// A function that returns true or false when given a [BuilderConfig] name
19-
/// and a [Build].
20-
typedef BuildFilter = bool Function(String configName, Build build);
21-
22-
/// Returns a filtered copy of [input] filtering out configs where test
23-
/// returns false.
24-
Map<String, BuilderConfig> filterBuilderConfigs(
25-
Map<String, BuilderConfig> input, ConfigFilter test) {
26-
return <String, BuilderConfig>{
27-
for (final MapEntry<String, BuilderConfig> entry in input.entries)
28-
if (test(entry.key, entry.value)) entry.key: entry.value,
29-
};
30-
}
31-
32-
/// Returns a copy of [input] filtering out configs that are not runnable
33-
/// on the current platform.
34-
Map<String, BuilderConfig> runnableBuilderConfigs(
35-
Environment env, Map<String, BuilderConfig> input) {
36-
return filterBuilderConfigs(input, (String name, BuilderConfig config) {
37-
return config.canRunOn(env.platform);
38-
});
39-
}
40-
41-
/// Returns a List of [Build] that match test.
42-
List<Build> filterBuilds(Map<String, BuilderConfig> input, BuildFilter test) {
43-
return <Build>[
44-
for (final MapEntry<String, BuilderConfig> entry in input.entries)
45-
for (final Build build in entry.value.builds)
46-
if (test(entry.key, build)) build,
47-
];
48-
}
49-
50-
/// Returns a list of runnable builds.
51-
List<Build> runnableBuilds(
52-
Environment env, Map<String, BuilderConfig> input, bool verbose) {
53-
return filterBuilds(input, (String configName, Build build) {
54-
return build.canRunOn(env.platform) &&
55-
(verbose || build.name.startsWith(env.platform.operatingSystem));
56-
});
57-
}
58-
5914
/// Validates the list of builds.
6015
/// Calls assert.
6116
void debugCheckBuilds(List<Build> builds) {
@@ -99,8 +54,10 @@ String mangleConfigName(Environment env, String name) {
9954
if (_doNotMangle(env, name)) {
10055
return name;
10156
}
102-
throw ArgumentError(
103-
'name argument "$name" must start with a valid platform name or "ci"',
57+
throw ArgumentError.value(
58+
name,
59+
'name',
60+
'Expected to start with a valid platform name (i.e. $osPrefix) or "ci/"',
10461
);
10562
}
10663

tools/engine_tool/lib/src/commands/command_runner.dart

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,14 @@ final class ToolCommandRunner extends CommandRunner<int> {
2525
required this.environment,
2626
required this.configs,
2727
this.help = false,
28-
}) : super(toolName, toolDescription, usageLineLength: _usageLineLength) {
28+
}) : super(
29+
'et',
30+
''
31+
'A command line tool for working on '
32+
'the Flutter Engine.\n\nThis is a community supported project, '
33+
'for more information see https://flutter.dev/to/et.',
34+
usageLineLength: _usageLineLength,
35+
) {
2936
final List<Command<int>> commands = <Command<int>>[
3037
FetchCommand(
3138
environment: environment,
@@ -73,16 +80,6 @@ final class ToolCommandRunner extends CommandRunner<int> {
7380
);
7481
}
7582

76-
/// The name of the tool as reported in the tool's usage and help
77-
/// messages.
78-
static const String toolName = 'et';
79-
80-
/// The description of the tool reported in the tool's usage and help
81-
/// messages.
82-
static const String toolDescription = 'A command line tool for working on '
83-
'the Flutter Engine.\n\nThis is a community supported project, file '
84-
'a bug or feature request: https://flutter.dev/to/engine-tool-bug.';
85-
8683
/// The host system environment.
8784
final Environment environment;
8885

tools/engine_tool/test/build_plan_test.dart

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,75 @@ void main() {
547547
contains('Additional arguments to provide to "gn"'),
548548
);
549549
});
550+
551+
/// Returns an [ArgParser] pre-primed with both MacOS and Linux builds.
552+
ArgParser createMultiPlatformArgParser({
553+
required bool verbose,
554+
}) {
555+
final testEnv = TestEnvironment.withTestEngine(
556+
verbose: verbose,
557+
);
558+
addTearDown(testEnv.cleanup);
559+
560+
final linuxConfig = TestBuilderConfig();
561+
linuxConfig.addBuild(
562+
name: 'linux/host_debug',
563+
dimension: TestDroneDimension.linux,
564+
description: 'A development build of the Linux host.',
565+
);
566+
linuxConfig.addBuild(
567+
name: 'ci/linux_host_debug',
568+
dimension: TestDroneDimension.linux,
569+
description: 'A CI-suitable development build of the Linux host.',
570+
);
571+
572+
final macOSConfig = TestBuilderConfig();
573+
macOSConfig.addBuild(
574+
name: 'macos/host_debug',
575+
dimension: TestDroneDimension.mac,
576+
description: 'A build we do not expect to see due to filtering.',
577+
);
578+
579+
final parser = ArgParser();
580+
final _ = BuildPlan.configureArgParser(
581+
parser,
582+
testEnv.environment,
583+
configs: {
584+
'linux_test_config': linuxConfig.buildConfig(
585+
path: 'ci/builders/linux_test_config.json',
586+
),
587+
'macos_test_config': macOSConfig.buildConfig(
588+
path: 'ci/builders/macos_test_config.json',
589+
),
590+
},
591+
help: true,
592+
);
593+
594+
return parser;
595+
}
596+
597+
test('shows only non-CI builds that can run locally', () {
598+
final parser = createMultiPlatformArgParser(verbose: false);
599+
600+
expect(
601+
parser.usage,
602+
contains('[host_debug]'),
603+
);
604+
});
605+
606+
test('shows builds that can run locally, with details', () {
607+
final parser = createMultiPlatformArgParser(verbose: true);
608+
609+
expect(
610+
parser.usage,
611+
stringContainsInOrder([
612+
'[ci/linux_host_debug]',
613+
'A CI-suitable development build of the Linux host.',
614+
'[host_debug]',
615+
'A development build of the Linux host.',
616+
]),
617+
);
618+
});
550619
});
551620
}
552621

tools/engine_tool/test/commands/build_command_test.dart

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,6 @@ import '../src/test_build_configs.dart';
1616
import '../src/utils.dart';
1717

1818
void main() {
19-
test('can find host runnable build', () async {
20-
final testEnv = TestEnvironment.withTestEngine(
21-
abi: Abi.macosArm64,
22-
);
23-
addTearDown(testEnv.cleanup);
24-
25-
final builder = TestBuilderConfig();
26-
builder.addBuild(
27-
name: 'macos/host_debug',
28-
dimension: TestDroneDimension.mac,
29-
);
30-
builder.addBuild(
31-
name: 'mac/host_profile',
32-
dimension: TestDroneDimension.mac,
33-
);
34-
builder.addBuild(
35-
name: 'linux/host_debug',
36-
dimension: TestDroneDimension.linux,
37-
);
38-
39-
final configs = {
40-
'mac_test_config': builder.buildConfig(
41-
path: 'ci/builders/mac_test_config.json',
42-
),
43-
};
44-
45-
final result = runnableBuilds(testEnv.environment, configs, true);
46-
expect(
47-
result.map((r) => r.name),
48-
unorderedEquals(['macos/host_debug', 'mac/host_profile']),
49-
);
50-
});
51-
5219
test('build command invokes gn', () async {
5320
final testEnv = TestEnvironment.withTestEngine(
5421
abi: Abi.macosArm64,

0 commit comments

Comments
 (0)