Unverified Commit 07b89dad authored by Jackson Gardner's avatar Jackson Gardner Committed by GitHub

Add support to the flutter tool to compile against the skwasm renderer (#124296)

Add support to the flutter tool to compile against the skwasm renderer
parent 8eb1c9d1
...@@ -284,6 +284,11 @@ class Dart2WasmTarget extends Dart2WebTarget { ...@@ -284,6 +284,11 @@ class Dart2WasmTarget extends Dart2WebTarget {
dartSdkRoot, dartSdkRoot,
'--libraries-spec', '--libraries-spec',
artifacts.getHostArtifact(HostArtifact.flutterWebLibrariesJson).path, artifacts.getHostArtifact(HostArtifact.flutterWebLibrariesJson).path,
if (webRenderer == WebRendererMode.skwasm)
...<String>[
'--import-shared-memory',
'--shared-memory-max-pages=32768',
],
'--depfile=${depFile.path}', '--depfile=${depFile.path}',
environment.buildDir.childFile('main.dart').path, // dartfile environment.buildDir.childFile('main.dart').path, // dartfile
...@@ -312,9 +317,6 @@ class Dart2WasmTarget extends Dart2WebTarget { ...@@ -312,9 +317,6 @@ class Dart2WasmTarget extends Dart2WebTarget {
Source.pattern('{OUTPUT_DIR}/main.dart.wasm'), Source.pattern('{OUTPUT_DIR}/main.dart.wasm'),
Source.pattern('{OUTPUT_DIR}/main.dart.mjs'), Source.pattern('{OUTPUT_DIR}/main.dart.mjs'),
]; ];
// TODO(jacksongardner): override `depfiles` once dart2wasm begins producing
// them: https://github.com/dart-lang/sdk/issues/50747
} }
/// Unpacks the dart2js or dart2wasm compilation and resources to a given /// Unpacks the dart2js or dart2wasm compilation and resources to a given
...@@ -461,9 +463,10 @@ class WebReleaseBundle extends Target { ...@@ -461,9 +463,10 @@ class WebReleaseBundle extends Target {
/// These assets can be cached until a new version of the flutter web sdk is /// These assets can be cached until a new version of the flutter web sdk is
/// downloaded. /// downloaded.
class WebBuiltInAssets extends Target { class WebBuiltInAssets extends Target {
const WebBuiltInAssets(this.fileSystem, {required this.isWasm}); const WebBuiltInAssets(this.fileSystem, this.webRenderer, {required this.isWasm});
final FileSystem fileSystem; final FileSystem fileSystem;
final WebRendererMode webRenderer;
final bool isWasm; final bool isWasm;
@override @override
...@@ -511,7 +514,9 @@ class WebBuiltInAssets extends Target { ...@@ -511,7 +514,9 @@ class WebBuiltInAssets extends Target {
if (isWasm) { if (isWasm) {
final File bootstrapFile = environment.outputDir.childFile('main.dart.js'); final File bootstrapFile = environment.outputDir.childFile('main.dart.js');
bootstrapFile.writeAsStringSync(wasm_bootstrap.generateWasmBootstrapFile()); bootstrapFile.writeAsStringSync(
wasm_bootstrap.generateWasmBootstrapFile(webRenderer == WebRendererMode.skwasm)
);
} }
// Write the flutter.js file // Write the flutter.js file
...@@ -538,7 +543,7 @@ class WebServiceWorker extends Target { ...@@ -538,7 +543,7 @@ class WebServiceWorker extends Target {
List<Target> get dependencies => <Target>[ List<Target> get dependencies => <Target>[
if (isWasm) Dart2WasmTarget(webRenderer) else Dart2JSTarget(webRenderer), if (isWasm) Dart2WasmTarget(webRenderer) else Dart2JSTarget(webRenderer),
WebReleaseBundle(webRenderer, isWasm: isWasm), WebReleaseBundle(webRenderer, isWasm: isWasm),
WebBuiltInAssets(fileSystem, isWasm: isWasm), WebBuiltInAssets(fileSystem, webRenderer, isWasm: isWasm),
]; ];
@override @override
......
...@@ -183,6 +183,7 @@ class BuildWebCommand extends BuildSubCommand { ...@@ -183,6 +183,7 @@ class BuildWebCommand extends BuildSubCommand {
displayNullSafetyMode(buildInfo); displayNullSafetyMode(buildInfo);
final WebBuilder webBuilder = WebBuilder( final WebBuilder webBuilder = WebBuilder(
logger: globals.logger, logger: globals.logger,
processManager: globals.processManager,
buildSystem: globals.buildSystem, buildSystem: globals.buildSystem,
fileSystem: globals.fs, fileSystem: globals.fs,
flutterVersion: globals.flutterVersion, flutterVersion: globals.flutterVersion,
......
...@@ -316,6 +316,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). ...@@ -316,6 +316,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
} else { } else {
final WebBuilder webBuilder = WebBuilder( final WebBuilder webBuilder = WebBuilder(
logger: _logger, logger: _logger,
processManager: globals.processManager,
buildSystem: globals.buildSystem, buildSystem: globals.buildSystem,
fileSystem: _fileSystem, fileSystem: _fileSystem,
flutterVersion: globals.flutterVersion, flutterVersion: globals.flutterVersion,
...@@ -393,6 +394,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). ...@@ -393,6 +394,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
try { try {
final WebBuilder webBuilder = WebBuilder( final WebBuilder webBuilder = WebBuilder(
logger: _logger, logger: _logger,
processManager: globals.processManager,
buildSystem: globals.buildSystem, buildSystem: globals.buildSystem,
fileSystem: _fileSystem, fileSystem: _fileSystem,
flutterVersion: globals.flutterVersion, flutterVersion: globals.flutterVersion,
......
...@@ -163,6 +163,7 @@ abstract class FlutterCommand extends Command<void> { ...@@ -163,6 +163,7 @@ abstract class FlutterCommand extends Command<void> {
'auto': WebRendererMode.autoDetect, 'auto': WebRendererMode.autoDetect,
'canvaskit': WebRendererMode.canvaskit, 'canvaskit': WebRendererMode.canvaskit,
'html': WebRendererMode.html, 'html': WebRendererMode.html,
'skwasm': WebRendererMode.skwasm,
}; };
/// The map used to convert web renderer mode to a List of dart-defines. /// The map used to convert web renderer mode to a List of dart-defines.
...@@ -179,6 +180,11 @@ abstract class FlutterCommand extends Command<void> { ...@@ -179,6 +180,11 @@ abstract class FlutterCommand extends Command<void> {
'FLUTTER_WEB_AUTO_DETECT=false', 'FLUTTER_WEB_AUTO_DETECT=false',
'FLUTTER_WEB_USE_SKIA=false', 'FLUTTER_WEB_USE_SKIA=false',
], ],
WebRendererMode.skwasm: <String>[
'FLUTTER_WEB_AUTO_DETECT=false',
'FLUTTER_WEB_USE_SKIA=false',
'FLUTTER_WEB_USE_SKWASM=true',
]
}; };
@override @override
...@@ -663,12 +669,13 @@ abstract class FlutterCommand extends Command<void> { ...@@ -663,12 +669,13 @@ abstract class FlutterCommand extends Command<void> {
argParser.addOption( argParser.addOption(
FlutterOptions.kWebRendererFlag, FlutterOptions.kWebRendererFlag,
defaultsTo: 'auto', defaultsTo: 'auto',
allowed: <String>['auto', 'canvaskit', 'html'], allowed: <String>['auto', 'canvaskit', 'html', 'skwasm'],
help: 'The renderer implementation to use when building for the web.', help: 'The renderer implementation to use when building for the web.',
allowedHelp: <String, String>{ allowedHelp: <String, String>{
'html': 'Always use the HTML renderer. This renderer uses a combination of HTML, CSS, SVG, 2D Canvas, and WebGL.', 'html': 'Always use the HTML renderer. This renderer uses a combination of HTML, CSS, SVG, 2D Canvas, and WebGL.',
'canvaskit': 'Always use the CanvasKit renderer. This renderer uses WebGL and WebAssembly to render graphics.', 'canvaskit': 'Always use the CanvasKit renderer. This renderer uses WebGL and WebAssembly to render graphics.',
'auto': 'Use the HTML renderer on mobile devices, and CanvasKit on desktop devices.', 'auto': 'Use the HTML renderer on mobile devices, and CanvasKit on desktop devices.',
'skwasm': 'Always use the experimental skwasm renderer.',
} }
); );
} }
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:process/process.dart';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
...@@ -26,17 +28,20 @@ export 'compiler_config.dart'; ...@@ -26,17 +28,20 @@ export 'compiler_config.dart';
class WebBuilder { class WebBuilder {
WebBuilder({ WebBuilder({
required Logger logger, required Logger logger,
required ProcessManager processManager,
required BuildSystem buildSystem, required BuildSystem buildSystem,
required Usage usage, required Usage usage,
required FlutterVersion flutterVersion, required FlutterVersion flutterVersion,
required FileSystem fileSystem, required FileSystem fileSystem,
}) : _logger = logger, }) : _logger = logger,
_processManager = processManager,
_buildSystem = buildSystem, _buildSystem = buildSystem,
_flutterUsage = usage, _flutterUsage = usage,
_flutterVersion = flutterVersion, _flutterVersion = flutterVersion,
_fileSystem = fileSystem; _fileSystem = fileSystem;
final Logger _logger; final Logger _logger;
final ProcessManager _processManager;
final BuildSystem _buildSystem; final BuildSystem _buildSystem;
final Usage _flutterUsage; final Usage _flutterUsage;
final FlutterVersion _flutterVersion; final FlutterVersion _flutterVersion;
...@@ -95,7 +100,7 @@ class WebBuilder { ...@@ -95,7 +100,7 @@ class WebBuilder {
artifacts: globals.artifacts!, artifacts: globals.artifacts!,
fileSystem: _fileSystem, fileSystem: _fileSystem,
logger: _logger, logger: _logger,
processManager: globals.processManager, processManager: _processManager,
platform: globals.platform, platform: globals.platform,
usage: _flutterUsage, usage: _flutterUsage,
cacheDir: globals.cache.getRoot(), cacheDir: globals.cache.getRoot(),
...@@ -135,6 +140,8 @@ enum WebRendererMode { ...@@ -135,6 +140,8 @@ enum WebRendererMode {
canvaskit, canvaskit,
/// Always uses html. /// Always uses html.
html, html,
/// Always use skwasm.
skwasm,
} }
/// The correct precompiled artifact to use for each build and render mode. /// The correct precompiled artifact to use for each build and render mode.
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
String generateWasmBootstrapFile() { String generateWasmBootstrapFile(bool isSkwasm) {
return r''' return '''
// Copyright 2014 The Flutter Authors. All rights reserved. // Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -12,20 +12,46 @@ String generateWasmBootstrapFile() { ...@@ -12,20 +12,46 @@ String generateWasmBootstrapFile() {
let dart2wasm_runtime; let dart2wasm_runtime;
let moduleInstance; let moduleInstance;
try { try {
const dartModulePromise = WebAssembly.compileStreaming(fetch("main.dart.wasm")); const dartModulePromise = WebAssembly.compileStreaming(fetch('main.dart.wasm'));
${generateImports(isSkwasm)}
dart2wasm_runtime = await import('./main.dart.mjs'); dart2wasm_runtime = await import('./main.dart.mjs');
moduleInstance = await dart2wasm_runtime.instantiate(dartModulePromise, {}); moduleInstance = await dart2wasm_runtime.instantiate(dartModulePromise, imports);
} catch (exception) { } catch (exception) {
console.error(`Failed to fetch and instantiate wasm module: ${exception}`); console.error(`Failed to fetch and instantiate wasm module: \${exception}`);
} }
if (moduleInstance) { if (moduleInstance) {
try { try {
await dart2wasm_runtime.invoke(moduleInstance); await dart2wasm_runtime.invoke(moduleInstance);
} catch (exception) { } catch (exception) {
console.error(`Exception while invoking test: ${exception}`); console.error(`Exception while invoking test: \${exception}`);
} }
} }
})(); })();
'''; ''';
} }
String generateImports(bool isSkwasm) {
if (isSkwasm) {
return r'''
const imports = new Promise((resolve, reject) => {
const skwasmScript = document.createElement('script');
skwasmScript.src = 'canvaskit/skwasm.js';
document.body.appendChild(skwasmScript);
skwasmScript.addEventListener('load', async () => {
const skwasmInstance = await skwasm();
window._flutter_skwasmInstance = skwasmInstance;
resolve({
'skwasm': skwasmInstance.asm,
'ffi': {
'memory': skwasmInstance.wasmMemory,
}
});
});
});
''';
} else {
return ' const imports = {};';
}
}
...@@ -810,6 +810,40 @@ void main() { ...@@ -810,6 +810,40 @@ void main() {
ProcessManager: () => processManager, ProcessManager: () => processManager,
})); }));
test('Dart2WasmTarget with skwasm renderer adds extra flags', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release';
final File depFile = environment.buildDir.childFile('dart2wasm.d');
processManager.addCommand(FakeCommand(
command: <String>[
'bin/cache/dart-sdk/bin/dartaotruntime',
'--disable-dart-dev',
'bin/cache/dart-sdk/bin/snapshots/dart2wasm_product.snapshot',
'-Ddart.vm.product=true',
'--packages=.dart_tool/package_config.json',
'--dart-sdk=bin/cache/dart-sdk',
'--multi-root-scheme',
'org-dartlang-sdk',
'--multi-root',
'bin/cache/flutter_web_sdk',
'--multi-root',
'bin/cache',
'--libraries-spec',
'bin/cache/flutter_web_sdk/libraries.json',
'--import-shared-memory',
'--shared-memory-max-pages=32768',
'--depfile=${depFile.absolute.path}',
environment.buildDir.childFile('main.dart').absolute.path,
environment.buildDir.childFile('main.dart.wasm').absolute.path,
])
);
await Dart2WasmTarget(WebRendererMode.skwasm).build(environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Generated service worker is empty with none-strategy', () => testbed.run(() { test('Generated service worker is empty with none-strategy', () => testbed.run(() {
final String fileGeneratorsPath = final String fileGeneratorsPath =
environment.artifacts.getArtifactPath(Artifact.flutterToolsFileGenerators); environment.artifacts.getArtifactPath(Artifact.flutterToolsFileGenerators);
...@@ -922,7 +956,7 @@ void main() { ...@@ -922,7 +956,7 @@ void main() {
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync('OL'); ..writeAsStringSync('OL');
await WebBuiltInAssets(globals.fs, isWasm: false).build(environment); await WebBuiltInAssets(globals.fs, WebRendererMode.autoDetect, isWasm: false).build(environment);
// No caching of source maps. // No caching of source maps.
final String fileGeneratorsPath = environment.artifacts final String fileGeneratorsPath = environment.artifacts
...@@ -939,7 +973,7 @@ void main() { ...@@ -939,7 +973,7 @@ void main() {
globals.fs.file('bin/cache/flutter_web_sdk/canvaskit/canvaskit.wasm') globals.fs.file('bin/cache/flutter_web_sdk/canvaskit/canvaskit.wasm')
.createSync(recursive: true); .createSync(recursive: true);
await WebBuiltInAssets(globals.fs, isWasm: true).build(environment); await WebBuiltInAssets(globals.fs, WebRendererMode.autoDetect, isWasm: true).build(environment);
expect(environment.outputDir.childFile('main.dart.js').existsSync(), true); expect(environment.outputDir.childFile('main.dart.js').existsSync(), true);
expect(environment.outputDir.childDirectory('canvaskit') expect(environment.outputDir.childDirectory('canvaskit')
...@@ -952,7 +986,7 @@ void main() { ...@@ -952,7 +986,7 @@ void main() {
..createSync(recursive: true); ..createSync(recursive: true);
canvasKitInput.writeAsStringSync('foo', flush: true); canvasKitInput.writeAsStringSync('foo', flush: true);
await WebBuiltInAssets(globals.fs, isWasm: true).build(environment); await WebBuiltInAssets(globals.fs, WebRendererMode.autoDetect, isWasm: true).build(environment);
final File canvasKitOutputBefore = environment.outputDir.childDirectory('canvaskit') final File canvasKitOutputBefore = environment.outputDir.childDirectory('canvaskit')
.childFile('canvaskit.wasm'); .childFile('canvaskit.wasm');
...@@ -961,7 +995,7 @@ void main() { ...@@ -961,7 +995,7 @@ void main() {
canvasKitInput.writeAsStringSync('bar', flush: true); canvasKitInput.writeAsStringSync('bar', flush: true);
await WebBuiltInAssets(globals.fs, isWasm: true).build(environment); await WebBuiltInAssets(globals.fs, WebRendererMode.autoDetect, isWasm: true).build(environment);
final File canvasKitOutputAfter = environment.outputDir.childDirectory('canvaskit') final File canvasKitOutputAfter = environment.outputDir.childDirectory('canvaskit')
.childFile('canvaskit.wasm'); .childFile('canvaskit.wasm');
......
...@@ -57,6 +57,7 @@ void main() { ...@@ -57,6 +57,7 @@ void main() {
final WebBuilder webBuilder = WebBuilder( final WebBuilder webBuilder = WebBuilder(
logger: logger, logger: logger,
processManager: FakeProcessManager.any(),
buildSystem: buildSystem, buildSystem: buildSystem,
usage: testUsage, usage: testUsage,
flutterVersion: flutterVersion, flutterVersion: flutterVersion,
...@@ -95,6 +96,7 @@ void main() { ...@@ -95,6 +96,7 @@ void main() {
final WebBuilder webBuilder = WebBuilder( final WebBuilder webBuilder = WebBuilder(
logger: logger, logger: logger,
processManager: FakeProcessManager.any(),
buildSystem: buildSystem, buildSystem: buildSystem,
usage: testUsage, usage: testUsage,
flutterVersion: flutterVersion, flutterVersion: flutterVersion,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment