anchor.diff:      show createAnalysisContextWithSources, AnalyzerOptions;
   import 'package:path/path.dart' as path;
   
  +const ENTRY = "main";
  +
   void main(List<String> args) {
     // Parse flags.
     var parser = new ArgParser()
  -    ..addOption('out', abbr: 'o', defaultsTo: 'out.js')
  -    ..addFlag('unsafe-force-compile', negatable: false)
  -    ..addOption('package-root', abbr: 'p', defaultsTo: 'packages/');
  +    ..addOption('out',
  +        help: 'Output file (defaults to "out.js")',
  +        abbr: 'o',
  +        defaultsTo: 'out.js')
  +    ..addFlag('unsafe-force-compile',
  +        help: 'Generate code with undefined behavior', negatable: false)
  +    ..addOption('package-root',
  +        help: 'Directory containing packages',
  +        abbr: 'p',
  +        defaultsTo: 'packages/')
  +    ..addFlag('log', help: 'Show individual build commands')
  +    ..addOption('tmp',
  +        help:
  +            'Directory for temporary artifacts (defaults to a system tmp directory)');
   
     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 outfile = options['out'] as String;
  +  var packageRoot = options['package-root'] as String;
  +  var unsafe = options['unsafe-force-compile'] as bool;
  +  var log = options['log'] as bool;
  +  var tmp = options['tmp'] as String;
  +
  +  // Build an invocation to dartdevc
     var dartPath = Platform.resolvedExecutable;
     var ddcPath = path.dirname(path.dirname(Platform.script.toFilePath()));
  -  var command = [
  +  var template = [
       '$ddcPath/bin/dartdevc.dart',
       'compile',
       '--no-source-map', // Invalid as we're just concatenating files below
       '-p',
  -    packageRoot,
  -    '-o',
  -    outfile
  +    packageRoot
     ];
     if (unsafe) {
  -    command.add('--unsafe-force-compile');
  +    template.add('--unsafe-force-compile');
     }
   
     // Compute the transitive closure
  -  var watch = new Stopwatch()..start();
  +  var total = new Stopwatch()..start();
  +  var partial = new Stopwatch()..start();
  +
  +  // TODO(vsm): We're using the analyzer just to compute the import/export/part
  +  // dependence graph.  This is expensive.  Is there a lighterweight way to do
  +  // this?
     var context = createAnalysisContextWithSources(new AnalyzerOptions());
  -  var inputSet = new Set<String>();
  -  transitiveFiles(inputSet, context, entry, Directory.current.path);
  -  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.
  +  transitiveFiles(context, entry, Directory.current.path);
  +  orderModules();
  +  computeTransitiveDependences();
  +
  +  var graphTime = partial.elapsedMilliseconds / 1000;
  +  print('Computed global build graph in $graphTime 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();
  +  out.writeAsStringSync(dartLibrary);
     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);
  +
  +  // Linearize module concatenation for deterministic output
  +  var last = new Future.value();
  +  for (var module in orderedModules) {
  +    linearizerMap[module] = last;
  +    var completer = new Completer();
  +    completerMap[module] = completer;
  +    last = completer.future;
  +  }
  +
  +  // Build modules asynchronously
  +  var tmpdir = (tmp == null)
  +      ? Directory.systemTemp
  +          .createTempSync(outfile.replaceAll(path.separator, '__'))
  +      : new Directory(tmp)..createSync();
  +  for (var module in orderedModules) {
  +    var file = tmpdir.path + path.separator + module + '.js';
  +    var command = new List.from(template)..addAll(['-o', file]);
  +    var dependences = transitiveDependenceMap[module];
  +    for (var dependence in dependences) {
  +      var summary = tmpdir.path + path.separator + dependence + '.sum';
  +      command.addAll(['-s', summary]);
  +    }
  +    var infiles = fileMap[module];
  +    command.addAll(infiles);
  +
  +    var immediateDeps =
  +        dependenceMap.containsKey(module) ? dependenceMap[module] : <String>[];
  +    var waitList = immediateDeps.map((dep) => readyMap[dep]);
  +    var future = Future.wait(waitList);
  +    readyMap[module] = future.then((_) {
  +      var ready = Process.run(dartPath, command);
  +      if (log) {
  +        print(command.join(' '));
  +      }
  +      return ready.then((result) {
  +        if (result.exitCode != 0) {
  +          print('ERROR: compiling $module');
  +          print(result.stdout);
  +          print(result.stderr);
  +          out.deleteSync();
  +          exit(1);
  +        }
  +        print('Compiled $module (${infiles.length} files)');
  +        print(result.stdout);
  +
  +        // Schedule module append once the previous module is written
  +        var codefile = new File(file);
  +        linearizerMap[module]
  +            .then((_) => codefile.readAsString())
  +            .then((code) =>
  +                out.writeAsString(code, mode: FileMode.APPEND, flush: true))
  +            .then((_) => completerMap[module].complete());
  +      });
  +    });
  +  }
  +
  +  last.then((_) {
  +    var time = total.elapsedMilliseconds / 1000;
  +    print('Successfully compiled ${inputSet.length} files in $time seconds');
  +
  +    // Append the entry point invocation.
  +    var libraryName =
  +        path.withoutExtension(entry).replaceAll(path.separator, '__');
  +    out.writeAsStringSync('dart_library.start("$ENTRY", "$libraryName");\n',
  +        mode: FileMode.APPEND);
  +  });
  +}
  +
  +final inputSet = new Set<String>();
  +final dependenceMap = new Map<String, Set<String>>();
  +final transitiveDependenceMap = new Map<String, Set<String>>();
  +final fileMap = new Map<String, Set<String>>();
  +
  +final readyMap = new Map<String, Future>();
  +final linearizerMap = new Map<String, Future>();
  +final completerMap = new Map<String, Completer>();
  +
  +final orderedModules = new List<String>();
  +final visitedModules = new Set<String>();
  +
  +void orderModules(
  +    [String module = ENTRY, List<String> stack, Set<String> visited]) {
  +  if (stack == null) {
  +    assert(visited == null);
  +    stack = new List<String>();
  +    visited = new Set<String>();
  +  }
  +  if (visited.contains(module)) return;
  +  visited.add(module);
  +  if (stack.contains(module)) {
  +    print(stack);
  +    throw 'Circular dependence on $module';
  +  }
  +  stack.add(module);
  +  var dependences = dependenceMap[module];
  +  if (dependences != null) {
  +    for (var dependence in dependences) {
  +      orderModules(dependence, stack, visited);
  +    }
  +  }
  +  orderedModules.add(module);
  +  assert(module == stack.last);
  +  stack.removeLast();
  +}
  +
  +void computeTransitiveDependences() {
  +  for (var module in orderedModules) {
  +    var transitiveSet = new Set<String>();
  +    if (dependenceMap.containsKey(module)) {
  +      transitiveSet.addAll(dependenceMap[module]);
  +      for (var dependence in dependenceMap[module]) {
  +        transitiveSet.addAll(transitiveDependenceMap[dependence]);
  +      }
  +    }
  +    transitiveDependenceMap[module] = transitiveSet;
  +  }
  +}
  +
  +String getModule(String uri) {
  +  var sourceUri = Uri.parse(uri);
  +  if (sourceUri.scheme == 'dart') {
  +    return 'dart';
  +  } else if (sourceUri.scheme == 'package') {
  +    return path.split(sourceUri.path)[0];
  +  } else {
  +    return ENTRY;
  +  }
  +}
  +
  +bool processFile(String file) {
  +  inputSet.add(file);
  +
  +  var module = getModule(file);
  +  fileMap.putIfAbsent(module, () => new Set<String>());
  +  return fileMap[module].add(file);
  +}
  +
  +void processDependence(String from, String to) {
  +  var fromModule = getModule(from);
  +  var toModule = getModule(to);
  +  if (fromModule == toModule || toModule == 'dart') return;
  +  dependenceMap.putIfAbsent(fromModule, () => new Set<String>());
  +  dependenceMap[fromModule].add(toModule);
   }
   
   String canonicalize(String uri, String root) {
  
positive.code:     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));
      }
    }
  }
  
negative.code: // 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:analyzer/src/generated/engine.dart' show AnalysisContext;
  