Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert the update_perfetto.sh script to a dart script #6636

Merged
merged 11 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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