Recognizegroup, and warn when we silently discard targets. (flutter/engine#55791)

Closes https://github.com/flutter/flutter/issues/156260.

Fixes the degenerate case where you specify an unrecognized target, and it falls back to rebuilding the entire engine as if you specified nothing. In addition, added recognition of `group`.
This commit is contained in:
Matan Lurey 2024-10-10 11:45:49 -07:00 committed by GitHub
parent ce933dae9a
commit ecb7c78604
5 changed files with 167 additions and 1 deletions

View File

@ -72,6 +72,20 @@ et build //flutter/fml:fml_benchmarks # Build a specific target in `//flutter/f
allTargets.addAll(targets.map((target) => target.label));
}
// Warn that we've discarded some targets.
// Other warnings should have been emitted above, so if this ends up being
// unneccesarily noisy, we can remove it or limit it to verbose mode.
if (allTargets.length < commandLineTargets.length) {
// Report which targets were not found.
final notFound = commandLineTargets.where(
(target) => !allTargets.contains(Label.parse(target)),
);
environment.logger.warning(
'One or more targets specified did not match any build targets:\n\n'
'${notFound.join('\n')}',
);
}
return runBuild(
environment,
plan.build,

View File

@ -1,3 +1,8 @@
// 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:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
@ -106,6 +111,9 @@ interface class Gn {
JsonObject(properties),
);
if (target == null) {
_environment.logger.warning(
'Unknown target type for $label: type=${properties['type']}',
);
return null;
}
return target;
@ -180,6 +188,11 @@ sealed class BuildTarget {
testOnly: testOnly,
json: json,
),
'group' => GroupBuildTarget(
label: Label.parseGn(label),
testOnly: testOnly,
deps: json.stringList('deps').map(Label.parseGn).toList(),
),
_ => null,
};
}
@ -281,3 +294,36 @@ final class ExecutableBuildTarget extends BuildTarget {
String toString() =>
'ExecutableBuildTarget($label, testOnly=$testOnly, executable=$executable)';
}
/// A build target that [group]s a meta-target of other build targets.
///
/// [group]: https://gn.googlesource.com/gn/+/main/docs/reference.md#func_group
final class GroupBuildTarget extends BuildTarget {
/// Construct a group build target.
const GroupBuildTarget({
required super.label,
required super.testOnly,
required this.deps,
});
/// The list of dependencies for this group target.
final List<Label> deps;
@override
bool operator ==(Object other) {
if (other is! GroupBuildTarget) {
return false;
}
if (label != other.label || testOnly != other.testOnly) {
return false;
}
return const ListEquality<Object>().equals(deps, other.deps);
}
@override
int get hashCode => Object.hash(label, testOnly, Object.hashAll(deps));
@override
String toString() =>
'GroupBuildTarget($label, testOnly=$testOnly, deps=$deps)';
}

View File

@ -11,6 +11,7 @@ import 'package:engine_tool/src/logger.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import '../src/matchers.dart';
import '../src/test_build_configs.dart';
import '../src/utils.dart';
@ -659,6 +660,77 @@ The input testing/scenario_app:sceario_app matches no targets, configs or files.
);
});
test('build command warns on an unrecognized action', () async {
final testEnv = TestEnvironment.withTestEngine(
abi: Abi.macosArm64,
cannedProcesses: [
CannedProcess(
(command) => command.contains('desc'),
stdout: convert.jsonEncode({
'//flutter/tools/unrecognized:action': {
'outputs': [
'//out/host_debug/unrecognized_action',
],
'testonly': true,
'type': 'unrecognized',
},
}),
),
],
);
addTearDown(testEnv.cleanup);
final builder = TestBuilderConfig();
builder.addBuild(
name: 'ci/host_debug',
targetDir: 'host_debug',
dimension: TestDroneDimension.mac,
);
final runner = ToolCommandRunner(
environment: testEnv.environment,
configs: {
'mac_test_config': builder.buildConfig(
path: 'ci/builders/mac_test_config.json',
),
},
);
final result = await runner.run([
'build',
'--config',
'ci/host_debug',
'//flutter/tools/unrecognized:action',
]);
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
expect(result, equals(0));
expect(
testEnv.testLogs,
contains(
logRecord(
stringContainsInOrder([
'Unknown target type',
'//flutter/tools/unrecognized:action',
'type=unrecognized',
]),
level: Logger.warningLevel,
),
),
);
expect(
testEnv.testLogs,
contains(logRecord(
stringContainsInOrder([
'One or more targets specified did not match',
'//flutter/tools/unrecognized:action',
]),
level: Logger.warningLevel,
)),
);
});
test('et help build line length is not too big', () async {
final testEnv = TestEnvironment.withTestEngine(
verbose: true,

View File

@ -19,7 +19,7 @@ import 'package:process_fakes/process_fakes.dart';
import 'package:process_runner/process_runner.dart';
import 'package:test/test.dart';
import 'src/test_build_configs.dart';
import '../src/test_build_configs.dart';
void main() {
late io.Directory tempRoot;

View File

@ -127,6 +127,40 @@ void main() {
);
});
test('parses a group', () async {
final testEnv = TestEnvironment.withTestEngine(
cannedProcesses: [
CannedProcess(
(List<String> command) => command.contains('desc'),
stdout: '''
{
"//foo/bar:baz_group": {
"deps": ["//foo/bar:baz_shared_library"],
"testonly": true,
"type": "group"
}
}
''',
),
],
);
addTearDown(testEnv.cleanup);
final gn = Gn.fromEnvironment(testEnv.environment);
final targets = await gn.desc('out/Release', TargetPattern('//foo', 'bar'));
expect(targets, hasLength(1));
final groupTarget = targets.single;
expect(
groupTarget,
GroupBuildTarget(
label: Label('//foo/bar', 'baz_group'),
testOnly: true,
deps: [Label('//foo/bar', 'baz_shared_library')],
),
);
});
test('parses a dart_test action as an executable', () async {
final testEnv = TestEnvironment.withTestEngine(
cannedProcesses: [