Index: tool/global_compile.dart |
diff --git a/tool/global_compile.dart b/tool/global_compile.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c6a658c018711b99bea45890cb8c12525c36182e |
--- /dev/null |
+++ b/tool/global_compile.dart |
@@ -0,0 +1,120 @@ |
+#!/usr/bin/env dart |
+// Copyright (c) 2016, 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:analyzer/src/generated/engine.dart' show AnalysisContext; |
+import 'package:args/args.dart' show ArgParser; |
+import 'package:dev_compiler/src/analyzer/context.dart' |
+ show createAnalysisContextWithSources; |
+import 'package:dev_compiler/src/analyzer/context.dart' |
+ show createAnalysisContextWithSources, AnalyzerOptions; |
+import 'package:path/path.dart' as path; |
+ |
+void main(List<String> args) { |
+ // Parse flags. |
+ var parser = new ArgParser() |
+ ..addOption('out', abbr: 'o', defaultsTo: 'out.js') |
+ ..addFlag('unsafe-force-compile', negatable: false) |
Jennifer Messerly
2016/05/03 21:25:48
could you just reuse all existing flags? e.g.
imp
|
+ ..addOption('package-root', abbr: 'p', defaultsTo: 'packages/'); |
+ |
+ var options = parser.parse(args); |
+ if (options.rest.length != 1) { |
+ throw 'Expected a single dart entrypoint.'; |
+ } |
+ var entry = options.rest.first; |
+ var outfile = options['out']; |
+ var packageRoot = options['package-root']; |
+ var unsafe = options['unsafe-force-compile']; |
+ |
+ // Build an invocation to dartdevc. |
+ var dartPath = Platform.resolvedExecutable; |
+ var ddcPath = path.dirname(path.dirname(Platform.script.toFilePath())); |
+ var command = [ |
+ '$ddcPath/bin/dartdevc.dart', |
+ 'compile', |
+ '--no-source-map', // Invalid as we're just concatenating files below |
+ '-p', |
+ packageRoot, |
+ '-o', |
+ outfile |
+ ]; |
+ if (unsafe) { |
+ command.add('--unsafe-force-compile'); |
+ } |
+ |
+ // Compute the transitive closure |
+ var watch = new Stopwatch()..start(); |
+ var context = createAnalysisContextWithSources(new AnalyzerOptions()); |
+ var inputSet = new Set<String>(); |
+ transitiveFiles(inputSet, context, entry, Directory.current.path); |
Jennifer Messerly
2016/05/03 21:25:48
consider: grouping by package, then linking output
|
+ command.addAll(inputSet); |
+ var result = Process.runSync(dartPath, command); |
+ |
+ if (result.exitCode == 0) { |
+ print(result.stdout); |
+ } else { |
+ print('ERROR:'); |
+ print(result.stdout); |
+ print(result.stderr); |
+ exit(1); |
+ } |
+ var time = watch.elapsedMilliseconds / 1000; |
+ print('Successfully compiled ${inputSet.length} files in $time seconds'); |
+ |
+ // Prepend Dart runtime files to the output. |
+ var out = new File(outfile); |
+ var code = out.readAsStringSync(); |
+ var dartLibrary = |
+ new File(path.join(ddcPath, 'lib', 'runtime', 'dart_library.js')) |
+ .readAsStringSync(); |
+ var dartSdk = new File(path.join(ddcPath, 'lib', 'runtime', 'dart_sdk.js')) |
+ .readAsStringSync(); |
+ out.writeAsStringSync(dartLibrary); |
+ out.writeAsStringSync(dartSdk, mode: FileMode.APPEND); |
+ out.writeAsStringSync(code, mode: FileMode.APPEND); |
+ |
+ // Append the entry point invocation. |
+ var moduleName = path.basenameWithoutExtension(outfile); |
+ var libraryName = |
+ path.withoutExtension(entry).replaceAll(path.separator, '__'); |
+ out.writeAsStringSync('dart_library.start("$moduleName", "$libraryName");\n', |
+ mode: FileMode.APPEND); |
+} |
+ |
+String canonicalize(String uri, String root) { |
+ var sourceUri = Uri.parse(uri); |
+ if (sourceUri.scheme == '') { |
+ sourceUri = path.toUri( |
+ path.isAbsolute(uri) ? path.absolute(uri) : path.join(root, uri)); |
+ } |
+ return sourceUri.toString(); |
+} |
+ |
+void transitiveFiles(Set<String> results, AnalysisContext context, |
+ String entryPoint, String root) { |
+ entryPoint = canonicalize(entryPoint, root); |
+ if (entryPoint.startsWith('dart:')) return; |
+ var entryDir = path.dirname(entryPoint); |
+ if (results.add(entryPoint)) { |
+ // Process this |
+ var source = context.sourceFactory.forUri(entryPoint); |
+ if (source == null) { |
+ throw new Exception('could not create a source for $entryPoint.' |
+ ' The file name is in the wrong format or was not found.'); |
+ } |
+ var library = context.computeLibraryElement(source); |
+ for (var entry in library.imports) { |
+ if (entry.uri == null) continue; |
+ transitiveFiles(results, context, entry.uri, entryDir); |
+ } |
+ for (var entry in library.exports) { |
+ transitiveFiles(results, context, entry.uri, entryDir); |
+ } |
+ for (var part in library.parts) { |
+ results.add(canonicalize(part.uri, entryDir)); |
+ } |
+ } |
+} |