1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-03 08:19:13 +00:00

[dart2wasm] Switch to package args for command line parsing.

Change-Id: I6ca7846e7dd2f41d4b04dcba1fce8ac8e7b1391f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250481
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Commit-Queue: Joshua Litt <joshualitt@google.com>
This commit is contained in:
Joshua Litt 2022-07-25 02:24:58 +00:00 committed by Commit Bot
parent ad004cf922
commit c8728d92e3
5 changed files with 210 additions and 97 deletions

View File

@ -5,102 +5,109 @@
import 'dart:io';
import 'dart:typed_data';
import 'package:args/args.dart' as args;
import 'package:front_end/src/api_unstable/vm.dart'
show printDiagnosticMessage, resolveInputUri;
import 'package:dart2wasm/compile.dart';
import 'package:dart2wasm/translator.dart';
import 'package:dart2wasm/compiler_options.dart';
import 'package:dart2wasm/option.dart';
final Map<String, void Function(TranslatorOptions, bool)> boolOptionMap = {
"export-all": (o, value) => o.exportAll = value,
"import-shared-memory": (o, value) => o.importSharedMemory = value,
"inlining": (o, value) => o.inlining = value,
"lazy-constants": (o, value) => o.lazyConstants = value,
"local-nullability": (o, value) => o.localNullability = value,
"name-section": (o, value) => o.nameSection = value,
"nominal-types": (o, value) => o.nominalTypes = value,
"parameter-nullability": (o, value) => o.parameterNullability = value,
"polymorphic-specialization": (o, value) =>
o.polymorphicSpecialization = value,
"print-kernel": (o, value) => o.printKernel = value,
"print-wasm": (o, value) => o.printWasm = value,
"runtime-types": (o, value) => o.runtimeTypes = value,
"string-data-segments": (o, value) => o.stringDataSegments = value,
};
final Map<String, void Function(TranslatorOptions, int)> intOptionMap = {
"shared-memory-max-pages": (o, value) => o.sharedMemoryMaxPages = value,
"watch": (o, value) => (o.watchPoints ??= []).add(value),
};
// Used to allow us to keep defaults on their respective option structs.
final CompilerOptions _d = CompilerOptions.defaultOptions();
Never usage(String message) {
print("Usage: dart2wasm [<options>] <infile.dart> <outfile.wasm>");
print("");
print("*NOTE*: Wasm compilation is experimental.");
print("The support may change, or be removed, with no advance notice.");
print("");
print("Options:");
print(" --dart-sdk=<path>");
print(" --platform=<path>");
print("");
for (String option in boolOptionMap.keys) {
print(" --[no-]$option");
final List<Option> options = [
Flag("help", (o, _) {}, abbr: "h", negatable: false, defaultsTo: false),
Flag("export-all", (o, value) => o.translatorOptions.exportAll = value,
defaultsTo: _d.translatorOptions.exportAll),
Flag("import-shared-memory",
(o, value) => o.translatorOptions.importSharedMemory = value,
defaultsTo: _d.translatorOptions.importSharedMemory),
Flag("inlining", (o, value) => o.translatorOptions.inlining = value,
defaultsTo: _d.translatorOptions.inlining),
Flag(
"lazy-constants", (o, value) => o.translatorOptions.lazyConstants = value,
defaultsTo: _d.translatorOptions.lazyConstants),
Flag("local-nullability",
(o, value) => o.translatorOptions.localNullability = value,
defaultsTo: _d.translatorOptions.localNullability),
Flag("name-section", (o, value) => o.translatorOptions.nameSection = value,
defaultsTo: _d.translatorOptions.nameSection),
Flag("nominal-types", (o, value) => o.translatorOptions.nominalTypes = value,
defaultsTo: _d.translatorOptions.nominalTypes),
Flag("parameter-nullability",
(o, value) => o.translatorOptions.parameterNullability = value,
defaultsTo: _d.translatorOptions.parameterNullability),
Flag("polymorphic-specialization",
(o, value) => o.translatorOptions.polymorphicSpecialization = value,
defaultsTo: _d.translatorOptions.polymorphicSpecialization),
Flag("print-kernel", (o, value) => o.translatorOptions.printKernel = value,
defaultsTo: _d.translatorOptions.printKernel),
Flag("print-wasm", (o, value) => o.translatorOptions.printWasm = value,
defaultsTo: _d.translatorOptions.printWasm),
Flag("runtime-types", (o, value) => o.translatorOptions.runtimeTypes = value,
defaultsTo: _d.translatorOptions.runtimeTypes),
Flag("string-data-segments",
(o, value) => o.translatorOptions.stringDataSegments = value,
defaultsTo: _d.translatorOptions.stringDataSegments),
IntOption(
"inlining-limit", (o, value) => o.translatorOptions.inliningLimit = value,
defaultsTo: "${_d.translatorOptions.inliningLimit}"),
IntOption("shared-memory-max-pages",
(o, value) => o.translatorOptions.sharedMemoryMaxPages = value),
UriOption("dart-sdk", (o, value) => o.sdkPath = value,
defaultsTo: "${_d.sdkPath}"),
UriOption("platform", (o, value) => o.platformPath = value),
IntMultiOption(
"watch", (o, values) => o.translatorOptions.watchPoints = values),
];
CompilerOptions parseArguments(List<String> arguments) {
args.ArgParser parser = args.ArgParser();
for (Option arg in options) {
arg.applyToParser(parser);
}
print("");
for (String option in intOptionMap.keys) {
print(" --$option <value>");
}
print("");
throw message;
Never usage() {
print("Usage: dart2wasm [<options>] <infile.dart> <outfile.wasm>");
print("");
print("*NOTE*: Wasm compilation is experimental.");
print("The support may change, or be removed, with no advance notice.");
print("");
print("Options:");
for (String line in parser.usage.split('\n')) {
print('\t$line');
}
exit(64);
}
try {
args.ArgResults results = parser.parse(arguments);
if (results['help']) {
usage();
}
List<String> rest = results.rest;
if (rest.length != 2) {
throw ArgumentError('Requires two positional file arguments');
}
CompilerOptions compilerOptions =
CompilerOptions(mainUri: resolveInputUri(rest[0]), outputFile: rest[1]);
for (Option arg in options) {
if (results.wasParsed(arg.name)) {
arg.applyToOptions(compilerOptions, results[arg.name]);
}
}
return compilerOptions;
} catch (e, s) {
print(s);
print('Argument Error: ' + e.toString());
usage();
}
}
Future<int> main(List<String> args) async {
Uri sdkPath = Platform.script.resolve("../../../sdk");
Uri? platformPath = null;
TranslatorOptions options = TranslatorOptions();
List<String> nonOptions = [];
void Function(TranslatorOptions, int)? intOptionFun = null;
for (String arg in args) {
if (intOptionFun != null) {
intOptionFun(options, int.parse(arg));
intOptionFun = null;
} else if (arg.startsWith("--dart-sdk=")) {
String path = arg.substring("--dart-sdk=".length);
sdkPath = Uri.file(Directory(path).absolute.path);
} else if (arg.startsWith("--platform=")) {
String path = arg.substring("--platform=".length);
platformPath = Uri.file(Directory(path).absolute.path);
} else if (arg.startsWith("--no-")) {
var optionFun = boolOptionMap[arg.substring(5)];
if (optionFun == null) usage("Unknown option $arg");
optionFun(options, false);
} else if (arg.startsWith("--")) {
var optionFun = boolOptionMap[arg.substring(2)];
if (optionFun != null) {
optionFun(options, true);
} else {
intOptionFun = intOptionMap[arg.substring(2)];
if (intOptionFun == null) usage("Unknown option $arg");
}
} else {
nonOptions.add(arg);
}
}
if (intOptionFun != null) {
usage("Missing argument to ${args.last}");
}
if (options.importSharedMemory && options.sharedMemoryMaxPages == null) {
usage("--shared-memory-max-pages must be "
"specified if --import-shared-memory is used.");
}
if (nonOptions.length != 2) usage("Requires two file arguments");
String input = nonOptions[0];
String output = nonOptions[1];
Uri mainUri = resolveInputUri(input);
Uint8List? module = await compileToModule(mainUri, sdkPath, platformPath,
CompilerOptions options = parseArguments(args);
Uint8List? module = await compileToModule(
options, (message) => printDiagnosticMessage(message, print));
if (module == null) {
@ -108,7 +115,7 @@ Future<int> main(List<String> args) async {
return exitCode;
}
await File(output).writeAsBytes(module);
await File(options.outputFile).writeAsBytes(module);
return 0;
}

View File

@ -22,6 +22,7 @@ import 'package:kernel/verifier.dart';
import 'package:vm/transformations/type_flow/transformer.dart' as globalTypeFlow
show transformComponent;
import 'package:dart2wasm/compiler_options.dart' as compiler;
import 'package:dart2wasm/target.dart';
import 'package:dart2wasm/translator.dart';
@ -30,11 +31,7 @@ import 'package:dart2wasm/translator.dart';
/// Returns `null` if an error occurred during compilation. The
/// [handleDiagnosticMessage] callback will have received an error message
/// describing the error.
Future<Uint8List?> compileToModule(
Uri mainUri,
Uri sdkRoot,
Uri? platformDill,
TranslatorOptions options,
Future<Uint8List?> compileToModule(compiler.CompilerOptions options,
void Function(DiagnosticMessage) handleDiagnosticMessage) async {
var succeeded = true;
void diagnosticMessageHandler(DiagnosticMessage message) {
@ -47,20 +44,20 @@ Future<Uint8List?> compileToModule(
Target target = WasmTarget();
CompilerOptions compilerOptions = CompilerOptions()
..target = target
..sdkRoot = sdkRoot
..sdkRoot = options.sdkPath
..environmentDefines = {}
..verbose = false
..onDiagnostic = diagnosticMessageHandler
..nnbdMode = NnbdMode.Strong;
if (platformDill != null) {
compilerOptions.sdkSummary = platformDill;
if (options.platformPath != null) {
compilerOptions.sdkSummary = options.platformPath;
} else {
compilerOptions.compileSdk = true;
}
CompilerResult? compilerResult =
await kernelForProgram(mainUri, compilerOptions);
await kernelForProgram(options.mainUri, compilerOptions);
if (compilerResult == null || !succeeded) {
return null;
}
@ -78,7 +75,10 @@ Future<Uint8List?> compileToModule(
return true;
}());
var translator = Translator(component, coreTypes,
TypeEnvironment(coreTypes, compilerResult.classHierarchy!), options);
var translator = Translator(
component,
coreTypes,
TypeEnvironment(coreTypes, compilerResult.classHierarchy!),
options.translatorOptions);
return translator.translate();
}

View File

@ -0,0 +1,29 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// 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/translator.dart';
class CompilerOptions {
final TranslatorOptions translatorOptions = TranslatorOptions();
Uri sdkPath = Platform.script.resolve("../../../sdk");
Uri? platformPath;
Uri mainUri;
String outputFile;
factory CompilerOptions.defaultOptions() =>
CompilerOptions(mainUri: Uri(), outputFile: '');
CompilerOptions({required this.mainUri, required this.outputFile});
void validate() {
if (translatorOptions.importSharedMemory &&
translatorOptions.sharedMemoryMaxPages == null) {
throw ArgumentError("--shared-memory-max-pages must be specified if "
"--import-shared-memory is used.");
}
}
}

View File

@ -0,0 +1,76 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// 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:args/args.dart';
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 T Function(dynamic v) converter;
void applyToOptions(CompilerOptions 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),
{String? abbr,
String? help,
bool? defaultsTo = false,
bool negatable = true})
: super(
name,
(a) => a.addFlag(name,
abbr: abbr,
help: help,
defaultsTo: defaultsTo,
negatable: negatable),
applyToOptions,
(v) => v == 'true' ? true : false);
}
class ValueOption<T> extends Option<T> {
ValueOption(String name, void applyToOptions(CompilerOptions o, T v),
T converter(dynamic v), {String? defaultsTo})
: super(name, (a) => a.addOption(name, defaultsTo: defaultsTo),
applyToOptions, converter);
}
class IntOption extends ValueOption<int> {
IntOption(String name, void applyToOptions(CompilerOptions o, int v),
{String? defaultsTo})
: super(name, applyToOptions, (v) => int.parse(v),
defaultsTo: defaultsTo);
}
class UriOption extends ValueOption<Uri> {
UriOption(String name, void applyToOptions(CompilerOptions o, Uri v),
{String? defaultsTo})
: super(name, applyToOptions, (v) => Uri.file(Directory(v).absolute.path),
defaultsTo: defaultsTo);
}
class MultiValueOption<T> extends Option<List<T>> {
MultiValueOption(
String name,
void Function(CompilerOptions o, List<T> v) applyToOptions,
T converter(dynamic v),
{Iterable<String>? defaultsTo})
: super(name, (a) => a.addMultiOption(name, defaultsTo: defaultsTo),
applyToOptions, (vs) => vs.map(converter).cast<T>().toList());
}
class IntMultiOption extends MultiValueOption<int> {
IntMultiOption(name, void applyToOptions(CompilerOptions o, List<int> v),
{Iterable<String>? defaultsTo})
: super(name, applyToOptions, (v) => int.parse(v),
defaultsTo: defaultsTo);
}

View File

@ -7,6 +7,7 @@ environment:
# Use 'any' constraints here; we get our versions from the DEPS file.
dependencies:
_js_interop_checks: any
args: any
front_end: any
kernel: any
vm: any