ee8d2322d4
Change-Id: I63aac10df5e26155f394623308a03c1977eba1e3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106400 Reviewed-by: Vijay Menon <vsm@google.com> Commit-Queue: Bob Nystrom <rnystrom@google.com>
281 lines
9.0 KiB
Dart
Executable File
281 lines
9.0 KiB
Dart
Executable File
#!/usr/bin/env dart
|
|
// Copyright (c) 2018, 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.
|
|
|
|
//
|
|
// Compiles code with DDC and runs the resulting code with either node or
|
|
// chrome.
|
|
//
|
|
// The first script supplied should be the one with `main()`.
|
|
//
|
|
// Saves the output in the same directory as the sources for convenient
|
|
// inspection, modification or rerunning the code.
|
|
|
|
import 'dart:io';
|
|
|
|
import 'package:args/args.dart' show ArgParser;
|
|
import 'package:path/path.dart' as path;
|
|
|
|
void main(List<String> args) async {
|
|
void printUsage() {
|
|
print('Usage: ddb [options] <dart-script-file>\n');
|
|
print('Compiles <dart-script-file> with the dev_compiler and runs it on a '
|
|
'JS platform.\n');
|
|
}
|
|
|
|
// Parse flags.
|
|
var parser = new ArgParser()
|
|
..addFlag('help', abbr: 'h', help: 'Display this message.')
|
|
..addFlag('kernel',
|
|
abbr: 'k', help: 'Compile with the new kernel-based front end.')
|
|
..addMultiOption('summary',
|
|
abbr: 's',
|
|
help: 'summary file(s) of imported libraries, optionally\n'
|
|
'with module import path: -s path.sum=js/import/path')
|
|
..addFlag('debug',
|
|
abbr: 'd',
|
|
help: 'Use current source instead of built SDK.',
|
|
defaultsTo: false)
|
|
..addOption('runtime',
|
|
abbr: 'r',
|
|
help: 'Platform to run on (node|d8|chrome). Default is node.',
|
|
allowed: ['node', 'd8', 'chrome'],
|
|
defaultsTo: 'node')
|
|
..addOption('port',
|
|
abbr: 'p',
|
|
help: 'Run with the corresponding chrome/V8 debugging port open.',
|
|
defaultsTo: '9222')
|
|
..addMultiOption('enable-experiment',
|
|
help: 'Run with specified experiments enabled.')
|
|
..addOption('binary', abbr: 'b', help: 'Runtime binary path.');
|
|
|
|
var options = parser.parse(args);
|
|
if (options['help']) {
|
|
printUsage();
|
|
print('Available options:');
|
|
print(parser.usage);
|
|
exit(0);
|
|
}
|
|
if (options.rest.length != 1) {
|
|
print('Dart script file required.\n');
|
|
printUsage();
|
|
exit(1);
|
|
}
|
|
var entry = options.rest.first;
|
|
var libRoot = path.dirname(entry);
|
|
var basename = path.basenameWithoutExtension(entry);
|
|
|
|
var debug = options['debug'] as bool;
|
|
var kernel = options['kernel'] as bool;
|
|
var binary = options['binary'] as String;
|
|
var experiments = options['enable-experiment'] as List;
|
|
var summaries = options['summary'] as List;
|
|
var port = int.parse(options['port'] as String);
|
|
|
|
// By default (no `-d`), we use the `dartdevc` binary on the user's path to
|
|
// compute the SDK we use for execution. I.e., we assume that `dart` is
|
|
// under `$DART_SDK/bin/dart` and use that to find `dartdevc` and related
|
|
// artifacts. In this mode, this script can run against any installed SDK.
|
|
// If you want to run against a freshly built SDK, that must be first on
|
|
// your path.
|
|
var dartBinary = Platform.resolvedExecutable;
|
|
var dartSdk = path.dirname(path.dirname(dartBinary));
|
|
|
|
// In debug mode (`-d`), we run from the `pkg/dev_compiler` sources. We
|
|
// determine the location via this actual script (i.e., `-d` assumes
|
|
// this script remains under to `tool` sub-directory).
|
|
var toolPath = Platform.script.normalizePath().toFilePath();
|
|
var ddcPath = path.dirname(path.dirname(toolPath));
|
|
var dartCheckoutPath = path.dirname(path.dirname(ddcPath));
|
|
|
|
ProcessResult runDdc(String command, List<String> args) {
|
|
if (debug) {
|
|
// Use unbuilt script. This only works from a source checkout.
|
|
args.insertAll(0,
|
|
['--enable-asserts', path.join(ddcPath, 'bin', '${command}.dart')]);
|
|
command = dartBinary;
|
|
} else {
|
|
// Use built snapshot.
|
|
command = path.join(dartSdk, 'bin', command);
|
|
}
|
|
return Process.runSync(command, args);
|
|
}
|
|
|
|
/// Writes stdout and stderr from [result] to this process.
|
|
///
|
|
/// Will exit with the exit code from [result] when it's not zero.
|
|
void echoResult(ProcessResult result) async {
|
|
stdout.write(result.stdout);
|
|
await stdout.flush();
|
|
stderr.write(result.stderr);
|
|
await stderr.flush();
|
|
if (result.exitCode != 0) exit(result.exitCode);
|
|
}
|
|
|
|
String mod;
|
|
bool chrome = false;
|
|
bool node = false;
|
|
bool d8 = false;
|
|
switch (options['runtime']) {
|
|
case 'node':
|
|
node = true;
|
|
mod = 'common';
|
|
break;
|
|
case 'd8':
|
|
d8 = true;
|
|
mod = 'es6';
|
|
break;
|
|
case 'chrome':
|
|
chrome = true;
|
|
mod = 'amd';
|
|
break;
|
|
}
|
|
|
|
String sdkJsPath;
|
|
String requirePath;
|
|
String ddcSdk;
|
|
if (debug) {
|
|
var sdkRoot = path.dirname(path.dirname(ddcPath));
|
|
var buildDir = path.join(sdkRoot, Platform.isMacOS ? 'xcodebuild' : 'out');
|
|
sdkJsPath = path.join(buildDir, 'ReleaseX64', 'gen', 'utils', 'dartdevc',
|
|
kernel ? 'kernel' : 'js', mod);
|
|
requirePath = path.join(sdkRoot, 'third_party', 'requirejs');
|
|
ddcSdk = path.join(buildDir, 'ReleaseX64', 'gen', 'utils', 'dartdevc',
|
|
kernel ? path.join('kernel', 'ddc_sdk.dill') : 'ddc_sdk.sum');
|
|
} else {
|
|
var suffix = kernel ? path.join('kernel', mod) : mod;
|
|
sdkJsPath = path.join(dartSdk, 'lib', 'dev_compiler', suffix);
|
|
requirePath = sdkJsPath;
|
|
ddcSdk = path.join(
|
|
dartSdk, 'lib', '_internal', kernel ? 'ddc_sdk.dill' : 'ddc_sdk.sum');
|
|
}
|
|
ProcessResult result;
|
|
var ddcArgs = [
|
|
if (kernel) '--kernel',
|
|
'--modules=$mod',
|
|
'--dart-sdk-summary=$ddcSdk',
|
|
// TODO(nshahan) Cleanup when we settle on using or removing library-root.
|
|
if (!kernel)
|
|
'--library-root=$libRoot',
|
|
for (var summary in summaries) '--summary=$summary',
|
|
for (var experiment in experiments) '--enable-experiment=$experiment',
|
|
'-o',
|
|
'$libRoot/$basename.js',
|
|
entry
|
|
];
|
|
|
|
result = runDdc('dartdevc', ddcArgs);
|
|
await echoResult(result);
|
|
|
|
if (chrome) {
|
|
String chromeBinary;
|
|
if (binary != null) {
|
|
chromeBinary = binary;
|
|
} else if (Platform.isWindows) {
|
|
chromeBinary =
|
|
'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe';
|
|
} else if (Platform.isMacOS) {
|
|
chromeBinary =
|
|
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
|
|
} else {
|
|
// Assume Linux
|
|
chromeBinary = 'google-chrome';
|
|
}
|
|
|
|
var html = """
|
|
<script src='$requirePath/require.js'></script>
|
|
<script>
|
|
require.config({
|
|
baseUrl: '$libRoot',
|
|
paths: {
|
|
'dart_sdk': '$sdkJsPath/dart_sdk'
|
|
},
|
|
waitSeconds: 15
|
|
});
|
|
require(['dart_sdk', '$basename'],
|
|
function(sdk, app) {
|
|
'use strict';
|
|
sdk._debugger.registerDevtoolsFormatter();
|
|
app.$basename.main();
|
|
});
|
|
</script>
|
|
""";
|
|
var htmlFile = '$libRoot/$basename.html';
|
|
new File(htmlFile).writeAsStringSync(html);
|
|
var tmp = path.join(Directory.systemTemp.path, 'ddc');
|
|
|
|
result = Process.runSync(chromeBinary, [
|
|
'--auto-open-devtools-for-tabs',
|
|
'--allow-file-access-from-files',
|
|
'--remote-debugging-port=$port',
|
|
'--user-data-dir=$tmp',
|
|
htmlFile
|
|
]);
|
|
} else if (node) {
|
|
var nodePath = '$sdkJsPath:$libRoot';
|
|
var runjs = '''
|
|
let source_maps;
|
|
try {
|
|
source_maps = require('source-map-support');
|
|
source_maps.install();
|
|
} catch(e) {
|
|
}
|
|
let sdk = require(\"dart_sdk\");
|
|
let main = require(\"./$basename\").$basename.main;
|
|
try {
|
|
sdk._isolate_helper.startRootIsolate(main, []);
|
|
} catch(e) {
|
|
if (!source_maps) {
|
|
console.log('For Dart source maps: npm install source-map-support');
|
|
}
|
|
console.error(e);
|
|
process.exit(1);
|
|
}
|
|
''';
|
|
var nodeFile = '$libRoot/$basename.run.js';
|
|
new File(nodeFile).writeAsStringSync(runjs);
|
|
var nodeBinary = binary ?? 'node';
|
|
result = Process.runSync(
|
|
nodeBinary, ['--inspect=localhost:$port', nodeFile],
|
|
environment: {'NODE_PATH': nodePath});
|
|
} else if (d8) {
|
|
// Fix SDK import. `d8` doesn't let us set paths, so we need a full path
|
|
// to the SDK.
|
|
|
|
var jsFile = File('$libRoot/$basename.js');
|
|
var jsContents = jsFile.readAsStringSync();
|
|
jsContents = jsContents.replaceFirst(
|
|
"from 'dart_sdk.js'", "from '$sdkJsPath/dart_sdk.js'");
|
|
jsFile.writeAsStringSync(jsContents);
|
|
|
|
var runjs = '''
|
|
import { dart, _isolate_helper } from '$sdkJsPath/dart_sdk.js';
|
|
import { $basename } from '$basename.js';
|
|
let main = $basename.main;
|
|
try {
|
|
_isolate_helper.startRootIsolate(() => {}, []);
|
|
main();
|
|
} catch(e) {
|
|
console.error(e);
|
|
}
|
|
''';
|
|
var d8File = path.join(libRoot, '$basename.d8.js');
|
|
new File(d8File).writeAsStringSync(runjs);
|
|
var d8Binary = binary ?? path.join(dartCheckoutPath, _d8executable);
|
|
result = Process.runSync(d8Binary, ['--module', d8File]);
|
|
}
|
|
await echoResult(result);
|
|
}
|
|
|
|
String get _d8executable {
|
|
if (Platform.isWindows) {
|
|
return path.join('third_party', 'd8', 'windows', 'd8.exe');
|
|
} else if (Platform.isLinux) {
|
|
return path.join('third_party', 'd8', 'linux', 'd8');
|
|
} else if (Platform.isMacOS) {
|
|
return path.join('third_party', 'd8', 'macos', 'd8');
|
|
}
|
|
throw new UnsupportedError('Unsupported platform.');
|
|
}
|