OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Defines the front-end API for converting source code to Dart Kernel objects. | 5 /// Defines the front-end API for converting source code to Dart Kernel objects. |
6 library front_end.kernel_generator; | 6 library front_end.kernel_generator; |
7 | 7 |
| 8 import 'compiler_options.dart'; |
8 import 'dart:async' show Future; | 9 import 'dart:async' show Future; |
9 import 'dart:async'; | 10 import 'dart:async'; |
10 | 11 import 'package:front_end/src/base/processed_options.dart'; |
| 12 import 'src/fasta/dill/dill_target.dart' show DillTarget; |
| 13 import 'src/fasta/errors.dart' show InputError; |
| 14 import 'src/fasta/kernel/kernel_target.dart' show KernelTarget; |
11 import 'package:kernel/kernel.dart' show Program; | 15 import 'package:kernel/kernel.dart' show Program; |
12 | 16 import 'package:kernel/target/targets.dart' show TargetFlags; |
13 import 'compiler_options.dart'; | 17 import 'package:kernel/target/vm_fasta.dart' show VmFastaTarget; |
14 import 'src/base/processed_options.dart'; | 18 import 'src/fasta/ticker.dart' show Ticker; |
15 import 'src/kernel_generator_impl.dart'; | 19 import 'src/fasta/translate_uri.dart' show TranslateUri; |
| 20 import 'src/simple_error.dart'; |
16 | 21 |
17 /// Generates a kernel representation of the program whose main library is in | 22 /// Generates a kernel representation of the program whose main library is in |
18 /// the given [source]. | 23 /// the given [source]. |
19 /// | 24 /// |
20 /// Intended for whole program (non-modular) compilation. | 25 /// Intended for whole program (non-modular) compilation. |
21 /// | 26 /// |
22 /// Given the Uri of a file containing a program's `main` method, this function | 27 /// Given the Uri of a file containing a program's `main` method, this function |
23 /// follows `import`, `export`, and `part` declarations to discover the whole | 28 /// follows `import`, `export`, and `part` declarations to discover the whole |
24 /// program, and converts the result to Dart Kernel format. | 29 /// program, and converts the result to Dart Kernel format. |
25 /// | 30 /// |
26 /// If `compileSdk` in [options] is true, the generated program will include | 31 /// If `compileSdk` in [options] is true, the generated program will include |
27 /// code for the SDK. | 32 /// code for the SDK. |
28 /// | 33 /// |
29 /// If summaries are provided in [options], the compiler will use them instead | 34 /// If summaries are provided in [options], they will be used to speed up |
30 /// of compiling the libraries contained in those summaries. This is useful, for | 35 /// the process. If in addition `compileSdk` is false, then the resulting |
31 /// example, when compiling for platforms that already embed those sources (like | 36 /// program will not contain the sdk contents. This is useful when building apps |
32 /// the sdk in the standalone VM). | 37 /// for platforms that already embed the sdk (e.g. the VM), so there is no need |
33 /// | 38 /// to spend time and space rebuilding it. |
34 /// The input [source] is expected to be a script with a main method, otherwise | |
35 /// an error is reported. | |
36 // TODO(sigmund): rename to kernelForScript? | |
37 Future<Program> kernelForProgram(Uri source, CompilerOptions options) async { | 39 Future<Program> kernelForProgram(Uri source, CompilerOptions options) async { |
38 var pOptions = new ProcessedOptions(options, false, [source]); | 40 var fs = options.fileSystem; |
39 var program = (await generateKernel(pOptions))?.program; | 41 report(String msg) { |
40 if (program == null) return null; | 42 options.onError(new SimpleError(msg)); |
41 | |
42 if (program.mainMethod == null) { | |
43 pOptions.reportError("No 'main' method found."); | |
44 return null; | 43 return null; |
45 } | 44 } |
46 | 45 |
47 return program; | 46 if (!await fs.entityForUri(source).exists()) { |
| 47 return report("Entry-point file not found: $source"); |
| 48 } |
| 49 |
| 50 var pOptions = new ProcessedOptions(options); |
| 51 |
| 52 if (!await pOptions.validateOptions()) return null; |
| 53 |
| 54 try { |
| 55 TranslateUri uriTranslator = await pOptions.getUriTranslator(); |
| 56 |
| 57 var dillTarget = new DillTarget(new Ticker(isVerbose: false), uriTranslator, |
| 58 new VmFastaTarget(new TargetFlags(strongMode: options.strongMode))); |
| 59 var summary = await pOptions.sdkSummaryProgram; |
| 60 if (summary != null) { |
| 61 dillTarget.loader.appendLibraries(summary); |
| 62 } |
| 63 |
| 64 var kernelTarget = |
| 65 new KernelTarget(options.fileSystem, dillTarget, uriTranslator); |
| 66 kernelTarget.read(source); |
| 67 |
| 68 await dillTarget.buildOutlines(); |
| 69 await kernelTarget.buildOutlines(); |
| 70 Program program = await kernelTarget.buildProgram(trimDependencies: true); |
| 71 |
| 72 if (kernelTarget.errors.isNotEmpty) { |
| 73 kernelTarget.errors.forEach(report); |
| 74 return null; |
| 75 } |
| 76 |
| 77 if (program.mainMethod == null) { |
| 78 return report("No 'main' method found."); |
| 79 } |
| 80 |
| 81 if (!options.compileSdk) { |
| 82 // TODO(sigmund): ensure that the result is not including |
| 83 // sources for the sdk, only external references. |
| 84 } |
| 85 return program; |
| 86 } on InputError catch (e) { |
| 87 options.onError(new SimpleError(e.format())); |
| 88 return null; |
| 89 } |
48 } | 90 } |
49 | 91 |
50 /// Generates a kernel representation for a build unit containing [sources]. | 92 /// Generates a kernel representation for a build unit. |
51 /// | 93 /// |
52 /// A build unit is a collection of libraries that are compiled together. | 94 /// Intended for modular compilation. |
53 /// Libraries in the build unit may depend on each other and may have | |
54 /// dependencies to libraries in other build units. Unlinke library | |
55 /// dependencies, build unit dependencies must be acyclic. | |
56 /// | 95 /// |
57 /// This API is intended for modular compilation. Dependencies to other build | 96 /// The build unit by default contains only the source files in [sources] |
58 /// units are specified using [CompilerOptions.inputSummaries]. | 97 /// (including library and part files), but if |
| 98 /// [CompilerOptions.chaseDependencies] is true, it may include some additional |
| 99 /// source files. All of the library files are transformed into Dart Kernel |
| 100 /// Library objects. |
59 /// | 101 /// |
60 /// By default, the compilation process is hermetic, meaning that the only files | 102 /// By default, the compilation process is hermetic, meaning that the only files |
61 /// which will be read are those listed in [sources], | 103 /// which will be read are those listed in [sources], |
62 /// [CompilerOptions.inputSummaries], and [CompilerOptions.sdkSummary]. If a | 104 /// [CompilerOptions.inputSummaries], and [CompilerOptions.sdkSummary]. If a |
63 /// source file attempts to refer to a file which is not obtainable from these | 105 /// source file attempts to refer to a file which is not obtainable from these |
64 /// URIs, that will result in an error, even if the file exists on the | 106 /// URIs, that will result in an error, even if the file exists on the |
65 /// filesystem. | 107 /// filesystem. |
66 /// | 108 /// |
67 /// When [CompilerOptions.chaseDependencies] is true, this default behavior | 109 /// When [CompilerOptions.chaseDependencies] is true, this default behavior |
68 /// changes, and any dependency of [sources] that is not listed in | 110 /// changes, and any dependency of [sources] that is not listed in |
69 /// [CompilerOptions.inputSummaries] and [CompilerOptions.sdkSummary] is treated | 111 /// [CompilerOptions.inputSummaries] and [CompilerOptions.sdkSummary] is treated |
70 /// as an additional source file for the build unit. | 112 /// as an additional source file for the build unit. |
71 /// | 113 /// |
72 /// Any `part` declarations found in [sources] must refer to part files which | 114 /// Any `part` declarations found in [sources] must refer to part files which |
73 /// are also listed in the build unit sources, otherwise an error results. (It | 115 /// are also listed in the build unit sources, otherwise an error results. (It |
74 /// is not permitted to refer to a part file declared in another build unit). | 116 /// is not permitted to refer to a part file declared in another build unit). |
75 /// | 117 /// |
76 /// The return value is a [Program] object with no main method set. The | 118 /// The return value is a [Program] object with no main method set. |
77 /// [Program] includes external libraries for those libraries loaded through | 119 /// TODO(paulberry): would it be better to define a data type in kernel to |
78 /// summaries. | 120 /// represent a bundle of all the libraries in a given build unit? |
| 121 /// |
| 122 /// TODO(paulberry): does additional information need to be output to allow the |
| 123 /// caller to match up referenced elements to the summary files they were |
| 124 /// obtained from? |
79 Future<Program> kernelForBuildUnit( | 125 Future<Program> kernelForBuildUnit( |
80 List<Uri> sources, CompilerOptions options) async { | 126 List<Uri> sources, CompilerOptions options) async { |
81 return (await generateKernel(new ProcessedOptions(options, true, sources))) | 127 var fs = options.fileSystem; |
82 ?.program; | 128 report(String msg) { |
| 129 options.onError(new SimpleError(msg)); |
| 130 return null; |
| 131 } |
| 132 |
| 133 if (!options.chaseDependencies) { |
| 134 // TODO(sigmund): add support, most likely we can do so by adding a wrapper |
| 135 // on top of filesystem that restricts reads to a set of known files. |
| 136 report("hermetic mode (chaseDependencies = false) is not implemented"); |
| 137 return null; |
| 138 } |
| 139 |
| 140 for (var source in sources) { |
| 141 if (!await fs.entityForUri(source).exists()) { |
| 142 return report("Entry-point file not found: $source"); |
| 143 } |
| 144 } |
| 145 |
| 146 var pOptions = new ProcessedOptions(options); |
| 147 |
| 148 if (!await pOptions.validateOptions()) return null; |
| 149 |
| 150 try { |
| 151 TranslateUri uriTranslator = await pOptions.getUriTranslator(); |
| 152 |
| 153 var dillTarget = new DillTarget(new Ticker(isVerbose: false), uriTranslator, |
| 154 new VmFastaTarget(new TargetFlags(strongMode: options.strongMode))); |
| 155 var summary = await pOptions.sdkSummaryProgram; |
| 156 if (summary != null) { |
| 157 dillTarget.loader.appendLibraries(summary); |
| 158 } |
| 159 |
| 160 // TODO(sigmund): this is likely not going to work if done naively: if |
| 161 // summaries contain external references we need to ensure they are loaded |
| 162 // in a specific order. |
| 163 for (var inputSummary in await pOptions.inputSummariesPrograms) { |
| 164 dillTarget.loader.appendLibraries(inputSummary); |
| 165 } |
| 166 |
| 167 await dillTarget.buildOutlines(); |
| 168 |
| 169 var kernelTarget = |
| 170 new KernelTarget(options.fileSystem, dillTarget, uriTranslator); |
| 171 sources.forEach(kernelTarget.read); |
| 172 await kernelTarget.buildOutlines(); |
| 173 |
| 174 Program program = await kernelTarget.buildProgram(trimDependencies: true); |
| 175 |
| 176 if (kernelTarget.errors.isNotEmpty) { |
| 177 kernelTarget.errors.forEach(report); |
| 178 return null; |
| 179 } |
| 180 |
| 181 return program; |
| 182 } on InputError catch (e) { |
| 183 options.onError(new SimpleError(e.format())); |
| 184 return null; |
| 185 } |
83 } | 186 } |
OLD | NEW |