blob: 3f7078088c5fa2b629291a94a70b4a17cf856114 [file] [log] [blame]
// Copyright 2023 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:devtools_tool/commands/shared.dart';
import 'package:devtools_tool/model.dart';
import 'package:io/io.dart';
import 'package:path/path.dart' as path;
import '../utils.dart';
/// This command builds the DevTools Flutter web app.
///
/// By default, this command builds DevTools in release mode, but this can be
/// overridden by passing 'debug' or 'profile' as the
/// [SharedCommandArgs.buildMode] argument. For testing embedded content in
/// VS Code, 'profile' or the default 'release' mode must be used because
/// the '--dart2js-optimization=O1' flag that is passed for 'debug' builds
/// will cause issues with the VS Code embedding.
///
/// If the [SharedCommandArgs.useFlutterFromPath] argument is present, the
/// Flutter SDK will not be updated to the latest Flutter candidate before
/// building DevTools. Use this flag to save the cost of updating the Flutter
/// SDK when you already have the proper SDK checked out. This is helpful when
/// developing with the DevTools server.
///
/// If the [SharedCommandArgs.updatePerfetto] argument is present, the
/// precompiled bits for Perfetto will be updated from the
/// `dt update-perfetto` command as part of the DevTools build
/// process.
///
/// If [SharedCommandArgs.pubGet] argument is negated (e.g. --no-pub-get), then
/// `dt pub-get --only-main` command will not be run before building
/// the DevTools web app. Use this flag to save the cost of updating pub
/// packages if your pub cahce does not need to be updated. This is helpful when
/// developing with the DevTools server.
class BuildCommand extends Command {
BuildCommand() {
argParser
..addUpdateFlutterFlag()
..addUpdatePerfettoFlag()
..addPubGetFlag()
..addBulidModeOption()
..addWasmFlag()
..addNoStripWasmFlag()
..addNoMinifyWasmFlag();
}
@override
String get name => 'build';
@override
String get description => 'Prepares a release build of DevTools.';
@override
Future run() async {
final repo = DevToolsRepo.getInstance();
final processManager = ProcessManager();
final results = argResults!;
final updateFlutter =
results[SharedCommandArgs.updateFlutter.flagName] as bool;
final updatePerfetto =
results[SharedCommandArgs.updatePerfetto.flagName] as bool;
final runPubGet = results[SharedCommandArgs.pubGet.flagName] as bool;
final buildMode = results[SharedCommandArgs.buildMode.flagName] as String;
final useWasm = results[SharedCommandArgs.wasm.flagName] as bool;
final noStripWasm = results[SharedCommandArgs.noStripWasm.flagName] as bool;
final noMinifyWasm =
results[SharedCommandArgs.noMinifyWasm.flagName] as bool;
final webBuildDir = Directory(
path.join(repo.devtoolsAppDirectoryPath, 'build', 'web'),
);
if (updateFlutter) {
logStatus('updating tool/flutter-sdk to the latest flutter candidate');
await processManager.runProcess(CliCommand.tool(['update-flutter-sdk']));
}
if (updatePerfetto) {
logStatus('updating the bundled Perfetto assets');
await processManager.runProcess(CliCommand.tool(['update-perfetto']));
}
logStatus('cleaning project');
if (webBuildDir.existsSync()) {
webBuildDir.deleteSync(recursive: true);
}
await processManager.runProcess(
CliCommand.flutter(['clean']),
workingDirectory: repo.devtoolsAppDirectoryPath,
);
logStatus(
'building DevTools in $buildMode mode with '
'${useWasm ? 'dart2wasm' : 'dart2js'}',
);
await processManager.runAll(
commands: [
if (runPubGet) CliCommand.tool(['pub-get', '--only-main']),
CliCommand.flutter([
'build',
'web',
'--source-maps',
if (useWasm) ...[
SharedCommandArgs.wasm.asArg(),
if (noStripWasm) SharedCommandArgs.noStripWasm.asArg(),
if (noMinifyWasm) SharedCommandArgs.noMinifyWasm.asArg(),
] else ...[
// Do not minify stack traces in debug mode.
if (buildMode == 'debug') '--dart2js-optimization=O1',
if (buildMode != 'debug') '--$buildMode',
],
'--pwa-strategy=offline-first',
'--no-tree-shake-icons',
]),
],
workingDirectory: repo.devtoolsAppDirectoryPath,
);
// TODO(kenz): investigate if we need to perform a windows equivalent of
// `chmod` or if we even need to perform `chmod` for linux / mac anymore.
if (!Platform.isWindows) {
final canvaskitDir = Directory(path.join(webBuildDir.path, 'canvaskit'));
for (final file in canvaskitDir.listSync()) {
if (RegExp(r'canvaskit\..*').hasMatch(file.path)) {
await processManager.runProcess(
CliCommand('chmod', ['0755', file.path]),
);
}
}
}
}
}