cf8a477cb7
This allows dartdevk to compile tests that import packages like expect.
There are a few pieces to this:
- Add support to build_pkgs.dart to build the kernel summaries for each
test package (in addition to the analyzer summaries it already
builds).
- Plumb that through the dartdevc_test target in the GN build as well.
- While we're at it, use GN to build the ddc_sdk.dill file and have
test.dart load that one instead of the manually built one from calling
./tool/kernel_sdk.dart.
- Add command-line arguments to dartdevk for passing in the path to the
SDK summary and the other summaries to compile against.
- Fix a little typo in processed_options.dart that was preventing it
from resolving "package:" URIs.
- In test.dart, when compiling a test, link in the summaries for all of
the test packages.
At runtime, it still uses the JS for those packages generated from the
old analyzer-based front end since the kernel-based compiler isn't
complete enough to compile any of those packages yet.
With all of this, if I change a test to:
import "package:expect/expect.dart";
main() {
Expect.equals("a", "b");
}
Then it compiles but fails at runtime. The compiler is completing, but
the generated code has some bugs. I don't know enough to fix them
myself, but here's what I've found out:
- In _libraryToModule(), the Library we get from kernel has a null
fileUri, so this returns an empty string. That in turn means the
generated JS tries to use "$" as the module name.
Using this works around it temporarily:
if (moduleName.isEmpty) moduleName = library.name;
- In _emitTopLevelNameNoInterop(), it doesn't handle the case where the
NamedNode is a static method on a class. It just generates the library
and method name, skipping the class, so "Expect.equals(1, 2)" gets
compiled to "expect.equals(1, 2)" instead of
"expect.Expect.equals(1, 2)".
Change-Id: I6bd9d98bc9706965160d8fb7cf70b20eeebab3a8
Reviewed-on: https://dart-review.googlesource.com/16687
Commit-Queue: Bob Nystrom <rnystrom@google.com>
Reviewed-by: Vijay Menon <vsm@google.com>
206 lines
6.3 KiB
Dart
Executable File
206 lines
6.3 KiB
Dart
Executable File
#!/usr/bin/env dart
|
|
import 'dart:async';
|
|
import 'dart:io';
|
|
|
|
import 'package:front_end/compilation_message.dart';
|
|
import 'package:front_end/compiler_options.dart';
|
|
import 'package:front_end/summary_generator.dart';
|
|
import 'package:path/path.dart' as p;
|
|
|
|
import 'package:dev_compiler/src/analyzer/command.dart' as analyzer;
|
|
import 'package:dev_compiler/src/kernel/target.dart';
|
|
|
|
final String scriptDirectory = p.dirname(p.fromUri(Platform.script));
|
|
|
|
/// The directory that output is written to.
|
|
///
|
|
/// The DDC kernel SDK should be directly in this directory. The resulting
|
|
/// packages will be placed in a "pkg" subdirectory of this.
|
|
String outputDirectory;
|
|
|
|
String get pkgDirectory => p.join(outputDirectory, "pkg");
|
|
|
|
/// Compiles the packages that the DDC tests use to JS into the given output
|
|
/// directory. Usage:
|
|
///
|
|
/// dart build_pkgs.dart <output_dir> [travis]
|
|
///
|
|
/// If "travis" is passed, builds the all of the modules tested on Travis.
|
|
/// Otherwise, only builds the modules needed by the tests.
|
|
Future main(List<String> arguments) async {
|
|
var isTravis = arguments.isNotEmpty && arguments.last == "travis";
|
|
if (isTravis) {
|
|
arguments = arguments.sublist(0, arguments.length - 1);
|
|
}
|
|
|
|
if (arguments.length != 1) {
|
|
print("Usage: dart build_pkgs.dart <output_dir> [travis]");
|
|
exit(1);
|
|
}
|
|
|
|
outputDirectory = arguments[0];
|
|
new Directory(pkgDirectory).createSync(recursive: true);
|
|
|
|
// Build leaf packages. These have no other package dependencies.
|
|
|
|
// Under pkg.
|
|
await compileModule('async_helper');
|
|
await compileModule('expect', libs: ['minitest']);
|
|
await compileModule('js', libs: ['js_util']);
|
|
await compileModule('meta');
|
|
if (isTravis) {
|
|
await compileModule('microlytics', libs: ['html_channels']);
|
|
await compileModule('typed_mock');
|
|
}
|
|
|
|
// Under third_party/pkg.
|
|
await compileModule('collection');
|
|
await compileModule('path');
|
|
if (isTravis) {
|
|
await compileModule('args', libs: ['command_runner']);
|
|
await compileModule('charcode');
|
|
await compileModule('fixnum');
|
|
await compileModule('logging');
|
|
await compileModule('markdown');
|
|
await compileModule('mime');
|
|
await compileModule('plugin', libs: ['manager']);
|
|
await compileModule('typed_data');
|
|
await compileModule('usage');
|
|
await compileModule('utf');
|
|
}
|
|
|
|
// Composite packages with dependencies.
|
|
await compileModule('stack_trace', deps: ['path']);
|
|
await compileModule('matcher', deps: ['stack_trace']);
|
|
if (isTravis) {
|
|
await compileModule('async', deps: ['collection']);
|
|
}
|
|
|
|
if (!isTravis) {
|
|
await compileModule('unittest', deps: [
|
|
'matcher',
|
|
'path',
|
|
'stack_trace'
|
|
], libs: [
|
|
'html_config',
|
|
'html_individual_config',
|
|
'html_enhanced_config'
|
|
]);
|
|
}
|
|
}
|
|
|
|
/// Compiles a [module] with a single matching ".dart" library and additional
|
|
/// [libs] and [deps] on other modules.
|
|
Future compileModule(String module,
|
|
{List<String> libs, List<String> deps}) async {
|
|
compileModuleUsingAnalyzer(module, libs, deps);
|
|
await compileKernelSummary(module, libs, deps);
|
|
}
|
|
|
|
void compileModuleUsingAnalyzer(
|
|
String module, List<String> libraries, List<String> dependencies) {
|
|
var sdkSummary = p.join(scriptDirectory, "../lib/sdk/ddc_sdk.sum");
|
|
var args = ['--dart-sdk-summary=$sdkSummary', '-o${pkgDirectory}/$module.js'];
|
|
|
|
// There is always a library that matches the module.
|
|
args.add('package:$module/$module.dart');
|
|
|
|
// Add any additional libraries.
|
|
if (libraries != null) {
|
|
for (var lib in libraries) {
|
|
args.add('package:$module/$lib.dart');
|
|
}
|
|
}
|
|
|
|
// Add summaries for any modules this depends on.
|
|
if (dependencies != null) {
|
|
for (var dep in dependencies) {
|
|
args.add('-s${pkgDirectory}/$dep.sum');
|
|
}
|
|
}
|
|
|
|
// TODO(rnystrom): Hack. DDC has its own forked copy of async_helper that
|
|
// has a couple of differences from pkg/async_helper. We should unfork them,
|
|
// but I'm not sure how they'll affect the other non-DDC tests. For now, just
|
|
// use ours.
|
|
if (module == 'async_helper') {
|
|
args.add('--url-mapping=package:async_helper/async_helper.dart,' +
|
|
p.join(scriptDirectory, "../test/codegen/async_helper.dart"));
|
|
}
|
|
|
|
var exitCode = analyzer.compile(args);
|
|
if (exitCode != 0) exit(exitCode);
|
|
}
|
|
|
|
Future compileKernelSummary(
|
|
String module, List<String> libraries, List<String> dependencies) async {
|
|
var succeeded = true;
|
|
|
|
void errorHandler(CompilationMessage error) {
|
|
if (error.severity == Severity.error) succeeded = false;
|
|
}
|
|
|
|
var sdk = p.toUri(p.join(outputDirectory, "ddc_sdk.dill"));
|
|
print(sdk);
|
|
var options = new CompilerOptions()
|
|
..sdkSummary = sdk
|
|
..packagesFileUri = _uriInRepo(".packages")
|
|
..strongMode = true
|
|
..debugDump = true
|
|
..chaseDependencies = true
|
|
..onError = errorHandler
|
|
..reportMessages = true
|
|
..target = new DevCompilerTarget();
|
|
|
|
var inputs = <Uri>[];
|
|
|
|
if (module == "async_helper") {
|
|
// TODO(rnystrom): Hack. DDC has its own forked copy of async_helper that
|
|
// has a couple of differences from pkg/async_helper. We should unfork them,
|
|
// but I'm not sure how they'll affect the other non-DDC tests. For now,
|
|
// just use ours.
|
|
inputs.add(_uriInRepo("pkg/dev_compiler/test/codegen/async_helper.dart"));
|
|
} else {
|
|
// There is always a library that matches the module.
|
|
inputs.add(Uri.parse("package:$module/$module.dart"));
|
|
|
|
// Add any other libraries too.
|
|
if (libraries != null) {
|
|
for (var lib in libraries) {
|
|
inputs.add(Uri.parse("package:$module/$lib.dart"));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add summaries for any modules this depends on.
|
|
if (dependencies != null) {
|
|
var uris = <Uri>[];
|
|
|
|
for (var dep in dependencies) {
|
|
uris.add(p.toUri(p.absolute(p.join(pkgDirectory, "$dep.dill"))));
|
|
}
|
|
|
|
options.inputSummaries = uris;
|
|
}
|
|
|
|
// Compile the summary.
|
|
var bytes = await summaryFor(inputs, options);
|
|
var dillFile = new File(p.join(pkgDirectory, "$module.dill"));
|
|
if (succeeded) {
|
|
dillFile.writeAsBytesSync(bytes);
|
|
} else {
|
|
// Don't leave the previous version of the file on failure.
|
|
if (dillFile.existsSync()) dillFile.deleteSync();
|
|
|
|
stderr.writeln("Could not generate kernel summary for $module.");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
Uri _uriInRepo(String pathInRepo) {
|
|
// Walk up to repo root.
|
|
var result = p.join(scriptDirectory, "../../../");
|
|
result = p.join(result, pathInRepo);
|
|
return p.toUri(p.absolute(p.normalize(result)));
|
|
}
|