Unverified Commit 529b919f authored by Kevin Moore's avatar Kevin Moore Committed by GitHub

tool-web-wasm: make wasm-opt an "option" instead of a "flag" (#126035)

Allows controlling a broader set of variables than just on/off.

Also make wasm-opt "full" the default
parent 5a80f8d6
...@@ -294,14 +294,16 @@ class Dart2WasmTarget extends Dart2WebTarget { ...@@ -294,14 +294,16 @@ class Dart2WasmTarget extends Dart2WebTarget {
final File optimizedOutput = environment.buildDir.childFile('main.dart.wasm'); final File optimizedOutput = environment.buildDir.childFile('main.dart.wasm');
final List<String> optimizeArgs = <String>[ final List<String> optimizeArgs = <String>[
wasmOptBinary, wasmOptBinary,
'-all', '--all-features',
'--closed-world', '--closed-world',
'-tnh', '--traps-never-happen',
'-O3', '-O3',
'--type-ssa', '--type-ssa',
'--gufa', '--gufa',
'-O3', '-O3',
'--type-merging', '--type-merging',
if (compilerConfig.wasmOpt == WasmOptLevel.debug)
'--debuginfo',
outputWasmFile.path, outputWasmFile.path,
'-o', '-o',
optimizedOutput.path, optimizedOutput.path,
......
...@@ -103,12 +103,13 @@ class BuildWebCommand extends BuildSubCommand { ...@@ -103,12 +103,13 @@ class BuildWebCommand extends BuildSubCommand {
negatable: false, negatable: false,
hide: !featureFlags.isFlutterWebWasmEnabled, hide: !featureFlags.isFlutterWebWasmEnabled,
); );
argParser.addFlag( argParser.addOption(
'wasm-opt', 'wasm-opt',
help: help:
'Optimize output wasm using the Binaryen (https://github.com/WebAssembly/binaryen) tool.\n' 'Optimize output wasm using the Binaryen (https://github.com/WebAssembly/binaryen) tool.',
'Increases the build time, but will yield a smaller, faster output.', defaultsTo: WasmOptLevel.defaultValue.cliName,
negatable: false, allowed: WasmOptLevel.values.map<String>((WasmOptLevel e) => e.cliName),
allowedHelp: CliEnum.allowedHelp(WasmOptLevel.values),
hide: !featureFlags.isFlutterWebWasmEnabled, hide: !featureFlags.isFlutterWebWasmEnabled,
); );
} }
...@@ -143,7 +144,7 @@ class BuildWebCommand extends BuildSubCommand { ...@@ -143,7 +144,7 @@ class BuildWebCommand extends BuildSubCommand {
} }
compilerConfig = WasmCompilerConfig( compilerConfig = WasmCompilerConfig(
omitTypeChecks: boolArg('omit-type-checks'), omitTypeChecks: boolArg('omit-type-checks'),
runWasmOpt: boolArg('wasm-opt'), wasmOpt: WasmOptLevel.values.byName(stringArg('wasm-opt')!),
); );
} else { } else {
compilerConfig = JsCompilerConfig( compilerConfig = JsCompilerConfig(
......
...@@ -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 '../base/utils.dart';
abstract class WebCompilerConfig { abstract class WebCompilerConfig {
const WebCompilerConfig(); const WebCompilerConfig();
...@@ -134,7 +136,7 @@ class JsCompilerConfig extends WebCompilerConfig { ...@@ -134,7 +136,7 @@ class JsCompilerConfig extends WebCompilerConfig {
class WasmCompilerConfig extends WebCompilerConfig { class WasmCompilerConfig extends WebCompilerConfig {
const WasmCompilerConfig({ const WasmCompilerConfig({
required this.omitTypeChecks, required this.omitTypeChecks,
required this.runWasmOpt, required this.wasmOpt,
}); });
/// Creates a new [WasmCompilerConfig] from build system environment values. /// Creates a new [WasmCompilerConfig] from build system environment values.
...@@ -144,28 +146,30 @@ class WasmCompilerConfig extends WebCompilerConfig { ...@@ -144,28 +146,30 @@ class WasmCompilerConfig extends WebCompilerConfig {
Map<String, String> defines) => Map<String, String> defines) =>
WasmCompilerConfig( WasmCompilerConfig(
omitTypeChecks: defines[kOmitTypeChecks] == 'true', omitTypeChecks: defines[kOmitTypeChecks] == 'true',
runWasmOpt: defines[kRunWasmOpt] == 'true', wasmOpt: WasmOptLevel.values.byName(defines[kRunWasmOpt]!),
); );
/// Build environment for [omitTypeChecks]. /// Build environment for [omitTypeChecks].
static const String kOmitTypeChecks = 'WasmOmitTypeChecks'; static const String kOmitTypeChecks = 'WasmOmitTypeChecks';
/// Build environment for [runWasmOpt]. /// Build environment for [wasmOpt].
static const String kRunWasmOpt = 'RunWasmOpt'; static const String kRunWasmOpt = 'RunWasmOpt';
/// If `omit-type-checks` should be passed to `dart2wasm`. /// If `omit-type-checks` should be passed to `dart2wasm`.
final bool omitTypeChecks; final bool omitTypeChecks;
/// Run wasm-opt on the resulting module. /// Run wasm-opt on the resulting module.
final bool runWasmOpt; final WasmOptLevel wasmOpt;
@override @override
bool get isWasm => true; bool get isWasm => true;
bool get runWasmOpt => wasmOpt == WasmOptLevel.full || wasmOpt == WasmOptLevel.debug;
@override @override
Map<String, String> toBuildSystemEnvironment() => <String, String>{ Map<String, String> toBuildSystemEnvironment() => <String, String>{
kOmitTypeChecks: omitTypeChecks.toString(), kOmitTypeChecks: omitTypeChecks.toString(),
kRunWasmOpt: runWasmOpt.toString(), kRunWasmOpt: wasmOpt.name,
}; };
List<String> toCommandOptions() => <String>[ List<String> toCommandOptions() => <String>[
...@@ -182,3 +186,21 @@ class WasmCompilerConfig extends WebCompilerConfig { ...@@ -182,3 +186,21 @@ class WasmCompilerConfig extends WebCompilerConfig {
entry.key: entry.value, entry.key: entry.value,
}; };
} }
enum WasmOptLevel implements CliEnum {
full,
debug,
none;
static const WasmOptLevel defaultValue = WasmOptLevel.full;
@override
String get cliName => name;
@override
String get helpText => switch(this) {
WasmOptLevel.none => 'wasm-opt is not run. Fastest build; bigger, slower output.',
WasmOptLevel.debug => 'Similar to `${WasmOptLevel.full.name}, but member names are preserved. Debugging is easier, but size is a bit bigger.',
WasmOptLevel.full => 'wasm-opt is run. Build time is slower, but output is smaller and faster.',
};
}
...@@ -24,7 +24,7 @@ import '../../../src/testbed.dart'; ...@@ -24,7 +24,7 @@ import '../../../src/testbed.dart';
const List<String> _kDart2jsLinuxArgs = <String>[ const List<String> _kDart2jsLinuxArgs = <String>[
'Artifact.engineDartBinary.TargetPlatform.web_javascript', 'Artifact.engineDartBinary.TargetPlatform.web_javascript',
'--disable-dart-dev', '--disable-dart-dev',
'Artifact.dart2jsSnapshot.TargetPlatform.web_javascript', 'Artifact.dart2jsSnapshot.TargetPlatform.web_javascript',
'--platform-binaries=HostArtifact.webPlatformKernelFolder', '--platform-binaries=HostArtifact.webPlatformKernelFolder',
'--invoker=flutter_tool', '--invoker=flutter_tool',
...@@ -46,6 +46,18 @@ const List<String> _kDart2WasmLinuxArgs = <String> [ ...@@ -46,6 +46,18 @@ const List<String> _kDart2WasmLinuxArgs = <String> [
'HostArtifact.flutterWebLibrariesJson', 'HostArtifact.flutterWebLibrariesJson',
]; ];
const List<String> _kWasmOptLinuxArgrs = <String> [
'Artifact.wasmOptBinary.TargetPlatform.web_javascript',
'--all-features',
'--closed-world',
'--traps-never-happen',
'-O3',
'--type-ssa',
'--gufa',
'-O3',
'--type-merging',
];
/// The result of calling `.parent` on a Memory directory pointing to /// The result of calling `.parent` on a Memory directory pointing to
/// `'Artifact.engineDartSdkPath.TargetPlatform.web_javascript'`. /// `'Artifact.engineDartSdkPath.TargetPlatform.web_javascript'`.
const String _kDartSdkRoot = '.'; const String _kDartSdkRoot = '.';
...@@ -759,10 +771,12 @@ void main() { ...@@ -759,10 +771,12 @@ void main() {
test('Dart2WasmTarget invokes dart2wasm with dart defines', () => testbed.run(() async { test('Dart2WasmTarget invokes dart2wasm with dart defines', () => testbed.run(() async {
environment.defines[kBuildMode] = 'profile'; environment.defines[kBuildMode] = 'profile';
environment.defines[WasmCompilerConfig.kRunWasmOpt] = WasmOptLevel.defaultValue.name;
environment.defines[kDartDefines] = encodeDartDefines(<String>['FOO=bar', 'BAZ=qux']); environment.defines[kDartDefines] = encodeDartDefines(<String>['FOO=bar', 'BAZ=qux']);
final File depFile = environment.buildDir.childFile('dart2wasm.d'); final File depFile = environment.buildDir.childFile('dart2wasm.d');
final File outputJsFile = environment.buildDir.childFile('main.dart.unopt.mjs');
processManager.addCommand(FakeCommand( processManager.addCommand(FakeCommand(
command: <String>[ command: <String>[
..._kDart2WasmLinuxArgs, ..._kDart2WasmLinuxArgs,
...@@ -771,21 +785,38 @@ void main() { ...@@ -771,21 +785,38 @@ void main() {
'-DBAZ=qux', '-DBAZ=qux',
'--depfile=${depFile.absolute.path}', '--depfile=${depFile.absolute.path}',
environment.buildDir.childFile('main.dart').absolute.path, environment.buildDir.childFile('main.dart').absolute.path,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
],
onRun: () => outputJsFile..createSync()..writeAsStringSync('foo'))
);
processManager.addCommand(FakeCommand(
command: <String>[
..._kWasmOptLinuxArgrs,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path, environment.buildDir.childFile('main.dart.wasm').absolute.path,
]) ])
); );
await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment); await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment);
expect(outputJsFile.existsSync(), isFalse);
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
expect(movedJsFile.existsSync(), isTrue);
expect(movedJsFile.readAsStringSync(), 'foo');
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
ProcessManager: () => processManager, ProcessManager: () => processManager,
})); }));
test('Dart2WasmTarget invokes dart2wasm with omit checks', () => testbed.run(() async { test('Dart2WasmTarget invokes dart2wasm with omit checks', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release'; environment.defines[kBuildMode] = 'release';
environment.defines[WasmCompilerConfig.kRunWasmOpt] = WasmOptLevel.defaultValue.name;
environment.defines[WasmCompilerConfig.kOmitTypeChecks] = 'true'; environment.defines[WasmCompilerConfig.kOmitTypeChecks] = 'true';
final File depFile = environment.buildDir.childFile('dart2wasm.d'); final File depFile = environment.buildDir.childFile('dart2wasm.d');
final File outputJsFile = environment.buildDir.childFile('main.dart.unopt.mjs');
processManager.addCommand(FakeCommand( processManager.addCommand(FakeCommand(
command: <String>[ command: <String>[
..._kDart2WasmLinuxArgs, ..._kDart2WasmLinuxArgs,
...@@ -793,18 +824,33 @@ void main() { ...@@ -793,18 +824,33 @@ void main() {
'--omit-type-checks', '--omit-type-checks',
'--depfile=${depFile.absolute.path}', '--depfile=${depFile.absolute.path}',
environment.buildDir.childFile('main.dart').absolute.path, environment.buildDir.childFile('main.dart').absolute.path,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
],
onRun: () => outputJsFile..createSync()..writeAsStringSync('foo'))
);
processManager.addCommand(FakeCommand(
command: <String>[
..._kWasmOptLinuxArgrs,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path, environment.buildDir.childFile('main.dart.wasm').absolute.path,
]) ])
); );
await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment); await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment);
expect(outputJsFile.existsSync(), isFalse);
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
expect(movedJsFile.existsSync(), isTrue);
expect(movedJsFile.readAsStringSync(), 'foo');
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
ProcessManager: () => processManager, ProcessManager: () => processManager,
})); }));
test('Dart2WasmTarget invokes dart2wasm and wasm-opt when RunWasmOpt is enabled', () => testbed.run(() async { test('Dart2WasmTarget invokes dart2wasm and wasm-opt with debug info in wasmopt debug mode', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release'; environment.defines[kBuildMode] = 'release';
environment.defines[WasmCompilerConfig.kRunWasmOpt] = 'true'; environment.defines[WasmCompilerConfig.kRunWasmOpt] = WasmOptLevel.debug.name;
final File depFile = environment.buildDir.childFile('dart2wasm.d'); final File depFile = environment.buildDir.childFile('dart2wasm.d');
...@@ -820,15 +866,8 @@ void main() { ...@@ -820,15 +866,8 @@ void main() {
processManager.addCommand(FakeCommand( processManager.addCommand(FakeCommand(
command: <String>[ command: <String>[
'Artifact.wasmOptBinary.TargetPlatform.web_javascript', ..._kWasmOptLinuxArgrs,
'-all', '--debuginfo',
'--closed-world',
'-tnh',
'-O3',
'--type-ssa',
'--gufa',
'-O3',
'--type-merging',
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path, environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
'-o', '-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path, environment.buildDir.childFile('main.dart.wasm').absolute.path,
...@@ -844,11 +883,33 @@ void main() { ...@@ -844,11 +883,33 @@ void main() {
ProcessManager: () => processManager, ProcessManager: () => processManager,
})); }));
test('Dart2WasmTarget invokes dart2wasm (but not wasm-opt) with wasm-opt none option', () => testbed.run(() async {
environment.defines[kBuildMode] = 'debug';
environment.defines[WasmCompilerConfig.kRunWasmOpt] = WasmOptLevel.none.name;
final File depFile = environment.buildDir.childFile('dart2wasm.d');
final File outputJsFile = environment.buildDir.childFile('main.dart.mjs');
processManager.addCommand(FakeCommand(
command: <String>[
..._kDart2WasmLinuxArgs,
'-Ddart.vm.product=true',
'--depfile=${depFile.absolute.path}',
environment.buildDir.childFile('main.dart').absolute.path,
environment.buildDir.childFile('main.dart.wasm').absolute.path,
], onRun: () => outputJsFile..createSync()..writeAsStringSync('foo')));
await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
test('Dart2WasmTarget with skwasm renderer adds extra flags', () => testbed.run(() async { test('Dart2WasmTarget with skwasm renderer adds extra flags', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release'; environment.defines[kBuildMode] = 'release';
environment.defines[WasmCompilerConfig.kRunWasmOpt] = WasmOptLevel.defaultValue.name;
final File depFile = environment.buildDir.childFile('dart2wasm.d'); final File depFile = environment.buildDir.childFile('dart2wasm.d');
final File outputJsFile = environment.buildDir.childFile('main.dart.unopt.mjs');
processManager.addCommand(FakeCommand( processManager.addCommand(FakeCommand(
command: <String>[ command: <String>[
..._kDart2WasmLinuxArgs, ..._kDart2WasmLinuxArgs,
...@@ -857,6 +918,16 @@ void main() { ...@@ -857,6 +918,16 @@ void main() {
'--shared-memory-max-pages=32768', '--shared-memory-max-pages=32768',
'--depfile=${depFile.absolute.path}', '--depfile=${depFile.absolute.path}',
environment.buildDir.childFile('main.dart').absolute.path, environment.buildDir.childFile('main.dart').absolute.path,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
],
onRun: () => outputJsFile..createSync()..writeAsStringSync('foo'))
);
processManager.addCommand(FakeCommand(
command: <String>[
..._kWasmOptLinuxArgrs,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path, environment.buildDir.childFile('main.dart.wasm').absolute.path,
]) ])
); );
......
...@@ -47,7 +47,7 @@ void main() { ...@@ -47,7 +47,7 @@ void main() {
'HasWebPlugins': 'false', 'HasWebPlugins': 'false',
'ServiceWorkerStrategy': ServiceWorkerStrategy.offlineFirst.cliName, 'ServiceWorkerStrategy': ServiceWorkerStrategy.offlineFirst.cliName,
'WasmOmitTypeChecks': 'false', 'WasmOmitTypeChecks': 'false',
'RunWasmOpt': 'false', 'RunWasmOpt': 'none',
'BuildMode': 'debug', 'BuildMode': 'debug',
'DartObfuscation': 'false', 'DartObfuscation': 'false',
'TrackWidgetCreation': 'true', 'TrackWidgetCreation': 'true',
...@@ -73,7 +73,7 @@ void main() { ...@@ -73,7 +73,7 @@ void main() {
ServiceWorkerStrategy.offlineFirst, ServiceWorkerStrategy.offlineFirst,
compilerConfig: const WasmCompilerConfig( compilerConfig: const WasmCompilerConfig(
omitTypeChecks: false, omitTypeChecks: false,
runWasmOpt: false wasmOpt: WasmOptLevel.none,
), ),
); );
......
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