mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:41:41 +00:00
Add a new dartdev compile verb.
Supports compiling to snapshots, JS, native executables, and kernel: $ dart help compile Compile Dart to various formats Usage: dart compile <subcommand> [arguments] -h, --help Print this usage information. Available subcommands: aot Compile Dart to an AOT snapshot exe Compile Dart to a self-contained executable jit Compile Dart to a JIT snapshot js Compile Dart to JavaScript kernel Compile Dart to Kernel intermediate format Change-Id: I1143f8dd0eec6f87a8271144f92dedc1fcf82923 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/146806 Commit-Queue: Michael Thomsen <mit@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Jaime Wren <jwren@google.com>
This commit is contained in:
parent
f008738abd
commit
b54a95b0bb
13
pkg/dart2native/analysis_options.yaml
Normal file
13
pkg/dart2native/analysis_options.yaml
Normal file
|
@ -0,0 +1,13 @@
|
|||
include: package:pedantic/analysis_options.1.8.0.yaml
|
||||
|
||||
analyzer:
|
||||
errors:
|
||||
# Increase the severity of several hints.
|
||||
prefer_single_quotes: warning
|
||||
unused_import: warning
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- directives_ordering
|
||||
- prefer_relative_imports
|
||||
- prefer_single_quotes
|
|
@ -6,83 +6,7 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:dart2native/dart2native.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
final String executableSuffix = Platform.isWindows ? '.exe' : '';
|
||||
final String snapshotDir = path.dirname(Platform.script.toFilePath());
|
||||
final String binDir = path.canonicalize(path.join(snapshotDir, '..'));
|
||||
final String sdkDir = path.canonicalize(path.join(binDir, '..'));
|
||||
final String dart = path.join(binDir, 'dart${executableSuffix}');
|
||||
final String genKernel = path.join(snapshotDir, 'gen_kernel.dart.snapshot');
|
||||
final String dartaotruntime =
|
||||
path.join(binDir, 'dartaotruntime${executableSuffix}');
|
||||
final String genSnapshot =
|
||||
path.join(binDir, 'utils', 'gen_snapshot${executableSuffix}');
|
||||
final String productPlatformDill =
|
||||
path.join(sdkDir, 'lib', '_internal', 'vm_platform_strong_product.dill');
|
||||
|
||||
Future<void> generateNative(
|
||||
Kind kind,
|
||||
String sourceFile,
|
||||
String outputFile,
|
||||
String debugFile,
|
||||
String packages,
|
||||
List<String> defines,
|
||||
bool enableAsserts,
|
||||
bool verbose,
|
||||
List<String> extraGenSnapshotOptions) async {
|
||||
final Directory tempDir = Directory.systemTemp.createTempSync();
|
||||
try {
|
||||
final String kernelFile = path.join(tempDir.path, 'kernel.dill');
|
||||
final String snapshotFile = (kind == Kind.aot
|
||||
? outputFile
|
||||
: path.join(tempDir.path, 'snapshot.aot'));
|
||||
|
||||
if (verbose) {
|
||||
print('Generating AOT kernel dill.');
|
||||
}
|
||||
|
||||
final kernelResult = await generateAotKernel(dart, genKernel,
|
||||
productPlatformDill, sourceFile, kernelFile, packages, defines);
|
||||
if (kernelResult.exitCode != 0) {
|
||||
stderr.writeln(kernelResult.stdout);
|
||||
stderr.writeln(kernelResult.stderr);
|
||||
await stderr.flush();
|
||||
throw 'Generating AOT kernel dill failed!';
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
print('Generating AOT snapshot.');
|
||||
}
|
||||
final snapshotResult = await generateAotSnapshot(genSnapshot, kernelFile,
|
||||
snapshotFile, debugFile, enableAsserts, extraGenSnapshotOptions);
|
||||
if (snapshotResult.exitCode != 0) {
|
||||
stderr.writeln(snapshotResult.stdout);
|
||||
stderr.writeln(snapshotResult.stderr);
|
||||
await stderr.flush();
|
||||
throw 'Generating AOT snapshot failed!';
|
||||
}
|
||||
|
||||
if (kind == Kind.exe) {
|
||||
if (verbose) {
|
||||
print('Generating executable.');
|
||||
}
|
||||
await writeAppendedExecutable(dartaotruntime, snapshotFile, outputFile);
|
||||
|
||||
if (Platform.isLinux || Platform.isMacOS) {
|
||||
if (verbose) {
|
||||
print('Marking binary executable.');
|
||||
}
|
||||
await markExecutable(outputFile);
|
||||
}
|
||||
}
|
||||
|
||||
print('Generated: ${outputFile}');
|
||||
} finally {
|
||||
tempDir.deleteSync(recursive: true);
|
||||
}
|
||||
}
|
||||
import 'package:dart2native/generate.dart';
|
||||
|
||||
void printUsage(final ArgParser parser) {
|
||||
print('''
|
||||
|
@ -95,7 +19,7 @@ Generates an executable or an AOT snapshot from <main-dart-file>.
|
|||
|
||||
Future<void> main(List<String> args) async {
|
||||
// If we're outputting to a terminal, wrap usage text to that width.
|
||||
int outputLineWidth = null;
|
||||
int outputLineWidth;
|
||||
try {
|
||||
outputLineWidth = stdout.terminalColumns;
|
||||
} catch (_) {/* Ignore. */}
|
||||
|
@ -159,42 +83,25 @@ Remove debugging information from the output and save it separately to the speci
|
|||
exit(1);
|
||||
}
|
||||
|
||||
final Kind kind = {
|
||||
'aot': Kind.aot,
|
||||
'exe': Kind.exe,
|
||||
}[parsedArgs['output-kind']];
|
||||
|
||||
final sourcePath = path.canonicalize(path.normalize(parsedArgs.rest[0]));
|
||||
final sourceWithoutDart = sourcePath.replaceFirst(new RegExp(r'\.dart$'), '');
|
||||
final outputPath =
|
||||
path.canonicalize(path.normalize(parsedArgs['output'] != null
|
||||
? parsedArgs['output']
|
||||
: {
|
||||
Kind.aot: '${sourceWithoutDart}.aot',
|
||||
Kind.exe: '${sourceWithoutDart}.exe',
|
||||
}[kind]));
|
||||
final debugPath = parsedArgs['save-debugging-info'] != null
|
||||
? path.canonicalize(path.normalize(parsedArgs['save-debugging-info']))
|
||||
: null;
|
||||
|
||||
if (!FileSystemEntity.isFileSync(sourcePath)) {
|
||||
final String sourceFile = parsedArgs.rest[0];
|
||||
if (!FileSystemEntity.isFileSync(sourceFile)) {
|
||||
stderr.writeln(
|
||||
'"${sourcePath}" is not a file. See \'--help\' for more information.');
|
||||
'"${sourceFile}" is not a file. See \'--help\' for more information.');
|
||||
await stderr.flush();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
await generateNative(
|
||||
kind,
|
||||
sourcePath,
|
||||
outputPath,
|
||||
debugPath,
|
||||
parsedArgs['packages'],
|
||||
parsedArgs['define'],
|
||||
parsedArgs['enable-asserts'],
|
||||
parsedArgs['verbose'],
|
||||
parsedArgs['extra-gen-snapshot-options']);
|
||||
kind: parsedArgs['output-kind'],
|
||||
sourceFile: sourceFile,
|
||||
outputFile: parsedArgs['output'],
|
||||
debugFile: parsedArgs['save-debugging-info'],
|
||||
packages: parsedArgs['packages'],
|
||||
defines: parsedArgs['define'],
|
||||
enableAsserts: parsedArgs['enable-asserts'],
|
||||
verbose: parsedArgs['verbose'],
|
||||
extraOptions: parsedArgs['extra-gen-snapshot-options']);
|
||||
} catch (e) {
|
||||
stderr.writeln('Failed to generate native files:');
|
||||
stderr.writeln(e);
|
||||
|
|
|
@ -21,7 +21,7 @@ Future writeAppendedExecutable(
|
|||
final offset = dartaotruntimeLength + padding;
|
||||
|
||||
// Note: The offset is always Little Endian regardless of host.
|
||||
final offsetBytes = new ByteData(8) // 64 bit in bytes.
|
||||
final offsetBytes = ByteData(8) // 64 bit in bytes.
|
||||
..setUint64(0, offset, Endian.little);
|
||||
|
||||
final outputFile = File(outputPath).openWrite();
|
||||
|
|
97
pkg/dart2native/lib/generate.dart
Normal file
97
pkg/dart2native/lib/generate.dart
Normal file
|
@ -0,0 +1,97 @@
|
|||
// Copyright (c) 2020, 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:path/path.dart' as path;
|
||||
import 'dart2native.dart';
|
||||
|
||||
final Directory binDir = File(Platform.resolvedExecutable).parent;
|
||||
final String executableSuffix = Platform.isWindows ? '.exe' : '';
|
||||
final String dartaotruntime =
|
||||
path.join(binDir.path, 'dartaotruntime${executableSuffix}');
|
||||
final String genKernel =
|
||||
path.join(binDir.path, 'snapshots', 'gen_kernel.dart.snapshot');
|
||||
final String genSnapshot =
|
||||
path.join(binDir.path, 'utils', 'gen_snapshot${executableSuffix}');
|
||||
final String productPlatformDill = path.join(
|
||||
binDir.parent.path, 'lib', '_internal', 'vm_platform_strong_product.dill');
|
||||
|
||||
Future<void> generateNative({
|
||||
String kind = 'exe',
|
||||
String sourceFile,
|
||||
String outputFile,
|
||||
String debugFile,
|
||||
String packages,
|
||||
List<String> defines,
|
||||
bool enableAsserts = false,
|
||||
bool verbose = false,
|
||||
List<String> extraOptions = const [],
|
||||
}) async {
|
||||
final Directory tempDir = Directory.systemTemp.createTempSync();
|
||||
try {
|
||||
final sourcePath = path.canonicalize(path.normalize(sourceFile));
|
||||
final Kind outputKind = {
|
||||
'aot': Kind.aot,
|
||||
'exe': Kind.exe,
|
||||
}[kind];
|
||||
final sourceWithoutDart = sourcePath.replaceFirst(RegExp(r'\.dart$'), '');
|
||||
final outputPath = path.canonicalize(path.normalize(outputFile != null
|
||||
? outputFile
|
||||
: {
|
||||
Kind.aot: '${sourceWithoutDart}.aot',
|
||||
Kind.exe: '${sourceWithoutDart}.exe',
|
||||
}[outputKind]));
|
||||
final debugPath =
|
||||
debugFile != null ? path.canonicalize(path.normalize(debugFile)) : null;
|
||||
|
||||
if (verbose) {
|
||||
print('Compiling $sourcePath to $outputPath using format $kind:');
|
||||
print('Generating AOT kernel dill.');
|
||||
}
|
||||
|
||||
final String kernelFile = path.join(tempDir.path, 'kernel.dill');
|
||||
final kernelResult = await generateAotKernel(Platform.executable, genKernel,
|
||||
productPlatformDill, sourcePath, kernelFile, packages, defines);
|
||||
if (kernelResult.exitCode != 0) {
|
||||
stderr.writeln(kernelResult.stdout);
|
||||
stderr.writeln(kernelResult.stderr);
|
||||
await stderr.flush();
|
||||
throw 'Generating AOT kernel dill failed!';
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
print('Generating AOT snapshot.');
|
||||
}
|
||||
|
||||
final String snapshotFile = (outputKind == Kind.aot
|
||||
? outputPath
|
||||
: path.join(tempDir.path, 'snapshot.aot'));
|
||||
final snapshotResult = await generateAotSnapshot(genSnapshot, kernelFile,
|
||||
snapshotFile, debugPath, enableAsserts, extraOptions);
|
||||
if (snapshotResult.exitCode != 0) {
|
||||
stderr.writeln(snapshotResult.stdout);
|
||||
stderr.writeln(snapshotResult.stderr);
|
||||
await stderr.flush();
|
||||
throw 'Generating AOT snapshot failed!';
|
||||
}
|
||||
|
||||
if (outputKind == Kind.exe) {
|
||||
if (verbose) {
|
||||
print('Generating executable.');
|
||||
}
|
||||
await writeAppendedExecutable(dartaotruntime, snapshotFile, outputPath);
|
||||
|
||||
if (Platform.isLinux || Platform.isMacOS) {
|
||||
if (verbose) {
|
||||
print('Marking binary executable.');
|
||||
}
|
||||
await markExecutable(outputPath);
|
||||
}
|
||||
}
|
||||
|
||||
print('Generated: ${outputPath}');
|
||||
} finally {
|
||||
tempDir.deleteSync(recursive: true);
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@ linter:
|
|||
- prefer_inlined_adds
|
||||
- prefer_interpolation_to_compose_strings
|
||||
- prefer_is_not_operator
|
||||
- prefer_final_fields
|
||||
- prefer_null_aware_operators
|
||||
- prefer_relative_imports
|
||||
- prefer_typing_uninitialized_variables
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'package:usage/usage.dart';
|
|||
|
||||
import 'src/analytics.dart';
|
||||
import 'src/commands/analyze.dart';
|
||||
import 'src/commands/compile.dart';
|
||||
import 'src/commands/create.dart';
|
||||
import 'src/commands/format.dart';
|
||||
import 'src/commands/pub.dart';
|
||||
|
@ -160,6 +161,7 @@ class DartdevRunner<int> extends CommandRunner {
|
|||
|
||||
addCommand(AnalyzeCommand(verbose: verbose));
|
||||
addCommand(CreateCommand(verbose: verbose));
|
||||
addCommand(CompileCommand(verbose: verbose));
|
||||
addCommand(FormatCommand(verbose: verbose));
|
||||
addCommand(MigrateCommand(verbose: verbose));
|
||||
addCommand(PubCommand(verbose: verbose));
|
||||
|
|
244
pkg/dartdev/lib/src/commands/compile.dart
Normal file
244
pkg/dartdev/lib/src/commands/compile.dart
Normal file
|
@ -0,0 +1,244 @@
|
|||
// Copyright (c) 2020, 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:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:dart2native/generate.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import '../core.dart';
|
||||
import '../sdk.dart';
|
||||
|
||||
const int compileErrorExitCode = 64;
|
||||
|
||||
class Option {
|
||||
final String flag;
|
||||
final String help;
|
||||
final String abbr;
|
||||
Option({this.flag, this.help, this.abbr});
|
||||
}
|
||||
|
||||
final Map<String, Option> commonOptions = {
|
||||
'outputFile': Option(
|
||||
flag: 'output',
|
||||
abbr: 'o',
|
||||
help: '''
|
||||
Write the output to <file name>.
|
||||
This can be an absolute or reletive path.
|
||||
''',
|
||||
),
|
||||
};
|
||||
|
||||
bool checkFile(String sourcePath) {
|
||||
if (!FileSystemEntity.isFileSync(sourcePath)) {
|
||||
stderr.writeln(
|
||||
'"$sourcePath" is not a file. See \'--help\' for more information.');
|
||||
stderr.flush();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class CompileJSCommand extends DartdevCommand<int> {
|
||||
bool verbose = false;
|
||||
CompileJSCommand({
|
||||
this.verbose,
|
||||
}) : super('js', 'Compile Dart to JavaScript') {
|
||||
argParser
|
||||
..addOption(
|
||||
commonOptions['outputFile'].flag,
|
||||
help: commonOptions['outputFile'].help,
|
||||
abbr: commonOptions['outputFile'].abbr,
|
||||
)
|
||||
..addFlag(
|
||||
'minified',
|
||||
help: 'Generate minified output.',
|
||||
abbr: 'm',
|
||||
negatable: false,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String get invocation => '${super.invocation} <dart entry point>';
|
||||
|
||||
@override
|
||||
FutureOr<int> run() async {
|
||||
// We expect a single rest argument; the dart entry point.
|
||||
if (argResults.rest.length != 1) {
|
||||
log.stderr('Missing Dart entry point.');
|
||||
printUsage();
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
final String sourcePath = argResults.rest[0];
|
||||
if (!checkFile(sourcePath)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final process = await startProcess(sdk.dart2js, argResults.arguments);
|
||||
routeToStdout(process);
|
||||
return process.exitCode;
|
||||
}
|
||||
}
|
||||
|
||||
class CompileSnapshotCommand extends DartdevCommand<int> {
|
||||
bool verbose = false;
|
||||
final String commandName;
|
||||
final String help;
|
||||
final String fileExt;
|
||||
final String formatName;
|
||||
|
||||
CompileSnapshotCommand({
|
||||
this.verbose,
|
||||
this.commandName,
|
||||
this.help,
|
||||
this.fileExt,
|
||||
this.formatName,
|
||||
}) : super(commandName, 'Compile Dart $help') {
|
||||
argParser
|
||||
..addOption(
|
||||
commonOptions['outputFile'].flag,
|
||||
help: commonOptions['outputFile'].help,
|
||||
abbr: commonOptions['outputFile'].abbr,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String get invocation => '${super.invocation} <dart entry point>';
|
||||
|
||||
@override
|
||||
FutureOr<int> run() async {
|
||||
// We expect a single rest argument; the dart entry point.
|
||||
if (argResults.rest.length != 1) {
|
||||
log.stderr('Missing Dart entry point.');
|
||||
printUsage();
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
final String sourcePath = argResults.rest[0];
|
||||
if (!checkFile(sourcePath)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Determine output file name.
|
||||
String outputFile = argResults[commonOptions['outputFile'].flag];
|
||||
if (outputFile == null) {
|
||||
final inputWithoutDart = sourcePath.replaceFirst(RegExp(r'\.dart$'), '');
|
||||
outputFile = '$inputWithoutDart.$fileExt';
|
||||
}
|
||||
|
||||
// Build arguments.
|
||||
List<String> args = [];
|
||||
args.add('--snapshot-kind=$formatName');
|
||||
args.add('--snapshot=${path.canonicalize(outputFile)}');
|
||||
if (verbose) {
|
||||
args.add('-v');
|
||||
}
|
||||
args.add(path.canonicalize(sourcePath));
|
||||
|
||||
log.stdout('Compiling $sourcePath to $commandName file $outputFile.');
|
||||
final process = await startProcess(sdk.dart, args);
|
||||
routeToStdout(process);
|
||||
return process.exitCode;
|
||||
}
|
||||
}
|
||||
|
||||
class CompileNativeCommand extends DartdevCommand<int> {
|
||||
bool verbose = false;
|
||||
final String commandName;
|
||||
final String format;
|
||||
final String help;
|
||||
|
||||
CompileNativeCommand({
|
||||
this.verbose,
|
||||
this.commandName,
|
||||
this.format,
|
||||
this.help,
|
||||
}) : super(commandName, 'Compile Dart $help') {
|
||||
argParser
|
||||
..addOption(
|
||||
commonOptions['outputFile'].flag,
|
||||
help: commonOptions['outputFile'].help,
|
||||
abbr: commonOptions['outputFile'].abbr,
|
||||
)
|
||||
..addMultiOption('define', abbr: 'D', valueHelp: 'key=value', help: '''
|
||||
Set values of environment variables. To specify multiple variables, use multiple options or use commas to separate key-value pairs.
|
||||
E.g.: dart2native -Da=1,b=2 main.dart''')
|
||||
..addFlag('enable-asserts',
|
||||
negatable: false, help: 'Enable assert statements.')
|
||||
..addOption('packages', abbr: 'p', valueHelp: 'path', help: '''
|
||||
Get package locations from the specified file instead of .packages. <path> can be relative or absolute.
|
||||
E.g.: dart2native --packages=/tmp/pkgs main.dart
|
||||
''')
|
||||
..addOption('save-debugging-info', abbr: 'S', valueHelp: 'path', help: '''
|
||||
Remove debugging information from the output and save it separately to the specified file. <path> can be relative or absolute.
|
||||
''');
|
||||
}
|
||||
|
||||
@override
|
||||
String get invocation => '${super.invocation} <dart entry point>';
|
||||
|
||||
@override
|
||||
FutureOr<int> run() async {
|
||||
// We expect a single rest argument; the dart entry point.
|
||||
if (argResults.rest.length != 1) {
|
||||
log.stderr('Missing Dart entry point.');
|
||||
printUsage();
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
final String sourcePath = argResults.rest[0];
|
||||
if (!checkFile(sourcePath)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
await generateNative(
|
||||
kind: format,
|
||||
sourceFile: sourcePath,
|
||||
outputFile: argResults['output'],
|
||||
defines: argResults['define'],
|
||||
packages: argResults['packages'],
|
||||
enableAsserts: argResults['enable-asserts'],
|
||||
debugFile: argResults['save-debugging-info'],
|
||||
verbose: verbose,
|
||||
);
|
||||
return 0;
|
||||
} catch (e) {
|
||||
log.stderr('Error: AOT compilation failed');
|
||||
log.stderr(e);
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CompileCommand extends Command {
|
||||
@override
|
||||
String get description => 'Compile Dart to various formats.';
|
||||
@override
|
||||
String get name => 'compile';
|
||||
|
||||
CompileCommand({bool verbose = false}) {
|
||||
addSubcommand(CompileJSCommand());
|
||||
addSubcommand(CompileSnapshotCommand(
|
||||
commandName: 'jit-snapshot',
|
||||
help: 'to a JIT snapshot',
|
||||
fileExt: 'jit',
|
||||
formatName: 'app-jit',
|
||||
verbose: verbose,
|
||||
));
|
||||
addSubcommand(CompileNativeCommand(
|
||||
commandName: 'exe',
|
||||
help: 'to a self-contained executable',
|
||||
format: 'exe',
|
||||
verbose: verbose,
|
||||
));
|
||||
addSubcommand(CompileNativeCommand(
|
||||
commandName: 'aot-snapshot',
|
||||
help: 'to an AOT snapshot',
|
||||
format: 'aot',
|
||||
verbose: verbose,
|
||||
));
|
||||
}
|
||||
}
|
|
@ -48,6 +48,8 @@ class Sdk {
|
|||
String get analysisServerSnapshot => path.absolute(
|
||||
sdkPath, 'bin', 'snapshots', 'analysis_server.dart.snapshot');
|
||||
|
||||
String get dart2js => path.absolute(sdkPath, 'bin', _binName('dart2js'));
|
||||
|
||||
String get dartfmt => path.absolute(sdkPath, 'bin', _binName('dartfmt'));
|
||||
|
||||
String get pub => path.absolute(sdkPath, 'bin', _binName('pub'));
|
||||
|
|
180
pkg/dartdev/test/commands/compile_test.dart
Normal file
180
pkg/dartdev/test/commands/compile_test.dart
Normal file
|
@ -0,0 +1,180 @@
|
|||
// Copyright (c) 2020, 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:path/path.dart' as path;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../utils.dart';
|
||||
|
||||
const int compileErrorExitCode = 64;
|
||||
|
||||
void main() {
|
||||
group('compile', defineCompileTests, timeout: longTimeout);
|
||||
}
|
||||
|
||||
void defineCompileTests() {
|
||||
// *** NOTE ***: These tests *must* be run with the `--use-sdk` option
|
||||
// as they depend on a fully built SDK to resolve various snapshot files
|
||||
// used by compilation.
|
||||
test('Running from built SDK', () {
|
||||
final Directory binDir = File(Platform.resolvedExecutable).parent;
|
||||
expect(binDir.path, contains('bin'));
|
||||
});
|
||||
|
||||
test('Implicit --help', () {
|
||||
final p = project();
|
||||
var result = p.runSync(
|
||||
'compile',
|
||||
[],
|
||||
);
|
||||
expect(result.stderr, contains('Compile Dart'));
|
||||
expect(result.exitCode, compileErrorExitCode);
|
||||
});
|
||||
|
||||
test('--help', () {
|
||||
final p = project();
|
||||
final result = p.runSync(
|
||||
'compile',
|
||||
['--help'],
|
||||
);
|
||||
expect(result.stdout, contains('Compile Dart'));
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
|
||||
test('Compile and run jit snapshot', () {
|
||||
final p = project(mainSrc: 'void main() { print("I love jit"); }');
|
||||
final outFile = path.join(p.dirPath, 'main.jit');
|
||||
var result = p.runSync(
|
||||
'compile',
|
||||
[
|
||||
'jit-snapshot',
|
||||
'-o',
|
||||
outFile,
|
||||
p.relativeFilePath,
|
||||
],
|
||||
);
|
||||
expect(File(outFile).existsSync(), true,
|
||||
reason: 'File not found: $outFile');
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
|
||||
result = p.runSync('run', ['main.jit']);
|
||||
expect(result.stdout, contains('I love jit'));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
|
||||
test('Compile and run executable', () {
|
||||
final p = project(mainSrc: 'void main() { print("I love executables"); }');
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'lib', 'main.exe'));
|
||||
|
||||
var result = p.runSync(
|
||||
'compile',
|
||||
[
|
||||
'exe',
|
||||
inFile,
|
||||
],
|
||||
);
|
||||
|
||||
expect(File(outFile).existsSync(), true,
|
||||
reason: 'File not found: $outFile');
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
|
||||
result = Process.runSync(
|
||||
outFile,
|
||||
[],
|
||||
);
|
||||
|
||||
expect(result.stdout, contains('I love executables'));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
|
||||
test('Compile and run executable with options', () {
|
||||
final p = project(
|
||||
mainSrc: 'void main() {print(const String.fromEnvironment("life"));}');
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
|
||||
|
||||
var result = p.runSync(
|
||||
'compile',
|
||||
[
|
||||
'exe',
|
||||
'--define',
|
||||
'life=42',
|
||||
'-o',
|
||||
outFile,
|
||||
inFile,
|
||||
],
|
||||
);
|
||||
|
||||
expect(File(outFile).existsSync(), true,
|
||||
reason: 'File not found: $outFile');
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
|
||||
result = Process.runSync(
|
||||
outFile,
|
||||
[],
|
||||
);
|
||||
|
||||
expect(result.stdout, contains('42'));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
|
||||
test('Compile and run aot snapshot', () {
|
||||
final p = project(mainSrc: 'void main() { print("I love AOT"); }');
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'main.aot'));
|
||||
|
||||
var result = p.runSync(
|
||||
'compile',
|
||||
[
|
||||
'aot-snapshot',
|
||||
'-o',
|
||||
'main.aot',
|
||||
inFile,
|
||||
],
|
||||
);
|
||||
|
||||
expect(File(outFile).existsSync(), true,
|
||||
reason: 'File not found: $outFile');
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
|
||||
final Directory binDir = File(Platform.resolvedExecutable).parent;
|
||||
result = Process.runSync(
|
||||
path.join(binDir.path, 'dartaotruntime'),
|
||||
[outFile],
|
||||
);
|
||||
|
||||
expect(result.stdout, contains('I love AOT'));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
|
||||
test('Compile JS', () {
|
||||
final p = project(mainSrc: "void main() { print('Hello from JS'); }");
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, 'main.js'));
|
||||
|
||||
final result = p.runSync('compile', [
|
||||
'js',
|
||||
'-m',
|
||||
'-o',
|
||||
outFile,
|
||||
'-v',
|
||||
inFile,
|
||||
]);
|
||||
expect(File(outFile).existsSync(), true,
|
||||
reason: 'File not found: $outFile');
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
}
|
|
@ -57,6 +57,7 @@ void help() {
|
|||
expect(result.stdout, contains('Available commands:'));
|
||||
expect(result.stdout, contains('analyze '));
|
||||
expect(result.stdout, contains('create '));
|
||||
expect(result.stdout, contains('compile '));
|
||||
expect(result.stdout, contains('format '));
|
||||
expect(result.stdout, contains('migrate '));
|
||||
});
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:test/test.dart';
|
|||
|
||||
import 'analytics_test.dart' as analytics;
|
||||
import 'commands/analyze_test.dart' as analyze;
|
||||
import 'commands/compile_test.dart' as compile;
|
||||
import 'commands/create_test.dart' as create;
|
||||
import 'commands/flag_test.dart' as flag;
|
||||
import 'commands/format_test.dart' as format;
|
||||
|
@ -29,6 +30,7 @@ void main() {
|
|||
migrate.main();
|
||||
pub.main();
|
||||
run.main();
|
||||
compile.main();
|
||||
test.main();
|
||||
core.main();
|
||||
sdk.main();
|
||||
|
|
Loading…
Reference in a new issue