OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 /// Defines the front-end API for converting source code to Dart Kernel objects. |
| 6 library front_end.kernel_generator_impl; |
| 7 |
| 8 import 'dart:async' show Future; |
| 9 import 'dart:async'; |
| 10 |
| 11 import 'package:kernel/kernel.dart' show Program, CanonicalName; |
| 12 |
| 13 import 'base/processed_options.dart'; |
| 14 import 'fasta/dill/dill_target.dart' show DillTarget; |
| 15 import 'fasta/errors.dart' show InputError, reportCrash; |
| 16 import 'fasta/kernel/kernel_outline_shaker.dart'; |
| 17 import 'fasta/kernel/kernel_target.dart' show KernelTarget; |
| 18 import 'fasta/kernel/verifier.dart'; |
| 19 import 'fasta/kernel/utils.dart'; |
| 20 import 'fasta/compiler_command_line.dart'; |
| 21 import 'fasta/translate_uri.dart' show TranslateUri; |
| 22 |
| 23 /// CODE REVIEW COMMENT: Should we expose this in the public API as well (it is |
| 24 /// used to implement all 3 APIs, but also used directly in patched_sdk) |
| 25 |
| 26 /// Implementation for the `package:front_end/kernel_generator.dart` and |
| 27 /// `package:front_end/summary_generator.dart` APIs. |
| 28 Future<CompilerResult> generateKernel(ProcessedOptions options, |
| 29 {bool buildSummary: false, |
| 30 bool buildProgram: true, |
| 31 bool trimDependencies: false}) async { |
| 32 // TODO(sigmund): Replace CompilerCommandLine and instead simply use a |
| 33 // CompilerContext that directly uses the ProcessedOptions throught the |
| 34 // system. |
| 35 return await CompilerCommandLine.withGlobalOptions("", [""], (context) async { |
| 36 context.options.options['--target'] = options.target; |
| 37 context.options.options['--strong-mode'] = options.strongMode; |
| 38 context.options.options['--verbose'] = options.verbose; |
| 39 |
| 40 return await generateKernelInternal(options, |
| 41 buildSummary: buildSummary, |
| 42 buildProgram: buildProgram, |
| 43 trimDependencies: trimDependencies); |
| 44 }); |
| 45 } |
| 46 |
| 47 Future<CompilerResult> generateKernelInternal(ProcessedOptions options, |
| 48 {bool buildSummary: false, |
| 49 bool buildProgram: true, |
| 50 bool trimDependencies: false}) async { |
| 51 var fs = options.fileSystem; |
| 52 options.ticker.logMs("Parsed arguments"); |
| 53 |
| 54 if (!await options.validateOptions()) return null; |
| 55 options.ticker.logMs("Validated arguments"); |
| 56 |
| 57 try { |
| 58 TranslateUri uriTranslator = await options.getUriTranslator(); |
| 59 |
| 60 var dillTarget = |
| 61 new DillTarget(options.ticker, uriTranslator, options.target); |
| 62 |
| 63 CanonicalName nameRoot = new CanonicalName.root(); |
| 64 Set<Uri> externalLibs(Program program) { |
| 65 return program.libraries |
| 66 .where((lib) => lib.isExternal) |
| 67 .map((lib) => lib.importUri) |
| 68 .toSet(); |
| 69 } |
| 70 |
| 71 var sdkSummary = await options.loadSdkSummary(nameRoot); |
| 72 if (sdkSummary != null) { |
| 73 var excluded = externalLibs(sdkSummary); |
| 74 dillTarget.loader |
| 75 .appendLibraries(sdkSummary, (uri) => !excluded.contains(uri)); |
| 76 } |
| 77 |
| 78 // TODO(sigmund): provide better error reporting if input summaries or |
| 79 // linked dependencies were listed out of order (or provide mechanism to |
| 80 // sort them). |
| 81 for (var inputSummary in await options.loadInputSummaries(nameRoot)) { |
| 82 var excluded = externalLibs(inputSummary); |
| 83 dillTarget.loader |
| 84 .appendLibraries(inputSummary, (uri) => !excluded.contains(uri)); |
| 85 } |
| 86 |
| 87 // All summaries are considered external and shouldn't include source-info. |
| 88 // TODO(sigmund): rather than clearing uriToSource here, it would be nice if |
| 89 // the serializer could filter uriToSource as well. |
| 90 dillTarget.loader.libraries.forEach((lib) => lib.isExternal = true); |
| 91 dillTarget.loader.uriToSource.clear(); |
| 92 |
| 93 // Linked dependencies are meant to be part of the program so they are not |
| 94 // marked external. |
| 95 for (var dependency in await options.loadLinkDependencies(nameRoot)) { |
| 96 var excluded = externalLibs(dependency); |
| 97 dillTarget.loader |
| 98 .appendLibraries(dependency, (uri) => !excluded.contains(uri)); |
| 99 } |
| 100 |
| 101 await dillTarget.buildOutlines(); |
| 102 |
| 103 var kernelTarget = new KernelTarget(fs, dillTarget, uriTranslator); |
| 104 options.inputs.forEach(kernelTarget.read); |
| 105 Program summaryProgram = |
| 106 await kernelTarget.buildOutlines(nameRoot: nameRoot); |
| 107 List<int> summary = null; |
| 108 if (buildSummary) { |
| 109 if (trimDependencies) { |
| 110 // TODO(sigmund): see if it is worth supporting this. Trimming the |
| 111 // program here will affect how we build the program later. To support |
| 112 // both we'd have to clone the program first. |
| 113 assert(!buildProgram); |
| 114 var excluded = |
| 115 dillTarget.loader.libraries.map((lib) => lib.importUri).toSet(); |
| 116 trimProgram(summaryProgram, (uri) => !excluded.contains(uri)); |
| 117 } |
| 118 if (options.verify) { |
| 119 verifyProgram(summaryProgram).forEach((e) => options.reportError('$e')); |
| 120 } |
| 121 if (kernelTarget.errors.isEmpty) { |
| 122 summary = serializeProgram(summaryProgram, excludeUriToSource: true); |
| 123 } |
| 124 options.ticker.logMs("Generated outline"); |
| 125 } |
| 126 |
| 127 Program program; |
| 128 if (buildProgram && kernelTarget.errors.isEmpty) { |
| 129 program = await kernelTarget.buildProgram(verify: options.verify); |
| 130 if (trimDependencies) { |
| 131 var excluded = |
| 132 dillTarget.loader.libraries.map((lib) => lib.importUri).toSet(); |
| 133 trimProgram(program, (uri) => !excluded.contains(uri)); |
| 134 } |
| 135 if (options.debugDump) printProgramText(program); |
| 136 options.ticker.logMs("Generated program"); |
| 137 } |
| 138 |
| 139 if (kernelTarget.errors.isNotEmpty) { |
| 140 kernelTarget.errors.forEach(options.reportError); |
| 141 return null; |
| 142 } |
| 143 |
| 144 return new CompilerResult( |
| 145 summary: summary, |
| 146 program: program, |
| 147 deps: kernelTarget.loader.getDependencies()); |
| 148 } on InputError catch (e) { |
| 149 options.reportError(e.format()); |
| 150 return null; |
| 151 } catch (e, t) { |
| 152 return reportCrash(e, t); |
| 153 } |
| 154 } |
| 155 |
| 156 /// Result object of [generateKernel]. |
| 157 class CompilerResult { |
| 158 /// The generated summary bytes, if it was requested. |
| 159 final List<int> summary; |
| 160 |
| 161 /// The generated program, if it was requested. |
| 162 final Program program; |
| 163 |
| 164 /// Dependencies traversed by the compiler. Used only for generating |
| 165 /// dependency .GN files in the dart-sdk build system. |
| 166 /// Note this might be removed when we switch to compute depencencies without |
| 167 /// using the compiler itself. |
| 168 final List<Uri> deps; |
| 169 |
| 170 CompilerResult({this.summary, this.program, this.deps}); |
| 171 } |
OLD | NEW |