Skip to content

Commit

Permalink
Convert the update_perfetto.sh script to a dart script (flutter#6636)
Browse files Browse the repository at this point in the history
  • Loading branch information
kenzieschmoll authored Nov 1, 2023
1 parent dcdfd9f commit ec4387b
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 167 deletions.
4 changes: 2 additions & 2 deletions packages/devtools_app/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ flutter:
- packages/perfetto_ui_compiled/dist/devtools/devtools_light.css
- packages/perfetto_ui_compiled/dist/devtools/devtools_shared.css
- packages/perfetto_ui_compiled/dist/devtools/devtools_theme_handler.js
# The version number for all the Perfetto asset paths below is updated by running the
# ./tool/update_perfetto.sh script.
# The version number for all the Perfetto asset paths below is updated by running
# `devtools_tool update-perfetto`.
- packages/perfetto_ui_compiled/dist/v33.0-1838a06af/engine_bundle.js
- packages/perfetto_ui_compiled/dist/v33.0-1838a06af/frontend_bundle.js
- packages/perfetto_ui_compiled/dist/v33.0-1838a06af/manifest.json
Expand Down
4 changes: 2 additions & 2 deletions tool/build_e2e.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ const argUpdatePerfetto = '--update-perfetto';
/// Flutter SDK when you already have the proper SDK checked out.
///
/// If [argUpdatePerfetto] is present, the precompiled bits for Perfetto will
/// be updated from the [update_perfetto.sh] script as part of the DevTools
/// build process (e.g. [devtools_tool build-release]).
/// be updated from the `devtools_tool update-perfetto` command as part of the
/// DevTools build process (e.g. running `devtools_tool build-release`).
void main(List<String> args) async {
final shouldUpdatePerfetto = args.contains(argUpdatePerfetto);
final noUpdateFlutter = args.contains(argUseLocalFlutter);
Expand Down
2 changes: 1 addition & 1 deletion tool/build_release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ echo "Flutter Path: $(which flutter)"
echo "Flutter Version: $(flutter --version)"

if [[ $1 = "--update-perfetto" ]]; then
$TOOL_DIR/update_perfetto.sh
devtools_tool update-perfetto
fi

pushd $DEVTOOLS_DIR/packages/devtools_shared
Expand Down
8 changes: 2 additions & 6 deletions tool/lib/commands/build_release.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,8 @@ class BuildReleaseCommand extends Command {
}

if (updatePerfetto) {
logStatus(
'skipping updating the bundled Perfetto assets'
'(https://github.com/flutter/devtools/issues/6324)',
);
// TODO(kenz): call `devtools_tool update-perfetto` once the
// tool/update_perfetto.sh script is converted to a Dart script.
logStatus('updating the bundled Perfetto assets');
await processManager.runProcess(CliCommand.tool('update-perfetto'));
}

logStatus('building DevTools in release mode');
Expand Down
218 changes: 218 additions & 0 deletions tool/lib/commands/update_perfetto.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
// Copyright 2023 The Chromium 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:io';

import 'package:args/command_runner.dart';
import 'package:devtools_tool/model.dart';
import 'package:io/io.dart';
import 'package:path/path.dart' as path;

import '../utils.dart';

const _buildFlag = 'build';

class UpdatePerfettoCommand extends Command {
UpdatePerfettoCommand() {
argParser.addOption(
_buildFlag,
abbr: 'b',
help: 'The build location of the Perfetto assets. When this is not '
'specified, the Perfetto assets will be fetched from the latest '
'source code at "android.googlesource.com".',
valueHelp: '/Users/me/path/to/perfetto/out/ui/ui/dist',
);
}

@override
String get name => 'update-perfetto';

@override
String get description =>
'Updates the Perfetto assets that are included in the DevTools app bundle.';

@override
Future run() async {
final processManager = ProcessManager();

final perfettoUiCompiledLibPath = pathFromRepoRoot(
path.join('third_party', 'packages', 'perfetto_ui_compiled', 'lib'),
);
final perfettoUiCompiledBuildPath =
path.join(perfettoUiCompiledLibPath, 'dist');
final perfettoDevToolsPath =
path.join(perfettoUiCompiledBuildPath, 'devtools');

logStatus(
'moving DevTools-Perfetto integration files to a temp directory.',
);
final tempPerfettoDevTools =
Directory(path.join(Directory.systemTemp.path, 'perfetto_devtools'))
..createSync();
await copyPath(perfettoDevToolsPath, tempPerfettoDevTools.path);

logStatus('deleting existing Perfetto build');
final existingBuild = Directory(perfettoUiCompiledBuildPath);
existingBuild.deleteSync(recursive: true);

logStatus('updating Perfetto build');
final buildLocation = argResults![_buildFlag];
if (buildLocation != null) {
logStatus('using Perfetto build from $buildLocation');
logStatus(
'copying content from $buildLocation to $perfettoUiCompiledLibPath',
);
await copyPath(buildLocation, perfettoUiCompiledBuildPath);
} else {
logStatus('cloning Perfetto from HEAD and building from source');
final tempPerfettoClone =
Directory(path.join(Directory.systemTemp.path, 'perfetto_clone'))
..createSync();
await processManager.runProcess(
CliCommand.git(
'clone https://android.googlesource.com/platform/external/perfetto',
),
workingDirectory: tempPerfettoClone.path,
);

logStatus('installing build deps and building the Perfetto UI');
await processManager.runAll(
commands: [
CliCommand('${path.join('tools', 'install-build-deps')} --ui'),
CliCommand(path.join('ui', 'build')),
],
workingDirectory: path.join(tempPerfettoClone.path, 'perfetto'),
);
final buildOutputPath = path.join(
tempPerfettoClone.path,
'perfetto',
'out',
'ui',
'ui',
'dist',
);
logStatus(
'copying content from $buildOutputPath to $perfettoUiCompiledLibPath',
);
await copyPath(buildOutputPath, perfettoUiCompiledLibPath);

logStatus('deleting perfetto clone');
tempPerfettoClone.deleteSync(recursive: true);
}

logStatus('deleting unnecessary js source map files from build');
final deleteMatchers = [
RegExp(r'\.js\.map'),
RegExp(r'\.css\.map'),
RegExp(r'traceconv\.wasm'),
RegExp(r'traceconv_bundle\.js'),
RegExp(r'catapult_trace_viewer\..*'),
RegExp(r'rec_.*\.png'),
];
final libDirectory = Directory(perfettoUiCompiledLibPath);
final libFiles = libDirectory.listSync(recursive: true);
for (final file in libFiles) {
if (deleteMatchers.any((matcher) => matcher.hasMatch(file.path))) {
logStatus('deleting ${file.path}');
file.deleteSync();
}
}

logStatus(
'moving DevTools-Perfetto integration files back from the temp directory',
);
Directory(perfettoDevToolsPath).createSync(recursive: true);
await copyPath(tempPerfettoDevTools.path, perfettoDevToolsPath);
logStatus('deleting temporary directory');
tempPerfettoDevTools.deleteSync(recursive: true);

_updateIndexFileForDevToolsEmbedding(
path.join(perfettoUiCompiledBuildPath, 'index.html'),
);
_updatePerfettoAssetsInPubspec();
}

void _updateIndexFileForDevToolsEmbedding(String indexFilePath) {
logStatus(
'updating index.html headers to include DevTools-Perfetto integration files',
);
final indexFile = File(indexFilePath);
final fileLines = indexFile.readAsLinesSync();
final fileLinesCopy = <String>[];
for (final line in fileLines) {
if (line == '</head>') {
fileLinesCopy.addAll([
' <link id="devtools-style" rel="stylesheet" href="devtools/devtools_dark.css">',
' <script src="devtools/devtools_theme_handler.js"></script>',
]);
}
fileLinesCopy.add(line);
}
indexFile.writeAsStringSync(fileLinesCopy.joinWithNewLine());
}

void _updatePerfettoAssetsInPubspec() {
logStatus('updating perfetto assets in the devtools_app pubspec.yaml file');
final repo = DevToolsRepo.getInstance();
final perfettoDistDir = Directory(
path.join(
repo.repoPath,
'third_party',
'packages',
'perfetto_ui_compiled',
'lib',
'dist',
),
);

// Find the new perfetto version number.
String newVersionNumber = '';
final versionRegExp = RegExp(r'v\d+[.]\d+-[0-9a-fA-F]+');
final entities = perfettoDistDir.listSync();
for (FileSystemEntity entity in entities) {
final path = entity.path;
final match = versionRegExp.firstMatch(path);
if (match != null) {
newVersionNumber = path.split('/').last;
logStatus('new Perfetto version: $newVersionNumber');
break;
}
}

if (newVersionNumber.isEmpty) {
throw Exception(
'Error updating Perfetto assets: could not find Perfetto version number '
'from entities: ${entities.map((e) => e.path).toList()}',
);
}

final pubspec = File(
path.join(repo.devtoolsAppDirectoryPath, 'pubspec.yaml'),
);

// TODO(kenz): Ensure the pubspec.yaml contains an entry for each file in
// [perfettoDistDir].

final perfettoAssetRegExp = RegExp(
r'(?<prefix>^.*packages\/perfetto_ui_compiled\/dist\/)(?<version>v\d+[.]\d+-[0-9a-fA-F]+)(?<suffix>\/.*$)',
);
final lines = pubspec.readAsLinesSync();
for (int i = 0; i < lines.length; i++) {
final line = lines[i];
final match = perfettoAssetRegExp.firstMatch(line);
if (match != null) {
final prefix = match.namedGroup('prefix')!;
final suffix = match.namedGroup('suffix')!;
lines[i] = '$prefix$newVersionNumber$suffix';
}
}

logStatus(
'updating devtools_app/pubspec.yaml for new Perfetto version'
'$newVersionNumber',
);
final pubspecLinesAsString = '${lines.join('\n')}\n';
pubspec.writeAsStringSync(pubspecLinesAsString);
}
}
6 changes: 0 additions & 6 deletions tool/lib/commands/update_version.dart
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,6 @@ const devToolsDependencyPrefixes = [
'devtools_test: ',
];

extension JoinExtension on List<String> {
String joinWithNewLine() {
return '${join('\n')}\n';
}
}

class ManualUpdateCommand extends Command {
ManualUpdateCommand() {
argParser
Expand Down
2 changes: 2 additions & 0 deletions tool/lib/devtools_command_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:devtools_tool/commands/fix_goldens.dart';
import 'package:devtools_tool/commands/generate_code.dart';
import 'package:devtools_tool/commands/sync.dart';
import 'package:devtools_tool/commands/update_flutter_sdk.dart';
import 'package:devtools_tool/commands/update_perfetto.dart';

import 'commands/analyze.dart';
import 'commands/list.dart';
Expand All @@ -34,5 +35,6 @@ class DevToolsCommandRunner extends CommandRunner {
addCommand(UpdateDartSdkDepsCommand());
addCommand(UpdateDevToolsVersionCommand());
addCommand(UpdateFlutterSdkCommand());
addCommand(UpdatePerfettoCommand());
}
}
6 changes: 6 additions & 0 deletions tool/lib/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,9 @@ extension CommandExtension on Command {
print('[$name] $log');
}
}

extension JoinExtension on List<String> {
String joinWithNewLine() {
return '${join('\n')}\n';
}
}
77 changes: 0 additions & 77 deletions tool/update_perfetto.sh

This file was deleted.

Loading

0 comments on commit ec4387b

Please sign in to comment.