Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2059)

Unified Diff: bin/commands/global_compile.dart

Issue 1900813002: Global compile option (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | bin/dartdevc.dart » ('j') | bin/dartdevc.dart » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: bin/commands/global_compile.dart
diff --git a/bin/commands/global_compile.dart b/bin/commands/global_compile.dart
new file mode 100644
index 0000000000000000000000000000000000000000..0f452a01bad6640042b91eb205906d3929609472
--- /dev/null
+++ b/bin/commands/global_compile.dart
@@ -0,0 +1,198 @@
+// 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:analyzer/src/generated/source.dart' show Source;
+import 'package:analyzer/src/summary/package_bundle_reader.dart'
+ show InSummarySource;
+import 'package:args/command_runner.dart';
+import 'package:dev_compiler/src/analyzer/context.dart' show
+ createAnalysisContextWithSources;
+import 'package:dev_compiler/src/compiler/command.dart';
+import 'package:dev_compiler/src/compiler/compiler.dart'
+ show BuildUnit, CompilerOptions, JSModuleFile, ModuleCompiler, ModuleFormat;
+import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions;
+import 'package:path/path.dart' as path;
+import 'package:yaml/yaml.dart' show loadYaml;
+
+
+/// The command for invoking the modular compiler on the whole program.
+class GlobalCommand extends Command {
Jennifer Messerly 2016/04/18 21:45:45 WholeProgramCompileCommand? or GlobalCompileComman
+ get name => 'global-compile';
Jennifer Messerly 2016/04/18 21:45:45 in the original design this was called "build". Th
+ get description => 'Compile all files reachable from an entry point.';
+
+ GlobalCommand() {
+ argParser.addOption('out', abbr: 'o', help: 'Output file (required)');
+ CompilerOptions.addArguments(argParser);
+ AnalyzerOptions.addArguments(argParser);
+ }
+
+ String canonicalize(String uri, String root) {
Jennifer Messerly 2016/04/18 21:45:45 is this is the exact code we have in ModuleCompile
+ var sourceUri = Uri.parse(uri);
+ if (sourceUri.scheme == '') {
+ sourceUri = path.toUri(path.isAbsolute(uri) ? path.absolute(uri) : path.join(root, uri));
Jennifer Messerly 2016/04/18 21:45:45 looks like this needs dartfmt
+ }
+ 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);
Jennifer Messerly 2016/04/18 21:45:45 I'm curious, why use resolution? You can figure ou
+ 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));
+ }
+ }
+ }
+
+ @override
+ void run() {
+ var analyzerOptions = new AnalyzerOptions.fromArguments(argResults);
+
+ var context = createAnalysisContextWithSources(analyzerOptions);
+ var inputSet = new Set<String>();
+ for (var entry in argResults.rest) {
+ transitiveFiles(inputSet, context, entry, Directory.current.path);
+ }
+ compile(
+ new ModuleCompiler.withContext(context),
Jennifer Messerly 2016/04/18 21:45:45 IMO, it would be better to have it use the command
Jennifer Messerly 2016/04/18 21:49:30 addendum -- a lot depends on where we are going wi
+ new CompilerOptions.fromArguments(argResults),
+ argResults['out'],
+ inputSet.toList());
+ }
+
+ void compile(ModuleCompiler compiler, CompilerOptions compilerOptions,
+ String outPath, List<String> extraArgs,
+ {void forEachError(String error): print}) {
+ if (outPath == null) {
+ usageException('Please include the output file location. For example:\n'
+ ' -o PATH/TO/OUTPUT_FILE.js');
+ }
+ if (compilerOptions.sourceMap) {
+ usageException('Source maps are not supported in global mode');
+ }
+ if (compilerOptions.summarizeApi) {
+ usageException('Summaries are not supported in global mode');
+ }
+ if (compilerOptions.moduleFormat != ModuleFormat.legacy) {
+ usageException('Only legacy modules are supported in global mode');
+ }
+ var unit = new BuildUnit(
+ path.basenameWithoutExtension(outPath), extraArgs, _moduleForLibrary);
+
+ JSModuleFile module = compiler.compile(unit, compilerOptions);
+ module.errors.forEach(forEachError);
+
+ if (!module.isValid) throw new CompileErrorException();
+
+ // Write JS file, as well as source map and summary (if requested).
+ var file = new File(outPath);
+ if (file.existsSync()) file.delete();
+ _copyLegacyDartRuntime(file);
+ file.writeAsStringSync(module.code, mode: FileMode.APPEND);
Jennifer Messerly 2016/04/18 21:45:45 I don't think you want .APPEND, won't this break a
+ }
+
+ String _moduleForLibrary(Source source) {
+ if (source is InSummarySource) {
+ return path.basenameWithoutExtension(source.summaryPath);
+ }
+
+ throw usageException(
+ 'Imported file "${source.uri}" was not found as a summary or source '
+ 'file. Please pass in either the summary or the source file '
+ 'for this import.');
+ }
+
+ void _copyLegacyDartRuntime(File outfile) {
+ var runtimeDir = _computeRuntimeDir();
+ if (runtimeDir == null) {
+ usageException('Cannot compute runtime directory for global mode');
+ }
+ for (var runtimeFile in _RUNTIME_FILES) {
+ var inPath = path.join(runtimeDir, runtimeFile);
+ var infile = new File(inPath);
+ var contents = infile.readAsStringSync();
+ outfile.writeAsStringSync(contents, mode: FileMode.APPEND);
+ }
+ }
+}
+
+const _ENTRY_POINTS = const [
+ 'dartdevc.dart',
+];
+
+const _RUNTIME_FILES = const [
+ 'dart_library.js',
+ 'dart_sdk.js'
+];
+
+final _ENTRY_POINT_SNAPSHOTS = _ENTRY_POINTS.map((f) => "$f.snapshot");
+
+/// Tries to find the `lib/runtime/` directory of the dev_compiler package. This
+/// works when running devc from it's sources or from a snapshot that is
+/// activated via `pub global activate`.
+String _computeRuntimeDir() {
Jennifer Messerly 2016/04/18 21:45:45 Vader "NOOOOOOOooooooooooo" meme ... ;) We just g
+ var scriptPath = path.fromUri(Platform.script);
+ var file = path.basename(scriptPath);
+ var dir = path.dirname(scriptPath);
+ var lastdir = path.basename(dir);
+ dir = path.dirname(dir);
+
+ // Both the source dartdevc.dart and the snapshot generated by pub global activate
+ // are under a bin folder.
+ if (lastdir != 'bin') return null;
+
+ // And both under a project directory containing a pubspec.lock file.
+ var lockfile = path.join(dir, 'pubspec.lock');
+ if (!new File(lockfile).existsSync()) return null;
+
+ // If running from sources we found it!
+ if (_ENTRY_POINTS.contains(file)) {
+ return path.join(dir, 'lib', 'runtime');
+ }
+
+ // If running from a pub global snapshot, we need to read the lock file to
+ // find where the actual sources are located in the pub cache.
+ if (_ENTRY_POINT_SNAPSHOTS.contains(file)) {
+ // Note: this depends on implementation details of pub.
+ var yaml = loadYaml(new File(lockfile).readAsStringSync());
+ var info = yaml['packages']['dev_compiler'];
+ if (info == null) return null;
+
+ var cacheDir;
+ if (info['source'] == 'hosted') {
+ cacheDir = path.join(
+ 'hosted', 'pub.dartlang.org', 'dev_compiler-${info["version"]}');
+ } else if (info['source'] == 'git') {
+ var ref = info['description']['resolved-ref'];
+ cacheDir = path.join('git', 'dev_compiler-${ref}');
+ }
+
+ // We should be under "/path/to/pub-cache/global_packages/dev_compiler".
+ // The pub-cache directory is two levels up, but we verify that the layout
+ // looks correct.
+ if (path.basename(dir) != 'dev_compiler') return null;
+ dir = path.dirname(dir);
+ if (path.basename(dir) != 'global_packages') return null;
+ dir = path.dirname(dir);
+ return path.join(dir, cacheDir, 'lib', 'runtime');
+ }
+ return null;
+}
« no previous file with comments | « no previous file | bin/dartdevc.dart » ('j') | bin/dartdevc.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698