Skip to content

Commit abadf9f

Browse files
authored
Use dart compile wasm for wasm compilations (#143298)
* Flags to `dart compile wasm` Some options are not relevant to a standalone user of `dart compile wasm` (e.g. specyfing dart-sdk, platform file etc). => Those aren't offered by the `dart compile wasm` tool directly. => We use the `--extra-compiler-option=` instead which passes through arbitrary options to the dart2wasm compiler. => We don't maintain compatibility of those options, if we update them we'll ensure to also update flutter tools * Binaryen optimization passes This change will mean we use the binaryen flags from Dart SDK which are slightly different from the ones in flutter. * Optimization configuration This change will also start using the more standardized `-O` flag for determining optimization levels. The meaning of those flags have been mostly aligned with dart2js (with some differences remaining). * Minimization Using the new optimization flags, namely `-O4` for `--wasm-opt=full`, will automatically enable the new `--minify` support. Minification is Dart semantics preserving but changes the `<obj>.runtimeType.toString()` to use minified names (just as in dart2js). * Code size changes Overall this change will reduce wonderous code size by around 10%. Issue dart-lang/sdk#54675
1 parent 295eeaf commit abadf9f

File tree

3 files changed

+70
-134
lines changed

3 files changed

+70
-134
lines changed

packages/flutter_tools/lib/src/build_system/targets/web.dart

Lines changed: 15 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,8 @@ class Dart2WasmTarget extends Dart2WebTarget {
249249
}
250250
final BuildMode buildMode = BuildMode.fromCliName(buildModeEnvironment);
251251
final Artifacts artifacts = environment.artifacts;
252-
final File outputWasmFile = environment.buildDir.childFile(
253-
compilerConfig.runWasmOpt ? 'main.dart.unopt.wasm' : 'main.dart.wasm'
254-
);
252+
final File outputWasmFile =
253+
environment.buildDir.childFile('main.dart.wasm');
255254
final File depFile = environment.buildDir.childFile('dart2wasm.d');
256255
final String dartSdkPath = artifacts.getArtifactPath(Artifact.engineDartSdkPath, platform: TargetPlatform.web_javascript);
257256
final String platformBinariesPath = artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path;
@@ -261,29 +260,29 @@ class Dart2WasmTarget extends Dart2WebTarget {
261260
);
262261

263262
final List<String> compilationArgs = <String>[
264-
artifacts.getArtifactPath(Artifact.engineDartAotRuntime, platform: TargetPlatform.web_javascript),
265-
'--disable-dart-dev',
266-
artifacts.getArtifactPath(Artifact.dart2wasmSnapshot, platform: TargetPlatform.web_javascript),
263+
artifacts.getArtifactPath(Artifact.engineDartBinary, platform: TargetPlatform.web_javascript),
264+
'compile',
265+
'wasm',
267266
'--packages=.dart_tool/package_config.json',
268-
'--dart-sdk=$dartSdkPath',
269-
'--platform=$platformFilePath',
267+
'--extra-compiler-option=--dart-sdk=$dartSdkPath',
268+
'--extra-compiler-option=--platform=$platformFilePath',
269+
if (compilerConfig.renderer == WebRendererMode.skwasm) ...<String>[
270+
'--extra-compiler-option=--import-shared-memory',
271+
'--extra-compiler-option=--shared-memory-max-pages=32768',
272+
],
270273
if (buildMode == BuildMode.profile)
271274
'-Ddart.vm.profile=true'
272275
else
273276
'-Ddart.vm.product=true',
274277
...decodeCommaSeparated(environment.defines, kExtraFrontEndOptions),
275278
for (final String dartDefine in dartDefines)
276279
'-D$dartDefine',
277-
...compilerConfig.toCommandOptions(),
278-
if (compilerConfig.renderer == WebRendererMode.skwasm)
279-
...<String>[
280-
'--import-shared-memory',
281-
'--shared-memory-max-pages=32768',
282-
],
283-
'--depfile=${depFile.path}',
280+
'--extra-compiler-option=--depfile=${depFile.path}',
284281

285-
environment.buildDir.childFile('main.dart').path, // dartfile
282+
...compilerConfig.toCommandOptions(),
283+
'-o',
286284
outputWasmFile.path,
285+
environment.buildDir.childFile('main.dart').path, // dartfile
287286
];
288287

289288
final ProcessUtils processUtils = ProcessUtils(
@@ -295,37 +294,6 @@ class Dart2WasmTarget extends Dart2WebTarget {
295294
throwOnError: true,
296295
compilationArgs,
297296
);
298-
if (compilerConfig.runWasmOpt) {
299-
final String wasmOptBinary = artifacts.getArtifactPath(
300-
Artifact.wasmOptBinary,
301-
platform: TargetPlatform.web_javascript
302-
);
303-
final File optimizedOutput = environment.buildDir.childFile('main.dart.wasm');
304-
final List<String> optimizeArgs = <String>[
305-
wasmOptBinary,
306-
'--all-features',
307-
'--closed-world',
308-
'--traps-never-happen',
309-
'-O3',
310-
'--type-ssa',
311-
'--gufa',
312-
'-O3',
313-
'--type-merging',
314-
if (compilerConfig.wasmOpt == WasmOptLevel.debug)
315-
'--debuginfo',
316-
outputWasmFile.path,
317-
'-o',
318-
optimizedOutput.path,
319-
];
320-
await processUtils.run(
321-
throwOnError: true,
322-
optimizeArgs,
323-
);
324-
325-
// Rename the .mjs file not to have the `.unopt` bit
326-
final File jsRuntimeFile = environment.buildDir.childFile('main.dart.unopt.mjs');
327-
await jsRuntimeFile.rename(environment.buildDir.childFile('main.dart.mjs').path);
328-
}
329297
}
330298

331299
@override

packages/flutter_tools/lib/src/web/compiler_config.dart

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,23 @@ class WasmCompilerConfig extends WebCompilerConfig {
148148
@override
149149
CompileTarget get compileTarget => CompileTarget.wasm;
150150

151-
bool get runWasmOpt =>
152-
wasmOpt == WasmOptLevel.full || wasmOpt == WasmOptLevel.debug;
153-
154-
List<String> toCommandOptions() => <String>[
155-
if (omitTypeChecks) '--omit-type-checks',
156-
];
151+
List<String> toCommandOptions() {
152+
// -O1: Optimizes
153+
// -O2: Same as -O1 but also minifies (still semantics preserving)
154+
// -O3: Same as -O2 but also omits implicit type checks.
155+
// -O4: Same as -O3 but also omits explicit type checks.
156+
// (NOTE: This differs from dart2js -O4 semantics atm.)
157+
158+
// Ortogonal: The name section is always kept by default and we emit it only
159+
// in [WasmOptLevel.full] mode (similar to `--strip` of static symbols in
160+
// AOT mode).
161+
final String level = !omitTypeChecks ? '-O2' : '-O4';
162+
return switch (wasmOpt) {
163+
WasmOptLevel.none => <String>['-O0'],
164+
WasmOptLevel.debug => <String>[level, '--no-minify'],
165+
WasmOptLevel.full => <String>[level, '--no-name-section'],
166+
};
167+
}
157168

158169
@override
159170
Map<String, Object> get buildEventAnalyticsValues => <String, Object>{

packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart

Lines changed: 38 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,12 @@ const List<String> _kDart2jsLinuxArgs = <String>[
3030
];
3131

3232
const List<String> _kDart2WasmLinuxArgs = <String> [
33-
'Artifact.engineDartAotRuntime.TargetPlatform.web_javascript',
34-
'--disable-dart-dev',
35-
'Artifact.dart2wasmSnapshot.TargetPlatform.web_javascript',
33+
'Artifact.engineDartBinary.TargetPlatform.web_javascript',
34+
'compile',
35+
'wasm',
3636
'--packages=.dart_tool/package_config.json',
37-
'--dart-sdk=Artifact.engineDartSdkPath.TargetPlatform.web_javascript',
38-
'--platform=HostArtifact.webPlatformKernelFolder/dart2wasm_platform.dill',
39-
];
40-
41-
const List<String> _kWasmOptLinuxArgrs = <String> [
42-
'Artifact.wasmOptBinary.TargetPlatform.web_javascript',
43-
'--all-features',
44-
'--closed-world',
45-
'--traps-never-happen',
46-
'-O3',
47-
'--type-ssa',
48-
'--gufa',
49-
'-O3',
50-
'--type-merging',
37+
'--extra-compiler-option=--dart-sdk=Artifact.engineDartSdkPath.TargetPlatform.web_javascript',
38+
'--extra-compiler-option=--platform=HostArtifact.webPlatformKernelFolder/dart2wasm_platform.dill',
5139
];
5240

5341
void main() {
@@ -920,7 +908,7 @@ void main() {
920908

921909
final File depFile = environment.buildDir.childFile('dart2wasm.d');
922910

923-
final File outputJsFile = environment.buildDir.childFile('main.dart.unopt.mjs');
911+
final File outputJsFile = environment.buildDir.childFile('main.dart.mjs');
924912
processManager.addCommand(FakeCommand(
925913
command: <String>[
926914
..._kDart2WasmLinuxArgs,
@@ -929,32 +917,23 @@ void main() {
929917
'-DBAZ=qux',
930918
'-DFLUTTER_WEB_AUTO_DETECT=false',
931919
'-DFLUTTER_WEB_USE_SKIA=true',
932-
'--depfile=${depFile.absolute.path}',
920+
'--extra-compiler-option=--depfile=${depFile.absolute.path}',
921+
'-O2',
922+
'--no-name-section',
923+
'-o',
924+
environment.buildDir.childFile('main.dart.wasm').absolute.path,
933925
environment.buildDir.childFile('main.dart').absolute.path,
934-
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
935926
],
936927
onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo'))
937928
);
938929

939-
processManager.addCommand(FakeCommand(
940-
command: <String>[
941-
..._kWasmOptLinuxArgrs,
942-
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
943-
'-o',
944-
environment.buildDir.childFile('main.dart.wasm').absolute.path,
945-
])
946-
);
947-
948930
await Dart2WasmTarget(
949931
const WasmCompilerConfig(
950932
renderer: WebRendererMode.canvaskit
951933
)
952934
).build(environment);
953935

954-
expect(outputJsFile.existsSync(), isFalse);
955-
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
956-
expect(movedJsFile.existsSync(), isTrue);
957-
expect(movedJsFile.readAsStringSync(), 'foo');
936+
expect(outputJsFile.existsSync(), isTrue);
958937
}, overrides: <Type, Generator>{
959938
ProcessManager: () => processManager,
960939
}));
@@ -966,41 +945,31 @@ void main() {
966945

967946
final File depFile = environment.buildDir.childFile('dart2wasm.d');
968947

969-
final File outputJsFile = environment.buildDir.childFile('main.dart.unopt.mjs');
948+
final File outputJsFile = environment.buildDir.childFile('main.dart.mjs');
970949
processManager.addCommand(FakeCommand(
971950
command: <String>[
972951
..._kDart2WasmLinuxArgs,
973952
'-Ddart.vm.product=true',
974953
'-DFLUTTER_WEB_AUTO_DETECT=false',
975954
'-DFLUTTER_WEB_USE_SKIA=true',
976-
'--omit-type-checks',
977-
'--depfile=${depFile.absolute.path}',
955+
'--extra-compiler-option=--depfile=${depFile.absolute.path}',
956+
'-O4',
957+
'--no-name-section',
958+
'-o',
959+
environment.buildDir.childFile('main.dart.wasm').absolute.path,
978960
environment.buildDir.childFile('main.dart').absolute.path,
979-
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
980961
],
981962
onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo'))
982963
);
983964

984-
processManager.addCommand(FakeCommand(
985-
command: <String>[
986-
..._kWasmOptLinuxArgrs,
987-
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
988-
'-o',
989-
environment.buildDir.childFile('main.dart.wasm').absolute.path,
990-
])
991-
);
992-
993965
await Dart2WasmTarget(
994966
const WasmCompilerConfig(
995967
omitTypeChecks: true,
996968
renderer: WebRendererMode.canvaskit
997969
)
998970
).build(environment);
999971

1000-
expect(outputJsFile.existsSync(), isFalse);
1001-
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
1002-
expect(movedJsFile.existsSync(), isTrue);
1003-
expect(movedJsFile.readAsStringSync(), 'foo');
972+
expect(outputJsFile.existsSync(), isTrue);
1004973
}, overrides: <Type, Generator>{
1005974
ProcessManager: () => processManager,
1006975
}));
@@ -1011,38 +980,29 @@ void main() {
1011980

1012981
final File depFile = environment.buildDir.childFile('dart2wasm.d');
1013982

1014-
final File outputJsFile = environment.buildDir.childFile('main.dart.unopt.mjs');
983+
final File outputJsFile = environment.buildDir.childFile('main.dart.mjs');
1015984
processManager.addCommand(FakeCommand(
1016985
command: <String>[
1017986
..._kDart2WasmLinuxArgs,
1018987
'-Ddart.vm.product=true',
1019988
'-DFLUTTER_WEB_AUTO_DETECT=false',
1020989
'-DFLUTTER_WEB_USE_SKIA=true',
1021-
'--depfile=${depFile.absolute.path}',
990+
'--extra-compiler-option=--depfile=${depFile.absolute.path}',
991+
'-O2',
992+
'--no-minify',
993+
'-o',
994+
environment.buildDir.childFile('main.dart.wasm').absolute.path,
1022995
environment.buildDir.childFile('main.dart').absolute.path,
1023-
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
1024996
], onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo')));
1025997

1026-
processManager.addCommand(FakeCommand(
1027-
command: <String>[
1028-
..._kWasmOptLinuxArgrs,
1029-
'--debuginfo',
1030-
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
1031-
'-o',
1032-
environment.buildDir.childFile('main.dart.wasm').absolute.path,
1033-
]));
1034-
1035998
await Dart2WasmTarget(
1036999
const WasmCompilerConfig(
10371000
wasmOpt: WasmOptLevel.debug,
10381001
renderer: WebRendererMode.canvaskit
10391002
)
10401003
).build(environment);
10411004

1042-
expect(outputJsFile.existsSync(), isFalse);
1043-
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
1044-
expect(movedJsFile.existsSync(), isTrue);
1045-
expect(movedJsFile.readAsStringSync(), 'foo');
1005+
expect(outputJsFile.existsSync(), isTrue);
10461006
}, overrides: <Type, Generator>{
10471007
ProcessManager: () => processManager,
10481008
}));
@@ -1060,9 +1020,11 @@ void main() {
10601020
'-Ddart.vm.product=true',
10611021
'-DFLUTTER_WEB_AUTO_DETECT=false',
10621022
'-DFLUTTER_WEB_USE_SKIA=true',
1063-
'--depfile=${depFile.absolute.path}',
1064-
environment.buildDir.childFile('main.dart').absolute.path,
1023+
'--extra-compiler-option=--depfile=${depFile.absolute.path}',
1024+
'-O0',
1025+
'-o',
10651026
environment.buildDir.childFile('main.dart.wasm').absolute.path,
1027+
environment.buildDir.childFile('main.dart').absolute.path,
10661028
], onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo')));
10671029

10681030
await Dart2WasmTarget(
@@ -1080,31 +1042,26 @@ void main() {
10801042
environment.defines[WasmCompilerConfig.kRunWasmOpt] = WasmOptLevel.defaultValue.name;
10811043
final File depFile = environment.buildDir.childFile('dart2wasm.d');
10821044

1083-
final File outputJsFile = environment.buildDir.childFile('main.dart.unopt.mjs');
1045+
final File outputJsFile = environment.buildDir.childFile('main.dart.mjs');
10841046
processManager.addCommand(FakeCommand(
10851047
command: <String>[
10861048
..._kDart2WasmLinuxArgs,
1049+
'--extra-compiler-option=--import-shared-memory',
1050+
'--extra-compiler-option=--shared-memory-max-pages=32768',
10871051
'-Ddart.vm.product=true',
10881052
'-DFLUTTER_WEB_AUTO_DETECT=false',
10891053
'-DFLUTTER_WEB_USE_SKIA=false',
10901054
'-DFLUTTER_WEB_USE_SKWASM=true',
1091-
'--import-shared-memory',
1092-
'--shared-memory-max-pages=32768',
1093-
'--depfile=${depFile.absolute.path}',
1055+
'--extra-compiler-option=--depfile=${depFile.absolute.path}',
1056+
'-O2',
1057+
'--no-name-section',
1058+
'-o',
1059+
environment.buildDir.childFile('main.dart.wasm').absolute.path,
10941060
environment.buildDir.childFile('main.dart').absolute.path,
1095-
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
10961061
],
10971062
onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo'))
10981063
);
10991064

1100-
processManager.addCommand(FakeCommand(
1101-
command: <String>[
1102-
..._kWasmOptLinuxArgrs,
1103-
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
1104-
'-o',
1105-
environment.buildDir.childFile('main.dart.wasm').absolute.path,
1106-
])
1107-
);
11081065

11091066
await Dart2WasmTarget(
11101067
const WasmCompilerConfig(

0 commit comments

Comments
 (0)