From 5b4320e30eba92ac608ff5ad04920127895686ef Mon Sep 17 00:00:00 2001 From: Kevin Chisholm Date: Mon, 27 Mar 2023 23:49:13 -0500 Subject: [PATCH] Revert "Reland "Default the CanvasKit base URL to local artifacts. (#40293)" (#40470)" (#40700) Revert "Reland "Default the CanvasKit base URL to local artifacts."" --- lib/web_ui/README.md | 28 +++ lib/web_ui/dev/canvaskit_lock.yaml | 4 + lib/web_ui/dev/canvaskit_roller.dart | 169 +++++++++++++++++++ lib/web_ui/lib/src/engine/configuration.dart | 7 +- 4 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 lib/web_ui/dev/canvaskit_lock.yaml create mode 100644 lib/web_ui/dev/canvaskit_roller.dart diff --git a/lib/web_ui/README.md b/lib/web_ui/README.md index 5c19ffdaade14..f1e11e92f9a01 100644 --- a/lib/web_ui/README.md +++ b/lib/web_ui/README.md @@ -197,6 +197,34 @@ Resources: 2. LUCI web [recipe][5] 3. More general reading on CIPD packages [link][6] +### Rolling CanvasKit + +CanvasKit is versioned separately from Skia and rolled manually. Flutter +consumes a pre-built CanvasKit provided by the Skia team, currently hosted on +unpkg.com. When a new version of CanvasKit is available (check +https://www.npmjs.com/package/canvaskit-wasm or consult the Skia team +directly), follow these steps to roll to the new version: + +- Make sure you have `depot_tools` installed (if you are regularly hacking on + the engine code, you probably do). +- If not already authenticated with CIPD, run `cipd auth-login` and follow + instructions (this step requires sufficient privileges; file a github + infra ticket queue issue: https://github.com/flutter/flutter/wiki/Infra-Ticket-Queue + to get access) +- Edit `dev/canvaskit_lock.yaml` and update the value of `canvaskit_version` + to the new version. +- Run `dart dev/canvaskit_roller.dart` and make sure it completes successfully. + The script uploads the new version of CanvasKit to the + `flutter/web/canvaskit_bundle` CIPD package, and writes the CIPD package + instance ID to the DEPS file. +- Rerun `gclient sync` and do a clean build to test that the new version is + picked up. +- Send a pull request containing the above file changes. If the new version + contains breaking changes, the PR must also contain corresponding fixes. + +If you have questions, contact the Flutter Web team on Flutter Discord on the +#hackers-web-🌍 channel. + ### Rolling Noto Font Data In order to generate new data for the Noto fallback fonts, you will need diff --git a/lib/web_ui/dev/canvaskit_lock.yaml b/lib/web_ui/dev/canvaskit_lock.yaml new file mode 100644 index 0000000000000..ab4826af1a057 --- /dev/null +++ b/lib/web_ui/dev/canvaskit_lock.yaml @@ -0,0 +1,4 @@ +# Specifies the version of CanvasKit to use for Flutter Web apps. +# +# See `lib/web_ui/README.md` for how to update this file. +canvaskit_version: "0.38.0" diff --git a/lib/web_ui/dev/canvaskit_roller.dart b/lib/web_ui/dev/canvaskit_roller.dart new file mode 100644 index 0000000000000..44b4de43f9d61 --- /dev/null +++ b/lib/web_ui/dev/canvaskit_roller.dart @@ -0,0 +1,169 @@ +// 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 'dart:convert' show json; +import 'dart:io'; + +import 'package:path/path.dart' as pathlib; +import 'package:yaml/yaml.dart'; + +import 'environment.dart'; +import 'utils.dart'; + +/// Rolls CanvasKit to the version specified in `dev/canvaskit_lock.yaml`. +/// +/// Detailed instructions for how to use this script can be found in +/// `lib/web_ui/README.md`. +Future main(List args) async { + final String canvaskitVersion = _readCanvaskitVersion(); + print('Rolling CanvasKit to version $canvaskitVersion'); + + final Directory canvaskitDirectory = await Directory.systemTemp.createTemp('canvaskit-roll-$canvaskitVersion-'); + print('Will use ${canvaskitDirectory.path} as staging directory.'); + + final String baseUrl = 'https://unpkg.com/canvaskit-wasm@$canvaskitVersion/bin/'; + print('Downloading CanvasKit from $baseUrl'); + final HttpClient client = HttpClient(); + for (final String assetPath in _canvaskitAssets) { + final String assetUrl = '$baseUrl/$assetPath'; + final File assetFile = File(pathlib.joinAll([ + canvaskitDirectory.path, + 'canvaskit', + ...assetPath.split('/'), // so it's compatible with Windows + ])); + await assetFile.parent.create(recursive: true); + final HttpClientRequest request = await client.getUrl(Uri.parse(assetUrl)); + final HttpClientResponse response = await request.close(); + final IOSink fileSink = assetFile.openWrite(); + await response.pipe(fileSink); + } + client.close(); + + final File cipdConfigFile = File(pathlib.join( + canvaskitDirectory.path, + 'cipd.yaml', + )); + await cipdConfigFile.writeAsString(''' +package: flutter/web/canvaskit_bundle +description: A build of CanvasKit bundled with Flutter Web apps +preserve_writable: true +data: + - dir: canvaskit +'''); + + print('Uploading to CIPD'); + await runProcess('cipd', [ + 'create', + '--tag=version:$canvaskitVersion', + '--pkg-def=cipd.yaml', + '--json-output=result.json', + ], workingDirectory: canvaskitDirectory.path); + + final Map cipdResult = json.decode(File(pathlib.join( + canvaskitDirectory.path, + 'result.json', + )).readAsStringSync()) as Map; + final String cipdInstanceId = (cipdResult['result'] as Map)['instance_id'] as String; + + print('CIPD instance information:'); + final String cipdInfo = await evalProcess('cipd', [ + 'describe', + 'flutter/web/canvaskit_bundle', + '--version=$cipdInstanceId', + ], workingDirectory: canvaskitDirectory.path); + print(cipdInfo.trim().split('\n').map((String line) => ' • $line').join('\n')); + + print('Updating DEPS file'); + await _updateDepsFile(cipdInstanceId); + await _updateCanvaskitInitializationCode(canvaskitVersion); + + print('\nATTENTION: the roll process is not complete yet.'); + print('Last step: for the roll to take effect submit an engine pull request from local git changes.'); +} + +const List _canvaskitAssets = [ + 'canvaskit.js', + 'canvaskit.wasm', + 'profiling/canvaskit.js', + 'profiling/canvaskit.wasm', +]; + +String _readCanvaskitVersion() { + final YamlMap canvaskitLock = loadYaml(File(pathlib.join( + environment.webUiDevDir.path, + 'canvaskit_lock.yaml', + )).readAsStringSync()) as YamlMap; + return canvaskitLock['canvaskit_version'] as String; +} + +Future _updateDepsFile(String cipdInstanceId) async { + final File depsFile = File(pathlib.join( + environment.flutterDirectory.path, + 'DEPS', + )); + + final String originalDepsCode = await depsFile.readAsString(); + final List rewrittenDepsCode = []; + const String kCanvasKitDependencyKeyInDeps = "'canvaskit_cipd_instance': '"; + bool canvaskitDependencyFound = false; + for (final String line in originalDepsCode.split('\n')) { + if (line.trim().startsWith(kCanvasKitDependencyKeyInDeps)) { + canvaskitDependencyFound = true; + rewrittenDepsCode.add( + " 'canvaskit_cipd_instance': '$cipdInstanceId',", + ); + } else { + rewrittenDepsCode.add(line); + } + } + + if (!canvaskitDependencyFound) { + stderr.writeln( + 'Failed to update the DEPS file.\n' + 'Could not to locate CanvasKit dependency in the DEPS file. Make sure the ' + 'DEPS file contains a line like this:\n' + '\n' + " 'canvaskit_cipd_instance': 'SOME_VALUE'," + ); + exit(1); + } + + await depsFile.writeAsString(rewrittenDepsCode.join('\n')); +} + +Future _updateCanvaskitInitializationCode(String canvaskitVersion) async { + const String kCanvasKitVersionKey = 'const String _canvaskitVersion'; + const String kPathToConfigurationCode = 'lib/src/engine/configuration.dart'; + final File initializationFile = File(pathlib.join( + environment.webUiRootDir.path, + kPathToConfigurationCode, + )); + final String originalInitializationCode = await initializationFile.readAsString(); + + final List rewrittenCode = []; + bool canvaskitVersionFound = false; + for (final String line in originalInitializationCode.split('\n')) { + if (line.trim().startsWith(kCanvasKitVersionKey)) { + canvaskitVersionFound = true; + rewrittenCode.add( + "const String _canvaskitVersion = '$canvaskitVersion';", + ); + } else { + rewrittenCode.add(line); + } + } + + if (!canvaskitVersionFound) { + stderr.writeln( + 'Failed to update CanvasKit version in $kPathToConfigurationCode.\n' + 'Could not to locate the constant that defines the version. Make sure the ' + '$kPathToConfigurationCode file contains a line like this:\n' + '\n' + "const String _canvaskitVersion = 'VERSION';" + ); + exit(1); + } + + await initializationFile.writeAsString(rewrittenCode.join('\n')); +} diff --git a/lib/web_ui/lib/src/engine/configuration.dart b/lib/web_ui/lib/src/engine/configuration.dart index 5e2d2b24b8764..71944deff9eee 100644 --- a/lib/web_ui/lib/src/engine/configuration.dart +++ b/lib/web_ui/lib/src/engine/configuration.dart @@ -50,6 +50,11 @@ import 'package:meta/meta.dart'; import 'canvaskit/renderer.dart'; import 'dom.dart'; +/// The version of CanvasKit used by the web engine by default. +// DO NOT EDIT THE NEXT LINE OF CODE MANUALLY +// See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. +const String _canvaskitVersion = '0.38.0'; + /// The Web Engine configuration for the current application. FlutterConfiguration get configuration => _configuration ??= FlutterConfiguration.legacy(_jsConfiguration); @@ -178,7 +183,7 @@ class FlutterConfiguration { String get canvasKitBaseUrl => _configuration?.canvasKitBaseUrl ?? _defaultCanvasKitBaseUrl; static const String _defaultCanvasKitBaseUrl = String.fromEnvironment( 'FLUTTER_WEB_CANVASKIT_URL', - defaultValue: 'canvaskit/', + defaultValue: 'https://unpkg.com/canvaskit-wasm@$_canvaskitVersion/bin/', ); /// The variant of CanvasKit to download.