OLD | NEW |
1 #!/usr/bin/env dart | 1 #!/usr/bin/env dart |
2 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 /// Command line tool to merge the SDK libraries and our patch files. | 6 /// Command line tool to merge the SDK libraries and our patch files. |
7 /// This is currently designed as an offline tool, but we could automate it. | 7 /// This is currently designed as an offline tool, but we could automate it. |
8 | 8 |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 import 'dart:isolate' show RawReceivePort; | 10 import 'dart:isolate' show RawReceivePort; |
11 import 'dart:async'; | 11 import 'dart:async'; |
12 import 'dart:math' as math; | 12 import 'dart:math' as math; |
13 | 13 |
14 import 'package:analyzer/analyzer.dart'; | 14 import 'package:analyzer/analyzer.dart'; |
15 import 'package:analyzer/src/generated/sdk.dart'; | 15 import 'package:analyzer/src/generated/sdk.dart'; |
16 import 'package:path/path.dart' as path; | 16 import 'package:path/path.dart' as path; |
17 | 17 |
18 import 'package:front_end/src/fasta/fasta.dart' as fasta | 18 import 'package:front_end/src/fasta/fasta.dart' |
19 show compilePlatform, writeDepsFile; | 19 show compilePlatform, writeDepsFile; |
20 | 20 |
21 import 'package:compiler/src/kernel/fasta_support.dart' as dart2js | |
22 show compilePlatform; | |
23 | |
24 /// Set of input files that were read by this script to generate patched SDK. | 21 /// Set of input files that were read by this script to generate patched SDK. |
25 /// We will dump it out into the depfile for ninja to use. | 22 /// We will dump it out into the depfile for ninja to use. |
26 /// | 23 /// |
27 /// For more information see GN and Ninja references: | 24 /// For more information see GN and Ninja references: |
28 /// https://chromium.googlesource.com/chromium/src/+/56807c6cb383140af0c03da8
f6731d77785d7160/tools/gn/docs/reference.md#depfile_string_File-name-for-input-d
ependencies-for-actions | 25 /// https://chromium.googlesource.com/chromium/src/+/56807c6cb383140af0c03da8
f6731d77785d7160/tools/gn/docs/reference.md#depfile_string_File-name-for-input-d
ependencies-for-actions |
29 /// https://ninja-build.org/manual.html#_depfile | 26 /// https://ninja-build.org/manual.html#_depfile |
30 /// | 27 /// |
31 final deps = new Set<Uri>(); | 28 final deps = new Set<Uri>(); |
32 | 29 |
33 /// Create [File] object from the given path and register it as a dependency. | 30 /// Create [File] object from the given path and register it as a dependency. |
(...skipping 14 matching lines...) Expand all Loading... |
48 | 45 |
49 Future main(List<String> argv) async { | 46 Future main(List<String> argv) async { |
50 var port = new RawReceivePort(); | 47 var port = new RawReceivePort(); |
51 try { | 48 try { |
52 await _main(argv); | 49 await _main(argv); |
53 } finally { | 50 } finally { |
54 port.close(); | 51 port.close(); |
55 } | 52 } |
56 } | 53 } |
57 | 54 |
58 void usage(String mode) { | 55 Future _main(List<String> argv) async { |
59 var base = path.fromUri(Platform.script); | 56 var base = path.fromUri(Platform.script); |
60 final self = path.relative(base); | 57 var dartDir = path.dirname(path.dirname(path.absolute(base))); |
61 print('Usage: $self $mode SDK_DIR PATCH_DIR OUTPUT_DIR PACKAGES'); | |
62 | 58 |
63 final repositoryDir = path.relative(path.dirname(path.dirname(base))); | 59 if (argv.length != 5 || argv.first != 'vm') { |
64 final sdkExample = path.relative(path.join(repositoryDir, 'sdk')); | 60 final self = path.relative(base); |
65 final patchExample = path.relative( | 61 print('Usage: $self vm SDK_DIR PATCH_DIR OUTPUT_DIR PACKAGES'); |
66 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patch')); | |
67 final outExample = path.relative( | |
68 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patched_sdk')); | |
69 final packagesExample = path.relative(path.join(repositoryDir, '.packages')); | |
70 print('For example:'); | |
71 print('\$ $self vm $sdkExample $patchExample $outExample $packagesExample'); | |
72 | 62 |
73 exit(1); | 63 final repositoryDir = path.relative(path.dirname(path.dirname(base))); |
74 } | 64 final sdkExample = path.relative(path.join(repositoryDir, 'sdk')); |
| 65 final patchExample = path.relative( |
| 66 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patch')); |
| 67 final outExample = path.relative(path.join( |
| 68 repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patched_sdk')); |
| 69 print('For example:'); |
| 70 print('\$ $self vm $sdkExample $patchExample $outExample'); |
75 | 71 |
76 Future _main(List<String> argv) async { | 72 exit(1); |
77 var mode = argv.first; | 73 } |
78 if (mode != 'vm' && mode != 'dart2js') usage('[vm|dart2js]'); | |
79 if (argv.length != 5) usage(mode); | |
80 | 74 |
81 bool forVm = mode == 'vm'; | 75 var mode = argv[0]; |
82 bool forDart2js = mode == 'dart2js'; | 76 assert(mode == "vm"); |
83 var input = argv[1]; | 77 var input = argv[1]; |
84 var sdkLibIn = path.join(input, 'lib'); | 78 var sdkLibIn = path.join(input, 'lib'); |
85 var patchIn = argv[2]; | 79 var patchIn = argv[2]; |
86 var outDir = argv[3]; | 80 var outDir = argv[3]; |
87 var outDirUri = Uri.base.resolveUri(new Uri.directory(outDir)); | |
88 var sdkOut = path.join(outDir, 'lib'); | 81 var sdkOut = path.join(outDir, 'lib'); |
89 var packagesFile = argv[4]; | 82 var packagesFile = argv[4]; |
90 | 83 |
91 // Parse libraries.dart | 84 // Copy and patch libraries.dart and version |
92 var libContents = readInputFile(path.join( | 85 var libContents = readInputFile(path.join( |
93 sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); | 86 sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); |
94 if (forVm) libContents = _updateLibraryMetadata(sdkOut, libContents); | |
95 var sdkLibraries = _getSdkLibraries(libContents); | |
96 | |
97 // Enumerate core libraries and apply patches | |
98 for (SdkLibrary library in sdkLibraries) { | |
99 if (forDart2js && library.isVmLibrary) continue; | |
100 if (forVm && library.isDart2JsLibrary) continue; | |
101 _applyPatch(library, sdkLibIn, patchIn, sdkOut); | |
102 } | |
103 | |
104 if (forVm) _copyExtraVmLibraries(sdkOut); | |
105 | |
106 Uri platform = outDirUri.resolve('platform.dill.tmp'); | |
107 Uri packages = Uri.base.resolveUri(new Uri.file(packagesFile)); | |
108 if (forVm) { | |
109 await fasta.compilePlatform(outDirUri, platform, packages: packages); | |
110 } else { | |
111 await dart2js.compilePlatform(outDirUri, platform, packages: packages); | |
112 } | |
113 | |
114 Uri platformFinalLocation = outDirUri.resolve('platform.dill'); | |
115 | |
116 // To properly regenerate the patched_sdk, patched_dart2js_sdk, and | |
117 // platform.dill only when necessary, we track dependencies as follows: | |
118 // - inputs like the sdk libraries and patch files are covered by the | |
119 // extraDependencies argument. | |
120 // - this script and its script dependencies are handled by writeDepsFile | |
121 // here. | |
122 // - the internal platform libraries that may affect how this script | |
123 // runs in the VM are discovered by providing the `platform` argument | |
124 // below. Regardless of patched_sdk or patched_dart2js_sdk we provide below | |
125 // the .dill file of patched_sdk (since the script runs in the VM and not | |
126 // in dart2js). At the BUILD.gn level we have a dependency from | |
127 // patched_dart2js_sdk to patched_sdk to ensure that file already exists. | |
128 await fasta.writeDepsFile(Platform.script, | |
129 Uri.base.resolveUri(new Uri.file("$outDir.d")), platformFinalLocation, | |
130 packages: packages, | |
131 platform: | |
132 forVm ? platform : outDirUri.resolve('../patched_sdk/platform.dill'), | |
133 extraDependencies: deps, | |
134 verbose: false); | |
135 | |
136 await new File.fromUri(platform).rename(platformFinalLocation.toFilePath()); | |
137 } | |
138 | |
139 /// Updates the contents of | |
140 /// sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart to include | |
141 /// declarations for vm internal libraries. | |
142 String _updateLibraryMetadata(String sdkOut, String libContents) { | |
143 // Copy and patch libraries.dart and version | |
144 libContents = libContents.replaceAll( | 87 libContents = libContents.replaceAll( |
145 ' libraries = const {', | 88 ' libraries = const {', |
146 ''' libraries = const { | 89 ''' libraries = const { |
147 | 90 |
148 "_builtin": const LibraryInfo( | 91 "_builtin": const LibraryInfo( |
149 "_builtin/_builtin.dart", | 92 "_builtin/_builtin.dart", |
150 categories: "Client,Server", | 93 categories: "Client,Server", |
151 implementation: true, | 94 implementation: true, |
152 documented: false, | 95 documented: false, |
153 platforms: VM_PLATFORM), | 96 platforms: VM_PLATFORM), |
(...skipping 13 matching lines...) Expand all Loading... |
167 "vmservice_io/vmservice_io.dart", | 110 "vmservice_io/vmservice_io.dart", |
168 implementation: true, | 111 implementation: true, |
169 documented: false, | 112 documented: false, |
170 platforms: VM_PLATFORM), | 113 platforms: VM_PLATFORM), |
171 | 114 |
172 '''); | 115 '''); |
173 _writeSync( | 116 _writeSync( |
174 path.join( | 117 path.join( |
175 sdkOut, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'), | 118 sdkOut, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'), |
176 libContents); | 119 libContents); |
177 return libContents; | |
178 } | |
179 | 120 |
180 /// Copy internal libraries that are developed under 'runtime/bin/' to the | 121 // Parse libraries.dart |
181 /// patched_sdk folder. | 122 var sdkLibraries = _getSdkLibraries(libContents); |
182 _copyExtraVmLibraries(String sdkOut) { | 123 |
183 var base = path.fromUri(Platform.script); | 124 // Enumerate core libraries and apply patches |
184 var dartDir = path.dirname(path.dirname(path.absolute(base))); | 125 for (SdkLibrary library in sdkLibraries) { |
| 126 if (library.isDart2JsLibrary) { |
| 127 continue; |
| 128 } |
| 129 |
| 130 var libraryOut = path.join(sdkLibIn, library.path); |
| 131 var libraryIn = libraryOut; |
| 132 |
| 133 var libraryFile = getInputFile(libraryIn, canBeMissing: true); |
| 134 if (libraryFile != null) { |
| 135 var outPaths = <String>[libraryOut]; |
| 136 var libraryContents = libraryFile.readAsStringSync(); |
| 137 |
| 138 int inputModifyTime = |
| 139 libraryFile.lastModifiedSync().millisecondsSinceEpoch; |
| 140 var partFiles = <File>[]; |
| 141 for (var part in parseDirectives(libraryContents).directives) { |
| 142 if (part is PartDirective) { |
| 143 var partPath = part.uri.stringValue; |
| 144 outPaths.add(path.join(path.dirname(libraryOut), partPath)); |
| 145 |
| 146 var partFile = |
| 147 getInputFile(path.join(path.dirname(libraryIn), partPath)); |
| 148 partFiles.add(partFile); |
| 149 inputModifyTime = math.max(inputModifyTime, |
| 150 partFile.lastModifiedSync().millisecondsSinceEpoch); |
| 151 } |
| 152 } |
| 153 |
| 154 // See if we can find a patch file. |
| 155 var patchPath = path.join( |
| 156 patchIn, path.basenameWithoutExtension(libraryIn) + '_patch.dart'); |
| 157 |
| 158 var patchFile = getInputFile(patchPath, canBeMissing: true); |
| 159 if (patchFile != null) { |
| 160 inputModifyTime = math.max(inputModifyTime, |
| 161 patchFile.lastModifiedSync().millisecondsSinceEpoch); |
| 162 } |
| 163 |
| 164 // Compute output paths |
| 165 outPaths = outPaths |
| 166 .map((p) => path.join(sdkOut, path.relative(p, from: sdkLibIn))) |
| 167 .toList(); |
| 168 |
| 169 // Compare output modify time with input modify time. |
| 170 bool needsUpdate = false; |
| 171 for (var outPath in outPaths) { |
| 172 var outFile = new File(outPath); |
| 173 if (!outFile.existsSync() || |
| 174 outFile.lastModifiedSync().millisecondsSinceEpoch < |
| 175 inputModifyTime) { |
| 176 needsUpdate = true; |
| 177 break; |
| 178 } |
| 179 } |
| 180 |
| 181 if (needsUpdate) { |
| 182 var contents = <String>[libraryContents]; |
| 183 contents.addAll(partFiles.map((f) => f.readAsStringSync())); |
| 184 if (patchFile != null) { |
| 185 var patchContents = patchFile.readAsStringSync(); |
| 186 contents = _patchLibrary(patchFile.path, contents, patchContents); |
| 187 } |
| 188 |
| 189 for (var i = 0; i < outPaths.length; i++) { |
| 190 _writeSync(outPaths[i], contents[i]); |
| 191 } |
| 192 } |
| 193 } |
| 194 } |
185 | 195 |
186 for (var tuple in [ | 196 for (var tuple in [ |
187 ['_builtin', 'builtin.dart'] | 197 ['_builtin', 'builtin.dart'] |
188 ]) { | 198 ]) { |
189 var vmLibrary = tuple[0]; | 199 var vmLibrary = tuple[0]; |
190 var dartFile = tuple[1]; | 200 var dartFile = tuple[1]; |
191 | 201 |
192 // The "dart:_builtin" library is only available for the DartVM. | 202 // The "dart:_builtin" library is only available for the DartVM. |
193 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile); | 203 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile); |
194 var builtinLibraryOut = path.join(sdkOut, vmLibrary, '${vmLibrary}.dart'); | 204 var builtinLibraryOut = path.join(sdkOut, vmLibrary, '${vmLibrary}.dart'); |
195 _writeSync(builtinLibraryOut, readInputFile(builtinLibraryIn)); | 205 _writeSync(builtinLibraryOut, readInputFile(builtinLibraryIn)); |
196 } | 206 } |
197 | 207 |
198 for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) { | 208 for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) { |
199 var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file); | 209 var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file); |
200 var libraryOut = path.join(sdkOut, 'vmservice_io', file); | 210 var libraryOut = path.join(sdkOut, 'vmservice_io', file); |
201 _writeSync(libraryOut, readInputFile(libraryIn)); | 211 _writeSync(libraryOut, readInputFile(libraryIn)); |
202 } | 212 } |
203 } | |
204 | 213 |
205 _applyPatch( | 214 Uri platform = Uri.base |
206 SdkLibrary library, String sdkLibIn, String patchIn, String sdkOut) { | 215 .resolveUri(new Uri.directory(outDir).resolve('platform.dill.tmp')); |
207 var libraryOut = path.join(sdkLibIn, library.path); | 216 Uri packages = Uri.base.resolveUri(new Uri.file(packagesFile)); |
208 var libraryIn = libraryOut; | 217 await compilePlatform( |
| 218 Uri.base.resolveUri(new Uri.directory(outDir)), platform, |
| 219 packages: packages, verbose: false); |
209 | 220 |
210 var libraryFile = getInputFile(libraryIn, canBeMissing: true); | 221 Uri platformFinalLocation = |
211 if (libraryFile != null) { | 222 Uri.base.resolveUri(new Uri.directory(outDir).resolve('platform.dill')); |
212 var outPaths = <String>[libraryOut]; | |
213 var libraryContents = libraryFile.readAsStringSync(); | |
214 | 223 |
215 int inputModifyTime = libraryFile.lastModifiedSync().millisecondsSinceEpoch; | 224 await writeDepsFile(Platform.script, |
216 var partFiles = <File>[]; | 225 Uri.base.resolveUri(new Uri.file("$outDir.d")), platformFinalLocation, |
217 for (var part in parseDirectives(libraryContents).directives) { | 226 packages: packages, |
218 if (part is PartDirective) { | 227 platform: platform, |
219 var partPath = part.uri.stringValue; | 228 extraDependencies: deps, |
220 outPaths.add(path.join(path.dirname(libraryOut), partPath)); | 229 verbose: false); |
221 | 230 |
222 var partFile = | 231 await new File.fromUri(platform).rename(platformFinalLocation.toFilePath()); |
223 getInputFile(path.join(path.dirname(libraryIn), partPath)); | |
224 partFiles.add(partFile); | |
225 inputModifyTime = math.max(inputModifyTime, | |
226 partFile.lastModifiedSync().millisecondsSinceEpoch); | |
227 } | |
228 } | |
229 | |
230 // See if we can find a patch file. | |
231 var patchPath = path.join( | |
232 patchIn, path.basenameWithoutExtension(libraryIn) + '_patch.dart'); | |
233 | |
234 var patchFile = getInputFile(patchPath, canBeMissing: true); | |
235 if (patchFile != null) { | |
236 inputModifyTime = math.max( | |
237 inputModifyTime, patchFile.lastModifiedSync().millisecondsSinceEpoch); | |
238 } | |
239 | |
240 // Compute output paths | |
241 outPaths = outPaths | |
242 .map((p) => path.join(sdkOut, path.relative(p, from: sdkLibIn))) | |
243 .toList(); | |
244 | |
245 // Compare output modify time with input modify time. | |
246 bool needsUpdate = false; | |
247 for (var outPath in outPaths) { | |
248 var outFile = new File(outPath); | |
249 if (!outFile.existsSync() || | |
250 outFile.lastModifiedSync().millisecondsSinceEpoch < inputModifyTime) { | |
251 needsUpdate = true; | |
252 break; | |
253 } | |
254 } | |
255 | |
256 if (needsUpdate) { | |
257 var contents = <String>[libraryContents]; | |
258 contents.addAll(partFiles.map((f) => f.readAsStringSync())); | |
259 if (patchFile != null) { | |
260 var patchContents = patchFile.readAsStringSync(); | |
261 contents = _patchLibrary(patchFile.path, contents, patchContents); | |
262 } | |
263 | |
264 for (var i = 0; i < outPaths.length; i++) { | |
265 _writeSync(outPaths[i], contents[i]); | |
266 } | |
267 } | |
268 } | |
269 } | 232 } |
270 | 233 |
271 /// Writes a file, creating the directory if needed. | 234 /// Writes a file, creating the directory if needed. |
272 void _writeSync(String filePath, String contents) { | 235 void _writeSync(String filePath, String contents) { |
273 var outDir = new Directory(path.dirname(filePath)); | 236 var outDir = new Directory(path.dirname(filePath)); |
274 if (!outDir.existsSync()) outDir.createSync(recursive: true); | 237 if (!outDir.existsSync()) outDir.createSync(recursive: true); |
275 | 238 |
276 new File(filePath).writeAsStringSync(contents); | 239 new File(filePath).writeAsStringSync(contents); |
277 } | 240 } |
278 | 241 |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 if (diff != 0) return diff; | 569 if (diff != 0) return diff; |
607 return end - other.end; | 570 return end - other.end; |
608 } | 571 } |
609 } | 572 } |
610 | 573 |
611 List<SdkLibrary> _getSdkLibraries(String contents) { | 574 List<SdkLibrary> _getSdkLibraries(String contents) { |
612 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); | 575 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); |
613 parseCompilationUnit(contents).accept(libraryBuilder); | 576 parseCompilationUnit(contents).accept(libraryBuilder); |
614 return libraryBuilder.librariesMap.sdkLibraries; | 577 return libraryBuilder.librariesMap.sdkLibraries; |
615 } | 578 } |
OLD | NEW |