| // Copyright (c) 2017, 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:async'; |
| import 'dart:io'; |
| |
| import 'package:args/args.dart'; |
| import 'package:bazel_worker/bazel_worker.dart'; |
| import 'package:front_end/front_end.dart' hide FileSystemException; |
| import 'package:front_end/src/fasta/command_line_reporting.dart'; |
| import 'package:kernel/target/targets.dart'; |
| |
| main(List<String> args) async { |
| args = preprocessArgs(args); |
| |
| if (args.contains('--persistent_worker')) { |
| if (args.length != 1) { |
| throw new StateError( |
| "unexpected args, expected only --persistent-worker but got: $args"); |
| } |
| await new SummaryWorker().run(); |
| } else { |
| await computeSummary(args); |
| } |
| } |
| |
| /// A bazel worker loop that can compute summaries. |
| class SummaryWorker extends AsyncWorkerLoop { |
| Future<WorkResponse> performRequest(WorkRequest request) async { |
| var outputBuffer = new StringBuffer(); |
| var response = new WorkResponse()..exitCode = 0; |
| try { |
| await computeSummary(request.arguments, |
| isWorker: true, outputBuffer: outputBuffer); |
| } catch (_, s) { |
| outputBuffer.writeln(s); |
| response.exitCode = 15; |
| } |
| response.output = outputBuffer.toString(); |
| return response; |
| } |
| } |
| |
| /// If the last arg starts with `@`, this reads the file it points to and treats |
| /// each line as an additional arg. |
| /// |
| /// This is how individual work request args are differentiated from startup |
| /// args in bazel (inidividual work request args go in that file). |
| List<String> preprocessArgs(List<String> args) { |
| args = new List.from(args); |
| if (args.isEmpty) { |
| return args; |
| } |
| String lastArg = args.last; |
| if (lastArg.startsWith('@')) { |
| File argsFile = new File(lastArg.substring(1)); |
| try { |
| args.removeLast(); |
| args.addAll(argsFile.readAsLinesSync()); |
| } on FileSystemException catch (e) { |
| throw new Exception('Failed to read file specified by $lastArg : $e'); |
| } |
| } |
| return args; |
| } |
| |
| /// An [ArgParser] for generating kernel summaries. |
| final summaryArgsParser = new ArgParser() |
| ..addOption('dart-sdk-summary') |
| ..addOption('input-summary', allowMultiple: true) |
| ..addOption('multi-root', allowMultiple: true) |
| ..addOption('packages-file') |
| ..addOption('source', allowMultiple: true) |
| ..addOption('output'); |
| |
| /// Computes a kernel summary based on [args]. |
| /// |
| /// If [isWorker] is true then exit codes will not be set on failure. |
| /// |
| /// If [outputBuffer] is provided then messages will be written to that buffer |
| /// instead of printed to the console. |
| Future computeSummary(List<String> args, |
| {bool isWorker: false, StringBuffer outputBuffer}) async { |
| var parsedArgs = summaryArgsParser.parse(args); |
| var options = new CompilerOptions() |
| ..packagesFileUri = Uri.parse(parsedArgs['packages-file']) |
| ..inputSummaries = parsedArgs['input-summary'].map(Uri.parse).toList() |
| ..sdkSummary = Uri.parse(parsedArgs['dart-sdk-summary']) |
| ..multiRoots = parsedArgs['multi-root'].map(Uri.parse).toList() |
| ..target = new NoneTarget(new TargetFlags()); |
| |
| if (outputBuffer != null) { |
| options.onError = (CompilationMessage error) { |
| var severityString = severityName(error.severity, capitalized: true); |
| outputBuffer.writeln('$severityString: ${error.message}'); |
| if (error.severity != Severity.nit) { |
| throw error; |
| } |
| }; |
| } else { |
| options.throwOnWarnings = true; |
| } |
| |
| var sources = parsedArgs['source'].map(Uri.parse).toList(); |
| var program = await summaryFor(sources, options); |
| |
| var outputFile = new File(parsedArgs['output']); |
| outputFile.createSync(recursive: true); |
| outputFile.writeAsBytesSync(program); |
| } |