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 /// Implementation for the `package:front_end/kernel_generator.dart` and | |
24 /// `package:front_end/summary_generator.dart` APIs. | |
25 Future<CompilerResult> generateKernel(ProcessedOptions options, | |
26 {bool buildSummary: false, | |
27 bool buildProgram: true, | |
28 bool trimDependencies: false}) async { | |
29 // TODO(sigmund): Replace CompilerCommandLine and instead simply use a | |
30 // CompilerContext that directly uses the ProcessedOptions throught the | |
31 // system. | |
32 return await CompilerCommandLine.withGlobalOptions("", [""], (context) async { | |
33 context.options.options['--target'] = options.target; | |
34 context.options.options['--strong-mode'] = options.strongMode; | |
35 context.options.options['--verbose'] = options.verbose; | |
36 | |
37 return await generateKernelInternal(options, | |
38 buildSummary: buildSummary, | |
39 buildProgram: buildProgram, | |
40 trimDependencies: trimDependencies); | |
41 }); | |
42 } | |
43 | |
44 Future<CompilerResult> generateKernelInternal(ProcessedOptions options, | |
45 {bool buildSummary: false, | |
46 bool buildProgram: true, | |
47 bool trimDependencies: false}) async { | |
48 var fs = options.fileSystem; | |
49 if (!await options.validateOptions()) return null; | |
50 options.ticker.logMs("Validated arguments"); | |
51 | |
52 try { | |
53 TranslateUri uriTranslator = await options.getUriTranslator(); | |
54 | |
55 var dillTarget = | |
56 new DillTarget(options.ticker, uriTranslator, options.target); | |
57 | |
58 CanonicalName nameRoot = new CanonicalName.root(); | |
59 Set<Uri> externalLibs(Program program) { | |
60 return program.libraries | |
61 .where((lib) => lib.isExternal) | |
62 .map((lib) => lib.importUri) | |
63 .toSet(); | |
64 } | |
65 | |
66 var sdkSummary = await options.loadSdkSummary(nameRoot); | |
67 if (sdkSummary != null) { | |
68 var excluded = externalLibs(sdkSummary); | |
69 dillTarget.loader | |
70 .appendLibraries(sdkSummary, (uri) => !excluded.contains(uri)); | |
71 } | |
72 | |
73 // TODO(sigmund): provide better error reporting if input summaries or | |
74 // linked dependencies were listed out of order (or provide mechanism to | |
75 // sort them). | |
76 for (var inputSummary in await options.loadInputSummaries(nameRoot)) { | |
77 var excluded = externalLibs(inputSummary); | |
78 dillTarget.loader | |
79 .appendLibraries(inputSummary, (uri) => !excluded.contains(uri)); | |
80 } | |
81 | |
82 // All summaries are considered external and shouldn't include source-info. | |
83 dillTarget.loader.libraries.forEach((lib) => lib.isExternal = true); | |
84 | |
85 // Linked dependencies are meant to be part of the program so they are not | |
86 // marked external. | |
87 for (var dependency in await options.loadLinkDependencies(nameRoot)) { | |
88 var excluded = externalLibs(dependency); | |
89 dillTarget.loader | |
90 .appendLibraries(dependency, (uri) => !excluded.contains(uri)); | |
91 } | |
92 | |
93 await dillTarget.buildOutlines(); | |
94 | |
95 var kernelTarget = new KernelTarget(fs, dillTarget, uriTranslator); | |
96 options.inputs.forEach(kernelTarget.read); | |
97 Program summaryProgram = | |
98 await kernelTarget.buildOutlines(nameRoot: nameRoot); | |
99 List<int> summary = null; | |
100 if (buildSummary) { | |
101 if (trimDependencies) { | |
102 // TODO(sigmund): see if it is worth supporting this. Note: trimming the | |
103 // program is destructive, so if we are emitting summaries and the | |
104 // program in a single API call, we would need to clone the program here | |
105 // to avoid deleting pieces that are needed by kernelTarget.buildProgram | |
106 // below. | |
107 assert(!buildProgram); | |
108 var excluded = | |
109 dillTarget.loader.libraries.map((lib) => lib.importUri).toSet(); | |
110 trimProgram(summaryProgram, (uri) => !excluded.contains(uri)); | |
111 } | |
112 if (options.verify) { | |
113 verifyProgram(summaryProgram).forEach((e) => options.reportError('$e')); | |
114 } | |
115 if (options.debugDump) { | |
116 printProgramText(summaryProgram, | |
117 libraryFilter: kernelTarget.isSourceLibrary); | |
118 } | |
119 if (kernelTarget.errors.isEmpty) { | |
120 summary = serializeProgram(summaryProgram, excludeUriToSource: true); | |
121 } | |
122 options.ticker.logMs("Generated outline"); | |
123 } | |
124 | |
125 Program program; | |
126 if (buildProgram && kernelTarget.errors.isEmpty) { | |
127 program = await kernelTarget.buildProgram(verify: options.verify); | |
128 if (trimDependencies) { | |
129 var excluded = | |
130 dillTarget.loader.libraries.map((lib) => lib.importUri).toSet(); | |
131 trimProgram(program, (uri) => !excluded.contains(uri)); | |
132 } | |
133 if (options.debugDump) { | |
134 printProgramText(program, libraryFilter: kernelTarget.isSourceLibrary); | |
135 } | |
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 |