blob: b0cad527ded241ec255b51cae176c4cfb6668c24 [file]
// 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 '../build_utils.dart';
import '../gn.dart';
import '../label.dart';
import 'command.dart';
import 'flags.dart';
/// The root 'build' command.
final class BuildCommand extends CommandBase {
/// Constructs the 'build' command.
BuildCommand({
required super.environment,
required Map<String, BuilderConfig> configs,
super.help = false,
super.usageLineLength,
}) {
// When printing the help/usage for this command, only list all builds
// when the --verbose flag is supplied.
final bool includeCiBuilds = environment.verbose || !help;
builds = runnableBuilds(environment, configs, includeCiBuilds);
debugCheckBuilds(builds);
addConfigOption(
environment,
argParser,
builds,
);
addConcurrencyOption(argParser);
argParser.addFlag(
rbeFlag,
defaultsTo: environment.hasRbeConfigInTree(),
help: 'RBE is enabled by default when available.',
);
argParser.addFlag(
ltoFlag,
help: 'Whether LTO should be enabled for a build. Default is disabled',
);
}
/// List of compatible builds.
late final List<Build> builds;
@override
String get name => 'build';
@override
String get description => '''
Builds the engine
et build //flutter/fml/... # Build all targets in `//flutter/fml` and its subdirectories.
et build //flutter/fml:all # Build all targets in `//flutter/fml`.
et build //flutter/fml:fml_benchmarks # Build a specific target in `//flutter/fml`.
''';
@override
Future<int> run() async {
final String configName = argResults![configFlag] as String;
final bool useRbe = argResults![rbeFlag] as bool;
if (useRbe && !environment.hasRbeConfigInTree()) {
environment.logger.error('RBE was requested but no RBE config was found');
return 1;
}
final bool useLto = argResults![ltoFlag] as bool;
final String demangledName = demangleConfigName(environment, configName);
final Build? build =
builds.where((Build build) => build.name == demangledName).firstOrNull;
if (build == null) {
environment.logger.error('Could not find config $configName');
return 1;
}
final String dashJ = argResults![concurrencyFlag] as String;
final int? concurrency = int.tryParse(dashJ);
if (concurrency == null || concurrency < 0) {
environment.logger.error('-j must specify a positive integer.');
return 1;
}
final List<String> extraGnArgs = <String>[
if (!useRbe) '--no-rbe',
if (useLto) '--lto' else '--no-lto',
];
final List<String> commandLineTargets = argResults!.rest;
if (commandLineTargets.isNotEmpty &&
!await ensureBuildDir(environment, build, enableRbe: useRbe)) {
return 1;
}
// Builds only accept labels as arguments, so convert patterns to labels.
// TODO(matanlurey): Can be optimized in cases where wildcards are not used.
final Gn gn = Gn.fromEnvironment(environment);
final Set<Label> allTargets = <Label>{};
for (final String pattern in commandLineTargets) {
final TargetPattern target = TargetPattern.parse(pattern);
final List<BuildTarget> targets = await gn.desc(
'out/${build.ninja.config}',
target,
);
allTargets.addAll(targets.map((BuildTarget target) => target.label));
}
return runBuild(
environment,
build,
concurrency: concurrency,
extraGnArgs: extraGnArgs,
targets: allTargets.toList(),
enableRbe: useRbe,
);
}
}