Skip to content

Commit

Permalink
Add new dart compile wasm command.
Browse files Browse the repository at this point in the history
Marked as experimental, and only shown when verbose flag is passed:

```
$ dart help compile -v
Compile Dart to various formats.

Usage: dart [vm-options] compile <subcommand> [arguments]
-h, --help    Print this usage information.

Available subcommands:
  aot-snapshot   Compile Dart to an AOT snapshot.
  exe            Compile Dart to a self-contained executable.
  jit-snapshot   Compile Dart to a JIT snapshot.
  js             Compile Dart to JavaScript.
  kernel         Compile Dart to a kernel snapshot.
  wasm           Compile Dart to a WebAssembly/WasmGC module (EXPERIMENTAL).
```

Change-Id: I6a0e65d4fbdd7b2782406b8b9969e14036bf0711
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/304860
Reviewed-by: Ben Konyi <[email protected]>
Commit-Queue: Michael Thomsen <[email protected]>
Reviewed-by: Aske Simon Christensen <[email protected]>
  • Loading branch information
mit-mit authored and Commit Queue committed Dec 5, 2023
1 parent 7abab94 commit 0df58fc
Show file tree
Hide file tree
Showing 10 changed files with 371 additions and 86 deletions.
6 changes: 5 additions & 1 deletion pkg/dart2wasm/bin/dart2wasm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
// for details. 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:dart2wasm/dart2wasm.dart' as dart2wasm;

Future<int> main(List<String> args) async => await dart2wasm.main(args);
Future<void> main(List<String> args) async {
exitCode = await dart2wasm.main(args);
}
2 changes: 1 addition & 1 deletion pkg/dart2wasm/lib/compile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class CompilerOutput {
/// Returns `null` if an error occurred during compilation. The
/// [handleDiagnosticMessage] callback will have received an error message
/// describing the error.
Future<CompilerOutput?> compileToModule(compiler.CompilerOptions options,
Future<CompilerOutput?> compileToModule(compiler.WasmCompilerOptions options,
void Function(DiagnosticMessage) handleDiagnosticMessage) async {
var succeeded = true;
void diagnosticMessageHandler(DiagnosticMessage message) {
Expand Down
8 changes: 4 additions & 4 deletions pkg/dart2wasm/lib/compiler_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'dart:io';
import 'package:dart2wasm/translator.dart';
import 'package:front_end/src/api_unstable/vm.dart' as fe;

class CompilerOptions {
class WasmCompilerOptions {
final TranslatorOptions translatorOptions = TranslatorOptions();

Uri sdkPath = Platform.script.resolve("../../../sdk");
Expand All @@ -26,10 +26,10 @@ class CompilerOptions {
String? dumpKernelBeforeTfa;
String? dumpKernelAfterTfa;

factory CompilerOptions.defaultOptions() =>
CompilerOptions(mainUri: Uri(), outputFile: '');
factory WasmCompilerOptions.defaultOptions() =>
WasmCompilerOptions(mainUri: Uri(), outputFile: '');

CompilerOptions({required this.mainUri, required this.outputFile});
WasmCompilerOptions({required this.mainUri, required this.outputFile});

void validate() {
if (translatorOptions.importSharedMemory &&
Expand Down
34 changes: 10 additions & 24 deletions pkg/dart2wasm/lib/dart2wasm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
import 'dart:io';

import 'package:args/args.dart' as args;
import 'package:front_end/src/api_unstable/vm.dart'
show printDiagnosticMessage, resolveInputUri;
import 'package:front_end/src/api_unstable/vm.dart' show resolveInputUri;
import 'package:front_end/src/api_unstable/vm.dart' as fe;

import 'package:dart2wasm/compile.dart';
import 'package:dart2wasm/compiler_options.dart';
import 'package:dart2wasm/generate_wasm.dart';
import 'package:dart2wasm/option.dart';

// Used to allow us to keep defaults on their respective option structs.
final CompilerOptions _d = CompilerOptions.defaultOptions();
// Note: When adding new options, consider if CLI options should be add
// to `pkg/dartdev/lib/src/commands/compile.dart` too.
final WasmCompilerOptions _d = WasmCompilerOptions.defaultOptions();

final List<Option> options = [
Flag("help", (o, _) {}, abbr: "h", negatable: false, defaultsTo: false),
Expand Down Expand Up @@ -96,7 +96,7 @@ Map<String, String> processEnvironment(List<String> defines) =>
return MapEntry<String, String>(keyAndValue[0], keyAndValue[1]);
}));

CompilerOptions parseArguments(List<String> arguments) {
WasmCompilerOptions parseArguments(List<String> arguments) {
args.ArgParser parser = args.ArgParser();
for (Option arg in options) {
arg.applyToParser(parser);
Expand Down Expand Up @@ -124,8 +124,8 @@ CompilerOptions parseArguments(List<String> arguments) {
if (rest.length != 2) {
throw ArgumentError('Requires two positional file arguments');
}
CompilerOptions compilerOptions =
CompilerOptions(mainUri: resolveInputUri(rest[0]), outputFile: rest[1]);
WasmCompilerOptions compilerOptions = WasmCompilerOptions(
mainUri: resolveInputUri(rest[0]), outputFile: rest[1]);
for (Option arg in options) {
if (results.wasParsed(arg.name)) {
arg.applyToOptions(compilerOptions, results[arg.name]);
Expand All @@ -140,20 +140,6 @@ CompilerOptions parseArguments(List<String> arguments) {
}

Future<int> main(List<String> args) async {
CompilerOptions options = parseArguments(args);
CompilerOutput? output = await compileToModule(
options, (message) => printDiagnosticMessage(message, print));

if (output == null) {
exitCode = 1;
return exitCode;
}

await File(options.outputFile).writeAsBytes(output.wasmModule);

final String outputJSRuntimeFile = options.outputJSRuntimeFile ??
'${options.outputFile.substring(0, options.outputFile.lastIndexOf('.'))}.mjs';
await File(outputJSRuntimeFile).writeAsString(output.jsRuntime);

return 0;
WasmCompilerOptions options = parseArguments(args);
return generateWasm(options);
}
37 changes: 37 additions & 0 deletions pkg/dart2wasm/lib/generate_wasm.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'dart:io';
import 'package:dart2wasm/compiler_options.dart';
import 'package:dart2wasm/compile.dart';
import 'package:front_end/src/api_unstable/vm.dart' show printDiagnosticMessage;
export 'package:dart2wasm/compiler_options.dart';

typedef PrintError = void Function(String error);

Future<int> generateWasm(WasmCompilerOptions options,
{bool verbose = false, PrintError errorPrinter = print}) async {
if (verbose) {
print('Running dart compile wasm...');
print(' - input file name = ${options.mainUri}');
print(' - output file name = ${options.outputFile}');
print(' - sdkPath = ${options.sdkPath}');
print(' - librariesSpecPath = ${options.librariesSpecPath}');
print(' - packagesPath file = ${options.packagesPath}');
print(' - platformPath file = ${options.platformPath}');
}

CompilerOutput? output = await compileToModule(
options, (message) => printDiagnosticMessage(message, errorPrinter));

if (output == null) {
return 1;
}

final File outFile = File(options.outputFile);
outFile.parent.createSync(recursive: true);
await outFile.writeAsBytes(output.wasmModule);

final jsFile = options.outputJSRuntimeFile ??
'${options.outputFile.substring(0, options.outputFile.lastIndexOf('.'))}.mjs';
await File(jsFile).writeAsString(output.jsRuntime);

return 0;
}
33 changes: 15 additions & 18 deletions pkg/dart2wasm/lib/option.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ import 'package:dart2wasm/compiler_options.dart';
class Option<T> {
final String name;
final void Function(ArgParser a) applyToParser;
final void Function(CompilerOptions o, T v) _applyToOptions;
final void Function(WasmCompilerOptions o, T v) _applyToOptions;
final T Function(dynamic v) converter;

void applyToOptions(CompilerOptions o, dynamic v) =>
void applyToOptions(WasmCompilerOptions o, dynamic v) =>
_applyToOptions(o, converter(v));

Option(this.name, this.applyToParser, this._applyToOptions, this.converter);
}

class Flag extends Option<bool> {
Flag(String name, void applyToOptions(CompilerOptions o, bool v),
Flag(String name, void applyToOptions(WasmCompilerOptions o, bool v),
{String? abbr,
String? help,
bool? defaultsTo = false,
Expand All @@ -38,31 +38,28 @@ class Flag extends Option<bool> {
}

class ValueOption<T> extends Option<T> {
ValueOption(String name, void applyToOptions(CompilerOptions o, T v),
ValueOption(String name, void applyToOptions(WasmCompilerOptions o, T v),
T converter(dynamic v), {String? defaultsTo, bool hide = false})
: super(
name,
(a) => a.addOption(name, defaultsTo: defaultsTo, hide: hide),
applyToOptions,
converter);
: super(name, (a) => a.addOption(name, defaultsTo: defaultsTo),
applyToOptions, converter);
}

class IntOption extends ValueOption<int> {
IntOption(String name, void applyToOptions(CompilerOptions o, int v),
IntOption(String name, void applyToOptions(WasmCompilerOptions o, int v),
{String? defaultsTo})
: super(name, applyToOptions, (v) => int.parse(v),
defaultsTo: defaultsTo);
}

class StringOption extends ValueOption<String> {
StringOption(String name, void applyToOptions(CompilerOptions o, String v),
StringOption(
String name, void applyToOptions(WasmCompilerOptions o, String v),
{String? defaultsTo, bool hide = false})
: super(name, applyToOptions, (v) => v,
defaultsTo: defaultsTo, hide: hide);
: super(name, applyToOptions, (v) => v, defaultsTo: defaultsTo);
}

class UriOption extends ValueOption<Uri> {
UriOption(String name, void applyToOptions(CompilerOptions o, Uri v),
UriOption(String name, void applyToOptions(WasmCompilerOptions o, Uri v),
{String? defaultsTo})
: super(name, applyToOptions, (v) => Uri.file(Directory(v).absolute.path),
defaultsTo: defaultsTo);
Expand All @@ -71,7 +68,7 @@ class UriOption extends ValueOption<Uri> {
class MultiValueOption<T> extends Option<List<T>> {
MultiValueOption(
String name,
void Function(CompilerOptions o, List<T> v) applyToOptions,
void Function(WasmCompilerOptions o, List<T> v) applyToOptions,
T converter(dynamic v),
{Iterable<String>? defaultsTo,
String? abbr})
Expand All @@ -83,22 +80,22 @@ class MultiValueOption<T> extends Option<List<T>> {
}

class IntMultiOption extends MultiValueOption<int> {
IntMultiOption(name, void applyToOptions(CompilerOptions o, List<int> v),
IntMultiOption(name, void applyToOptions(WasmCompilerOptions o, List<int> v),
{Iterable<String>? defaultsTo})
: super(name, applyToOptions, (v) => int.parse(v),
defaultsTo: defaultsTo);
}

class StringMultiOption extends MultiValueOption<String> {
StringMultiOption(
name, void applyToOptions(CompilerOptions o, List<String> v),
name, void applyToOptions(WasmCompilerOptions o, List<String> v),
{String? abbr, Iterable<String>? defaultsTo})
: super(name, applyToOptions, (v) => v,
abbr: abbr, defaultsTo: defaultsTo);
}

class UriMultiOption extends MultiValueOption<Uri> {
UriMultiOption(name, void applyToOptions(CompilerOptions o, List<Uri> v),
UriMultiOption(name, void applyToOptions(WasmCompilerOptions o, List<Uri> v),
{Iterable<String>? defaultsTo})
: super(name, applyToOptions, (v) => Uri.file(Directory(v).absolute.path),
defaultsTo: defaultsTo);
Expand Down
Loading

0 comments on commit 0df58fc

Please sign in to comment.