|
5 | 5 | import 'dart:io';
|
6 | 6 | import 'dart:typed_data';
|
7 | 7 |
|
| 8 | +import 'package:args/args.dart' as args; |
8 | 9 | import 'package:front_end/src/api_unstable/vm.dart'
|
9 | 10 | show printDiagnosticMessage, resolveInputUri;
|
10 | 11 |
|
11 | 12 | import 'package:dart2wasm/compile.dart';
|
12 |
| -import 'package:dart2wasm/translator.dart'; |
| 13 | +import 'package:dart2wasm/compiler_options.dart'; |
| 14 | +import 'package:dart2wasm/option.dart'; |
13 | 15 |
|
14 |
| -final Map<String, void Function(TranslatorOptions, bool)> boolOptionMap = { |
15 |
| - "export-all": (o, value) => o.exportAll = value, |
16 |
| - "import-shared-memory": (o, value) => o.importSharedMemory = value, |
17 |
| - "inlining": (o, value) => o.inlining = value, |
18 |
| - "lazy-constants": (o, value) => o.lazyConstants = value, |
19 |
| - "local-nullability": (o, value) => o.localNullability = value, |
20 |
| - "name-section": (o, value) => o.nameSection = value, |
21 |
| - "nominal-types": (o, value) => o.nominalTypes = value, |
22 |
| - "parameter-nullability": (o, value) => o.parameterNullability = value, |
23 |
| - "polymorphic-specialization": (o, value) => |
24 |
| - o.polymorphicSpecialization = value, |
25 |
| - "print-kernel": (o, value) => o.printKernel = value, |
26 |
| - "print-wasm": (o, value) => o.printWasm = value, |
27 |
| - "runtime-types": (o, value) => o.runtimeTypes = value, |
28 |
| - "string-data-segments": (o, value) => o.stringDataSegments = value, |
29 |
| -}; |
30 |
| -final Map<String, void Function(TranslatorOptions, int)> intOptionMap = { |
31 |
| - "shared-memory-max-pages": (o, value) => o.sharedMemoryMaxPages = value, |
32 |
| - "watch": (o, value) => (o.watchPoints ??= []).add(value), |
33 |
| -}; |
| 16 | +// Used to allow us to keep defaults on their respective option structs. |
| 17 | +final CompilerOptions _d = CompilerOptions.defaultOptions(); |
34 | 18 |
|
35 |
| -Never usage(String message) { |
36 |
| - print("Usage: dart2wasm [<options>] <infile.dart> <outfile.wasm>"); |
37 |
| - print(""); |
38 |
| - print("*NOTE*: Wasm compilation is experimental."); |
39 |
| - print("The support may change, or be removed, with no advance notice."); |
40 |
| - print(""); |
41 |
| - print("Options:"); |
42 |
| - print(" --dart-sdk=<path>"); |
43 |
| - print(" --platform=<path>"); |
44 |
| - print(""); |
45 |
| - for (String option in boolOptionMap.keys) { |
46 |
| - print(" --[no-]$option"); |
47 |
| - } |
48 |
| - print(""); |
49 |
| - for (String option in intOptionMap.keys) { |
50 |
| - print(" --$option <value>"); |
51 |
| - } |
52 |
| - print(""); |
| 19 | +final List<Option> options = [ |
| 20 | + Flag("help", (o, _) {}, abbr: "h", negatable: false, defaultsTo: false), |
| 21 | + Flag("export-all", (o, value) => o.translatorOptions.exportAll = value, |
| 22 | + defaultsTo: _d.translatorOptions.exportAll), |
| 23 | + Flag("import-shared-memory", |
| 24 | + (o, value) => o.translatorOptions.importSharedMemory = value, |
| 25 | + defaultsTo: _d.translatorOptions.importSharedMemory), |
| 26 | + Flag("inlining", (o, value) => o.translatorOptions.inlining = value, |
| 27 | + defaultsTo: _d.translatorOptions.inlining), |
| 28 | + Flag( |
| 29 | + "lazy-constants", (o, value) => o.translatorOptions.lazyConstants = value, |
| 30 | + defaultsTo: _d.translatorOptions.lazyConstants), |
| 31 | + Flag("local-nullability", |
| 32 | + (o, value) => o.translatorOptions.localNullability = value, |
| 33 | + defaultsTo: _d.translatorOptions.localNullability), |
| 34 | + Flag("name-section", (o, value) => o.translatorOptions.nameSection = value, |
| 35 | + defaultsTo: _d.translatorOptions.nameSection), |
| 36 | + Flag("nominal-types", (o, value) => o.translatorOptions.nominalTypes = value, |
| 37 | + defaultsTo: _d.translatorOptions.nominalTypes), |
| 38 | + Flag("parameter-nullability", |
| 39 | + (o, value) => o.translatorOptions.parameterNullability = value, |
| 40 | + defaultsTo: _d.translatorOptions.parameterNullability), |
| 41 | + Flag("polymorphic-specialization", |
| 42 | + (o, value) => o.translatorOptions.polymorphicSpecialization = value, |
| 43 | + defaultsTo: _d.translatorOptions.polymorphicSpecialization), |
| 44 | + Flag("print-kernel", (o, value) => o.translatorOptions.printKernel = value, |
| 45 | + defaultsTo: _d.translatorOptions.printKernel), |
| 46 | + Flag("print-wasm", (o, value) => o.translatorOptions.printWasm = value, |
| 47 | + defaultsTo: _d.translatorOptions.printWasm), |
| 48 | + Flag("runtime-types", (o, value) => o.translatorOptions.runtimeTypes = value, |
| 49 | + defaultsTo: _d.translatorOptions.runtimeTypes), |
| 50 | + Flag("string-data-segments", |
| 51 | + (o, value) => o.translatorOptions.stringDataSegments = value, |
| 52 | + defaultsTo: _d.translatorOptions.stringDataSegments), |
| 53 | + IntOption( |
| 54 | + "inlining-limit", (o, value) => o.translatorOptions.inliningLimit = value, |
| 55 | + defaultsTo: "${_d.translatorOptions.inliningLimit}"), |
| 56 | + IntOption("shared-memory-max-pages", |
| 57 | + (o, value) => o.translatorOptions.sharedMemoryMaxPages = value), |
| 58 | + UriOption("dart-sdk", (o, value) => o.sdkPath = value, |
| 59 | + defaultsTo: "${_d.sdkPath}"), |
| 60 | + UriOption("platform", (o, value) => o.platformPath = value), |
| 61 | + IntMultiOption( |
| 62 | + "watch", (o, values) => o.translatorOptions.watchPoints = values), |
| 63 | +]; |
53 | 64 |
|
54 |
| - throw message; |
55 |
| -} |
| 65 | +CompilerOptions parseArguments(List<String> arguments) { |
| 66 | + args.ArgParser parser = args.ArgParser(); |
| 67 | + for (Option arg in options) { |
| 68 | + arg.applyToParser(parser); |
| 69 | + } |
56 | 70 |
|
57 |
| -Future<int> main(List<String> args) async { |
58 |
| - Uri sdkPath = Platform.script.resolve("../../../sdk"); |
59 |
| - Uri? platformPath = null; |
60 |
| - TranslatorOptions options = TranslatorOptions(); |
61 |
| - List<String> nonOptions = []; |
62 |
| - void Function(TranslatorOptions, int)? intOptionFun = null; |
63 |
| - for (String arg in args) { |
64 |
| - if (intOptionFun != null) { |
65 |
| - intOptionFun(options, int.parse(arg)); |
66 |
| - intOptionFun = null; |
67 |
| - } else if (arg.startsWith("--dart-sdk=")) { |
68 |
| - String path = arg.substring("--dart-sdk=".length); |
69 |
| - sdkPath = Uri.file(Directory(path).absolute.path); |
70 |
| - } else if (arg.startsWith("--platform=")) { |
71 |
| - String path = arg.substring("--platform=".length); |
72 |
| - platformPath = Uri.file(Directory(path).absolute.path); |
73 |
| - } else if (arg.startsWith("--no-")) { |
74 |
| - var optionFun = boolOptionMap[arg.substring(5)]; |
75 |
| - if (optionFun == null) usage("Unknown option $arg"); |
76 |
| - optionFun(options, false); |
77 |
| - } else if (arg.startsWith("--")) { |
78 |
| - var optionFun = boolOptionMap[arg.substring(2)]; |
79 |
| - if (optionFun != null) { |
80 |
| - optionFun(options, true); |
81 |
| - } else { |
82 |
| - intOptionFun = intOptionMap[arg.substring(2)]; |
83 |
| - if (intOptionFun == null) usage("Unknown option $arg"); |
84 |
| - } |
85 |
| - } else { |
86 |
| - nonOptions.add(arg); |
| 71 | + Never usage() { |
| 72 | + print("Usage: dart2wasm [<options>] <infile.dart> <outfile.wasm>"); |
| 73 | + print(""); |
| 74 | + print("*NOTE*: Wasm compilation is experimental."); |
| 75 | + print("The support may change, or be removed, with no advance notice."); |
| 76 | + print(""); |
| 77 | + print("Options:"); |
| 78 | + for (String line in parser.usage.split('\n')) { |
| 79 | + print('\t$line'); |
87 | 80 | }
|
88 |
| - } |
89 |
| - if (intOptionFun != null) { |
90 |
| - usage("Missing argument to ${args.last}"); |
| 81 | + exit(64); |
91 | 82 | }
|
92 | 83 |
|
93 |
| - if (options.importSharedMemory && options.sharedMemoryMaxPages == null) { |
94 |
| - usage("--shared-memory-max-pages must be " |
95 |
| - "specified if --import-shared-memory is used."); |
| 84 | + try { |
| 85 | + args.ArgResults results = parser.parse(arguments); |
| 86 | + if (results['help']) { |
| 87 | + usage(); |
| 88 | + } |
| 89 | + List<String> rest = results.rest; |
| 90 | + if (rest.length != 2) { |
| 91 | + throw ArgumentError('Requires two positional file arguments'); |
| 92 | + } |
| 93 | + CompilerOptions compilerOptions = |
| 94 | + CompilerOptions(mainUri: resolveInputUri(rest[0]), outputFile: rest[1]); |
| 95 | + for (Option arg in options) { |
| 96 | + if (results.wasParsed(arg.name)) { |
| 97 | + arg.applyToOptions(compilerOptions, results[arg.name]); |
| 98 | + } |
| 99 | + } |
| 100 | + return compilerOptions; |
| 101 | + } catch (e, s) { |
| 102 | + print(s); |
| 103 | + print('Argument Error: ' + e.toString()); |
| 104 | + usage(); |
96 | 105 | }
|
| 106 | +} |
97 | 107 |
|
98 |
| - if (nonOptions.length != 2) usage("Requires two file arguments"); |
99 |
| - String input = nonOptions[0]; |
100 |
| - String output = nonOptions[1]; |
101 |
| - Uri mainUri = resolveInputUri(input); |
102 |
| - |
103 |
| - Uint8List? module = await compileToModule(mainUri, sdkPath, platformPath, |
| 108 | +Future<int> main(List<String> args) async { |
| 109 | + CompilerOptions options = parseArguments(args); |
| 110 | + Uint8List? module = await compileToModule( |
104 | 111 | options, (message) => printDiagnosticMessage(message, print));
|
105 | 112 |
|
106 | 113 | if (module == null) {
|
107 | 114 | exitCode = 1;
|
108 | 115 | return exitCode;
|
109 | 116 | }
|
110 | 117 |
|
111 |
| - await File(output).writeAsBytes(module); |
| 118 | + await File(options.outputFile).writeAsBytes(module); |
112 | 119 |
|
113 | 120 | return 0;
|
114 | 121 | }
|
0 commit comments