Add new dart compile wasm command.
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 <bkonyi@google.com> Commit-Queue: Michael Thomsen <mit@google.com> Reviewed-by: Aske Simon Christensen <askesc@google.com>
This commit is contained in:
committed by
Commit Queue
parent
7abab94d97
commit
0df58fc2d0
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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),
|
||||
@@ -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);
|
||||
@@ -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]);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
@@ -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);
|
||||
@@ -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})
|
||||
@@ -83,7 +80,7 @@ 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);
|
||||
@@ -91,14 +88,14 @@ class IntMultiOption extends MultiValueOption<int> {
|
||||
|
||||
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);
|
||||
|
||||
@@ -7,8 +7,10 @@ import 'dart:io';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:dart2native/generate.dart';
|
||||
import 'package:dart2wasm/generate_wasm.dart';
|
||||
import 'package:front_end/src/api_prototype/compiler_options.dart'
|
||||
show Verbosity;
|
||||
import 'package:front_end/src/api_unstable/vm.dart' as fe;
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:vm/target_os.dart'; // For possible --target-os values.
|
||||
|
||||
@@ -384,6 +386,200 @@ Remove debugging information from the output and save it separately to the speci
|
||||
}
|
||||
}
|
||||
|
||||
class CompileWasmCommand extends CompileSubcommandCommand {
|
||||
static const String commandName = 'wasm';
|
||||
static const String format = 'wasm';
|
||||
static const String help =
|
||||
'Compile Dart to a WebAssembly/WasmGC module (EXPERIMENTAL).';
|
||||
|
||||
final String optimizer = path.join(binDir.path, 'utils', 'wasm-opt');
|
||||
String optimizerFlags(bool outputNames) =>
|
||||
'-all --closed-world -tnh --type-unfinalizing -O3 --type-ssa'
|
||||
' --gufa -O3 --type-merging -O1 --type-finalizing'
|
||||
'${outputNames ? ' -g' : ''}';
|
||||
static const String unoptExtension = '.unopt';
|
||||
|
||||
CompileWasmCommand({bool verbose = false})
|
||||
: super(commandName, help, verbose, hidden: !verbose) {
|
||||
argParser
|
||||
..addOption(
|
||||
outputFileOption.flag,
|
||||
help: outputFileOption.help,
|
||||
abbr: outputFileOption.abbr,
|
||||
)
|
||||
..addFlag(
|
||||
'optimize',
|
||||
defaultsTo: true,
|
||||
negatable: true,
|
||||
help: 'Optimize wasm output using Binaryen wasm-opt.',
|
||||
)
|
||||
..addFlag(
|
||||
'omit-type-checks',
|
||||
defaultsTo: false,
|
||||
negatable: false,
|
||||
help: 'Omit runtime type checks, such as covariance and downcasts.',
|
||||
hide: !verbose,
|
||||
)
|
||||
..addFlag(
|
||||
'name-section',
|
||||
defaultsTo: false,
|
||||
negatable: false,
|
||||
help: 'Include a name section with printable function names.',
|
||||
hide: !verbose,
|
||||
)
|
||||
..addFlag(
|
||||
'print-wasm',
|
||||
help: 'Print human-readable wasm debug output',
|
||||
hide: !verbose,
|
||||
negatable: false,
|
||||
)
|
||||
..addFlag(
|
||||
'print-kernel',
|
||||
help: 'Print human-readable Dart kernel debug output',
|
||||
hide: !verbose,
|
||||
negatable: false,
|
||||
)
|
||||
..addFlag(
|
||||
'verbose',
|
||||
abbr: 'v',
|
||||
help: 'Print debug output during compilation',
|
||||
negatable: false,
|
||||
)
|
||||
..addFlag(
|
||||
'enable-asserts',
|
||||
help: 'Enable assert statements.',
|
||||
negatable: false,
|
||||
)
|
||||
..addOption(
|
||||
'shared-memory',
|
||||
help: 'Import a shared memory buffer.'
|
||||
' The max number of pages must be passed.',
|
||||
valueHelp: 'page count',
|
||||
hide: !verbose,
|
||||
)
|
||||
..addOption(
|
||||
packagesOption.flag,
|
||||
abbr: packagesOption.abbr,
|
||||
valueHelp: packagesOption.valueHelp,
|
||||
help: packagesOption.help,
|
||||
hide: !verbose,
|
||||
);
|
||||
// TODO(): Defines are currently not supported by dart2wasm.
|
||||
// ..addMultiOption(
|
||||
// defineOption.flag,
|
||||
// help: defineOption.help,
|
||||
// abbr: defineOption.abbr,
|
||||
// valueHelp: defineOption.valueHelp,
|
||||
// )
|
||||
}
|
||||
|
||||
@override
|
||||
String get invocation => '${super.invocation} <dart entry point>';
|
||||
|
||||
@override
|
||||
FutureOr<int> run() async {
|
||||
log.stdout('*NOTE*: Compilation to WasmGC is experimental.');
|
||||
log.stdout(
|
||||
'The support may change, or be removed, with no advance notice.\n');
|
||||
|
||||
final libraries = path.absolute(sdk.sdkPath, 'lib', 'libraries.json');
|
||||
if (!Sdk.checkArtifactExists(libraries)) {
|
||||
return 255;
|
||||
}
|
||||
final args = argResults!;
|
||||
bool verbose = this.verbose || args['verbose'];
|
||||
if (args['optimize'] && !Sdk.checkArtifactExists(optimizer)) {
|
||||
return 255;
|
||||
}
|
||||
|
||||
// We expect a single rest argument; the dart entry point.
|
||||
if (args.rest.length != 1) {
|
||||
// This throws.
|
||||
usageException('Missing Dart entry point.');
|
||||
}
|
||||
final String sourcePath = args.rest[0];
|
||||
if (!checkFile(sourcePath)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Determine output file name.
|
||||
String? outputFile = args[outputFileOption.flag];
|
||||
if (outputFile == null) {
|
||||
final inputWithoutDart = sourcePath.endsWith('.dart')
|
||||
? sourcePath.substring(0, sourcePath.length - 5)
|
||||
: sourcePath;
|
||||
outputFile = '$inputWithoutDart.wasm';
|
||||
}
|
||||
|
||||
final options = WasmCompilerOptions(
|
||||
mainUri: Uri.file(path.absolute(sourcePath)),
|
||||
outputFile: outputFile,
|
||||
);
|
||||
options.librariesSpecPath =
|
||||
Uri.file(path.absolute(sdk.sdkPath, 'lib', 'libraries.json'));
|
||||
options.sdkPath = Uri.file(path.absolute(sdk.sdkPath));
|
||||
options.packagesPath = args[packagesOption.flag];
|
||||
options.translatorOptions.enableAsserts = args['enable-asserts'];
|
||||
options.translatorOptions.printWasm = args['print-wasm'];
|
||||
options.translatorOptions.printKernel = args['print-kernel'];
|
||||
options.translatorOptions.omitTypeChecks = args['omit-type-checks'];
|
||||
options.translatorOptions.nameSection = args['name-section'];
|
||||
if (args['shared-memory'] != null) {
|
||||
int? maxPages = int.tryParse(args['shared-memory']);
|
||||
if (maxPages == null) {
|
||||
usageException(
|
||||
'Error: The --shared-memory flag must specify a number!');
|
||||
}
|
||||
options.translatorOptions.importSharedMemory = true;
|
||||
options.translatorOptions.sharedMemoryMaxPages = maxPages;
|
||||
}
|
||||
// Enable inline classes.
|
||||
// TODO: Remove this when inline classe ship.
|
||||
options.feExperimentalFlags = {fe.ExperimentalFlag.inlineClass: true};
|
||||
|
||||
int result;
|
||||
try {
|
||||
result = await generateWasm(
|
||||
options,
|
||||
verbose: verbose,
|
||||
errorPrinter: (error) => log.stderr(error),
|
||||
);
|
||||
if (result != 0) return compileErrorExitCode;
|
||||
} catch (e, st) {
|
||||
log.stderr('Error: Wasm compilation failed');
|
||||
log.stderr(e.toString());
|
||||
if (verbose) {
|
||||
log.stderr(st.toString());
|
||||
}
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
|
||||
if (args['optimize']) {
|
||||
final unoptFile = outputFile + unoptExtension;
|
||||
final flags = optimizerFlags(args['name-section']);
|
||||
File(outputFile).renameSync(unoptFile);
|
||||
if (verbose) {
|
||||
log.stdout('Optimizing output with: $optimizer $flags');
|
||||
}
|
||||
final processResult = Process.runSync(
|
||||
optimizer,
|
||||
[...flags.split(' '), '-o', outputFile, unoptFile],
|
||||
);
|
||||
if (processResult.exitCode != 0) {
|
||||
log.stderr('Error: Wasm compilation failed while optimizing output');
|
||||
log.stderr(processResult.stderr);
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
}
|
||||
|
||||
final mjsFile =
|
||||
'${options.outputFile.substring(0, options.outputFile.lastIndexOf('.'))}.mjs';
|
||||
log.stdout(
|
||||
"Generated wasm module '$outputFile', and JS init file '$mjsFile'.");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class CompileSubcommandCommand extends DartdevCommand {
|
||||
final outputFileOption = Option(
|
||||
flag: 'output',
|
||||
@@ -487,5 +683,6 @@ class CompileCommand extends DartdevCommand {
|
||||
verbose: verbose,
|
||||
nativeAssetsExperimentEnabled: nativeAssetsExperimentEnabled,
|
||||
));
|
||||
addSubcommand(CompileWasmCommand(verbose: verbose));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ dependencies:
|
||||
cli_util: any
|
||||
collection: any
|
||||
dart2native: any
|
||||
dart2wasm: any
|
||||
dart_style: any
|
||||
dartdoc: any
|
||||
dds: any
|
||||
|
||||
@@ -46,7 +46,7 @@ void defineCompileTests() {
|
||||
path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'exe',
|
||||
@@ -172,7 +172,7 @@ void defineCompileTests() {
|
||||
|
||||
test('Implicit --help', () async {
|
||||
final p = project();
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
],
|
||||
@@ -309,7 +309,7 @@ void defineCompileTests() {
|
||||
final p = project(mainSrc: 'void main() { print("I love executables"); }');
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'exe',
|
||||
@@ -326,7 +326,7 @@ void defineCompileTests() {
|
||||
final p = project(mainSrc: 'void main() { print("I love executables"); }');
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'aot-snapshot',
|
||||
@@ -418,7 +418,7 @@ void defineCompileTests() {
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
|
||||
final targetOS = Platform.isLinux ? 'macos' : 'linux';
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'exe',
|
||||
@@ -611,7 +611,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'exe',
|
||||
@@ -641,7 +641,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'exe',
|
||||
@@ -663,7 +663,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'exe',
|
||||
@@ -687,7 +687,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'exe',
|
||||
@@ -743,7 +743,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'exe',
|
||||
@@ -773,7 +773,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'exe',
|
||||
@@ -791,12 +791,68 @@ void main() {
|
||||
expect(result.exitCode, 0);
|
||||
}, skip: isRunningOnIA32);
|
||||
|
||||
test('Compile wasm with error', () async {
|
||||
final p = project(mainSrc: '''
|
||||
void main() {
|
||||
int? i;
|
||||
i.isEven;
|
||||
}
|
||||
''');
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'mywasm'));
|
||||
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'wasm',
|
||||
'-o',
|
||||
outFile,
|
||||
inFile,
|
||||
],
|
||||
);
|
||||
|
||||
expect(result.stdout, contains('Compilation to WasmGC is experimental'));
|
||||
expect(result.stderr, contains('Error: '));
|
||||
// The CFE doesn't print to stderr, so all output is piped to stderr, even
|
||||
// including info-only output:
|
||||
expect(result.stderr, isNot(contains(soundNullSafetyMessage)));
|
||||
expect(result.exitCode, compileErrorExitCode);
|
||||
expect(File(outFile).existsSync(), false,
|
||||
reason: 'File not found: $outFile');
|
||||
}, skip: isRunningOnIA32);
|
||||
|
||||
test('Compile wasm with warnings', () async {
|
||||
final p = project(mainSrc: '''
|
||||
void main() {
|
||||
int i = 0;
|
||||
i?.isEven;
|
||||
}
|
||||
''');
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'mywasm.wasm'));
|
||||
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'wasm',
|
||||
'-o',
|
||||
outFile,
|
||||
inFile,
|
||||
],
|
||||
);
|
||||
|
||||
expect(result.stderr, contains('Warning: '));
|
||||
expect(result.exitCode, 0);
|
||||
expect(File(outFile).existsSync(), true,
|
||||
reason: 'File not found: $outFile');
|
||||
}, skip: isRunningOnIA32);
|
||||
|
||||
test('Compile JS with sound null safety', () async {
|
||||
final p = project(mainSrc: '''void main() {}''');
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myjs'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'js',
|
||||
@@ -821,7 +877,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myjs'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'js',
|
||||
@@ -844,7 +900,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myjs'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'js',
|
||||
@@ -872,7 +928,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myjs'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'js',
|
||||
@@ -893,7 +949,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myaot'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'aot-snapshot',
|
||||
@@ -917,7 +973,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myaot'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'aot-snapshot',
|
||||
@@ -941,7 +997,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myaot'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'aot-snapshot',
|
||||
@@ -971,7 +1027,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myaot'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'aot-snapshot',
|
||||
@@ -999,7 +1055,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myaot'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'aot-snapshot',
|
||||
@@ -1022,7 +1078,7 @@ void main() {
|
||||
final p = project(mainSrc: '''void main() {}''');
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'kernel',
|
||||
@@ -1046,7 +1102,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'kernel',
|
||||
@@ -1075,7 +1131,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'kernel',
|
||||
@@ -1100,7 +1156,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'kernel',
|
||||
@@ -1125,7 +1181,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'kernel',
|
||||
@@ -1149,7 +1205,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'kernel',
|
||||
@@ -1172,7 +1228,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'kernel',
|
||||
@@ -1199,7 +1255,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'kernel',
|
||||
@@ -1224,7 +1280,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'kernel',
|
||||
@@ -1245,7 +1301,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'jit-snapshot',
|
||||
@@ -1268,7 +1324,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'jit-snapshot',
|
||||
@@ -1291,7 +1347,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'jit-snapshot',
|
||||
@@ -1315,7 +1371,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'jit-snapshot',
|
||||
@@ -1338,7 +1394,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'jit-snapshot',
|
||||
@@ -1366,7 +1422,7 @@ void main() {}
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'jit-snapshot',
|
||||
@@ -1392,7 +1448,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'jit-snapshot',
|
||||
@@ -1417,7 +1473,7 @@ void main() {
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
|
||||
|
||||
var result = await p.run(
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
'jit-snapshot',
|
||||
|
||||
@@ -41,7 +41,7 @@ void _dartdevCommand() {
|
||||
});
|
||||
|
||||
test('compile', () {
|
||||
assertDartdevCommandProperties(CompileCommand(), 'compile', 'compile', 5);
|
||||
assertDartdevCommandProperties(CompileCommand(), 'compile', 'compile', 6);
|
||||
});
|
||||
|
||||
test('compile/js', () {
|
||||
@@ -79,6 +79,13 @@ void _dartdevCommand() {
|
||||
'compile/aot-snapshot');
|
||||
});
|
||||
|
||||
test('compile/wasm', () {
|
||||
assertDartdevCommandProperties(
|
||||
CompileCommand().subcommands['wasm'] as DartdevCommand,
|
||||
'wasm',
|
||||
'compile/wasm');
|
||||
});
|
||||
|
||||
test('create', () {
|
||||
assertDartdevCommandProperties(CreateCommand(), 'create', 'create');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user