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; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
45 | 45 |
46 Future main(List<String> argv) async { | 46 Future main(List<String> argv) async { |
47 var port = new RawReceivePort(); | 47 var port = new RawReceivePort(); |
48 try { | 48 try { |
49 await _main(argv); | 49 await _main(argv); |
50 } finally { | 50 } finally { |
51 port.close(); | 51 port.close(); |
52 } | 52 } |
53 } | 53 } |
54 | 54 |
55 Future _main(List<String> argv) async { | 55 void usage(String mode) { |
Vyacheslav Egorov (Google)
2017/04/27 14:07:23
mode is not used in the body of this function
Siggi Cherem (dart-lang)
2017/04/28 21:37:21
oops. Done.
| |
56 var base = path.fromUri(Platform.script); | |
57 final self = path.relative(base); | |
58 print('Usage: $self [vm|dart2js] SDK_DIR PATCH_DIR OUTPUT_DIR PACKAGES'); | |
59 | |
60 final repositoryDir = path.relative(path.dirname(path.dirname(base))); | |
61 final sdkExample = path.relative(path.join(repositoryDir, 'sdk')); | |
62 final patchExample = path.relative( | |
63 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patch')); | |
64 final outExample = path.relative( | |
65 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patched_sdk')); | |
66 final packagesExample = path.relative(path.join(repositoryDir, '.packages')); | |
67 print('For example:'); | |
68 print('\$ $self vm $sdkExample $patchExample $outExample $packagesExample'); | |
69 | |
70 exit(1); | |
71 } | |
72 | |
73 Future _main(List<String> argv) { | |
74 var mode = argv.first; | |
75 if (mode == 'vm') return _vmMain(argv); | |
76 if (mode == 'dart2js') return _dart2jsMain(argv); | |
77 usage('[vm|dart2js]'); | |
78 return null; | |
79 } | |
80 | |
81 Future _vmMain(List<String> argv) async { | |
Vyacheslav Egorov (Google)
2017/04/27 14:07:23
vmMain and dart2jsMain have very similar prefix an
Siggi Cherem (dart-lang)
2017/04/28 21:37:21
Done.
| |
56 var base = path.fromUri(Platform.script); | 82 var base = path.fromUri(Platform.script); |
57 var dartDir = path.dirname(path.dirname(path.absolute(base))); | 83 var dartDir = path.dirname(path.dirname(path.absolute(base))); |
58 | |
59 if (argv.length != 5 || argv.first != 'vm') { | 84 if (argv.length != 5 || argv.first != 'vm') { |
Vyacheslav Egorov (Google)
2017/04/27 14:07:23
argv.first != 'vm' can't happen anymore.
Siggi Cherem (dart-lang)
2017/04/28 21:37:21
Done.
| |
60 final self = path.relative(base); | 85 usage('vm'); |
61 print('Usage: $self vm SDK_DIR PATCH_DIR OUTPUT_DIR PACKAGES'); | |
62 | |
63 final repositoryDir = path.relative(path.dirname(path.dirname(base))); | |
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'); | |
71 | |
72 exit(1); | |
73 } | 86 } |
74 | 87 |
75 var mode = argv[0]; | |
76 assert(mode == "vm"); | |
77 var input = argv[1]; | 88 var input = argv[1]; |
78 var sdkLibIn = path.join(input, 'lib'); | 89 var sdkLibIn = path.join(input, 'lib'); |
79 var patchIn = argv[2]; | 90 var patchIn = argv[2]; |
80 var outDir = argv[3]; | 91 var outDir = argv[3]; |
81 var sdkOut = path.join(outDir, 'lib'); | 92 var sdkOut = path.join(outDir, 'lib'); |
82 var packagesFile = argv[4]; | 93 var packagesFile = argv[4]; |
83 | 94 |
84 // Copy and patch libraries.dart and version | 95 // Copy and patch libraries.dart and version |
85 var libContents = readInputFile(path.join( | 96 var libContents = readInputFile(path.join( |
86 sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); | 97 sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
119 libContents); | 130 libContents); |
120 | 131 |
121 // Parse libraries.dart | 132 // Parse libraries.dart |
122 var sdkLibraries = _getSdkLibraries(libContents); | 133 var sdkLibraries = _getSdkLibraries(libContents); |
123 | 134 |
124 // Enumerate core libraries and apply patches | 135 // Enumerate core libraries and apply patches |
125 for (SdkLibrary library in sdkLibraries) { | 136 for (SdkLibrary library in sdkLibraries) { |
126 if (library.isDart2JsLibrary) { | 137 if (library.isDart2JsLibrary) { |
127 continue; | 138 continue; |
128 } | 139 } |
129 | 140 _applyPatch(library, sdkLibIn, patchIn, sdkOut); |
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 } | 141 } |
195 | 142 |
196 for (var tuple in [ | 143 for (var tuple in [ |
197 ['_builtin', 'builtin.dart'] | 144 ['_builtin', 'builtin.dart'] |
198 ]) { | 145 ]) { |
199 var vmLibrary = tuple[0]; | 146 var vmLibrary = tuple[0]; |
200 var dartFile = tuple[1]; | 147 var dartFile = tuple[1]; |
201 | 148 |
202 // The "dart:_builtin" library is only available for the DartVM. | 149 // The "dart:_builtin" library is only available for the DartVM. |
203 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile); | 150 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile); |
(...skipping 20 matching lines...) Expand all Loading... | |
224 await writeDepsFile(Platform.script, | 171 await writeDepsFile(Platform.script, |
225 Uri.base.resolveUri(new Uri.file("$outDir.d")), platformFinalLocation, | 172 Uri.base.resolveUri(new Uri.file("$outDir.d")), platformFinalLocation, |
226 packages: packages, | 173 packages: packages, |
227 platform: platform, | 174 platform: platform, |
228 extraDependencies: deps, | 175 extraDependencies: deps, |
229 verbose: false); | 176 verbose: false); |
230 | 177 |
231 await new File.fromUri(platform).rename(platformFinalLocation.toFilePath()); | 178 await new File.fromUri(platform).rename(platformFinalLocation.toFilePath()); |
232 } | 179 } |
233 | 180 |
181 Future _dart2jsMain(List<String> argv) async { | |
182 if (argv.length != 5 || argv.first != 'dart2js') { | |
183 usage('dart2js'); | |
184 } | |
185 | |
186 var input = argv[1]; | |
187 var sdkLibIn = path.join(input, 'lib'); | |
188 var patchIn = argv[2]; | |
189 var outDir = argv[3]; | |
190 var sdkOut = path.join(outDir, 'lib'); | |
191 var packagesFile = argv[4]; | |
192 | |
193 // Parse libraries.dart | |
194 var libContents = readInputFile(path.join( | |
195 sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); | |
196 var sdkLibraries = _getSdkLibraries(libContents); | |
197 | |
198 // Enumerate core libraries and apply patches | |
199 for (SdkLibrary library in sdkLibraries) { | |
200 if (library.isVmLibrary) continue; | |
201 _applyPatch(library, sdkLibIn, patchIn, sdkOut); | |
202 } | |
203 | |
204 Uri platform = Uri.base | |
205 .resolveUri(new Uri.directory(outDir).resolve('platform.dill.tmp')); | |
206 Uri packages = Uri.base.resolveUri(new Uri.file(packagesFile)); | |
207 await compilePlatform( | |
208 Uri.base.resolveUri(new Uri.directory(outDir)), platform, | |
209 packages: packages, verbose: false, targetDart2js: true); | |
210 | |
211 Uri platformFinalLocation = | |
212 Uri.base.resolveUri(new Uri.directory(outDir).resolve('platform.dill')); | |
213 | |
214 // To properly regenerate the patched_dart2js_sdk and platform.dill only when | |
215 // necessary, we track dependencies as follows: | |
216 // - inputs like the sdk libraries and dart2js patch files are covered by the | |
217 // extraDependencies argument. | |
218 // - this script and its script dependencies are handled by writeDepsFile. | |
219 // - the internal platform libraries that may affect how this script | |
220 // runs are tracked at the BUILD.gn level (patched_dart2js_sdk depends on | |
221 // patched_sdk). | |
222 await writeDepsFile(Platform.script, | |
223 Uri.base.resolveUri(new Uri.file("$outDir.d")), platformFinalLocation, | |
224 packages: packages, | |
225 // To track dependencies of this script, we need to use a platform.dill | |
226 // file generated for the VM. The dependency on the patched_sdk at the | |
227 // BUILD level guarantees that this file already exists. | |
228 platform: Uri.base.resolveUri( | |
229 new Uri.directory(outDir).resolve('../patched_sdk/platform.dill')), | |
230 extraDependencies: deps, | |
231 verbose: false, | |
232 targetDart2js: false); | |
233 | |
234 await new File.fromUri(platform).rename(platformFinalLocation.toFilePath()); | |
235 } | |
236 | |
237 _applyPatch( | |
238 SdkLibrary library, String sdkLibIn, String patchIn, String sdkOut) { | |
239 var libraryOut = path.join(sdkLibIn, library.path); | |
240 var libraryIn = libraryOut; | |
241 | |
242 var libraryFile = getInputFile(libraryIn, canBeMissing: true); | |
243 if (libraryFile != null) { | |
244 var outPaths = <String>[libraryOut]; | |
245 var libraryContents = libraryFile.readAsStringSync(); | |
246 | |
247 int inputModifyTime = libraryFile.lastModifiedSync().millisecondsSinceEpoch; | |
248 var partFiles = <File>[]; | |
249 for (var part in parseDirectives(libraryContents).directives) { | |
250 if (part is PartDirective) { | |
251 var partPath = part.uri.stringValue; | |
252 outPaths.add(path.join(path.dirname(libraryOut), partPath)); | |
253 | |
254 var partFile = | |
255 getInputFile(path.join(path.dirname(libraryIn), partPath)); | |
256 partFiles.add(partFile); | |
257 inputModifyTime = math.max(inputModifyTime, | |
258 partFile.lastModifiedSync().millisecondsSinceEpoch); | |
259 } | |
260 } | |
261 | |
262 // See if we can find a patch file. | |
263 var patchPath = path.join( | |
264 patchIn, path.basenameWithoutExtension(libraryIn) + '_patch.dart'); | |
265 | |
266 var patchFile = getInputFile(patchPath, canBeMissing: true); | |
267 if (patchFile != null) { | |
268 inputModifyTime = math.max( | |
269 inputModifyTime, patchFile.lastModifiedSync().millisecondsSinceEpoch); | |
270 } | |
271 | |
272 // Compute output paths | |
273 outPaths = outPaths | |
274 .map((p) => path.join(sdkOut, path.relative(p, from: sdkLibIn))) | |
275 .toList(); | |
276 | |
277 // Compare output modify time with input modify time. | |
278 bool needsUpdate = false; | |
279 for (var outPath in outPaths) { | |
280 var outFile = new File(outPath); | |
281 if (!outFile.existsSync() || | |
282 outFile.lastModifiedSync().millisecondsSinceEpoch < inputModifyTime) { | |
283 needsUpdate = true; | |
284 break; | |
285 } | |
286 } | |
287 | |
288 if (needsUpdate) { | |
289 var contents = <String>[libraryContents]; | |
290 contents.addAll(partFiles.map((f) => f.readAsStringSync())); | |
291 if (patchFile != null) { | |
292 var patchContents = patchFile.readAsStringSync(); | |
293 contents = _patchLibrary(patchFile.path, contents, patchContents); | |
294 } | |
295 | |
296 for (var i = 0; i < outPaths.length; i++) { | |
297 _writeSync(outPaths[i], contents[i]); | |
298 } | |
299 } | |
300 } | |
301 } | |
302 | |
234 /// Writes a file, creating the directory if needed. | 303 /// Writes a file, creating the directory if needed. |
235 void _writeSync(String filePath, String contents) { | 304 void _writeSync(String filePath, String contents) { |
236 var outDir = new Directory(path.dirname(filePath)); | 305 var outDir = new Directory(path.dirname(filePath)); |
237 if (!outDir.existsSync()) outDir.createSync(recursive: true); | 306 if (!outDir.existsSync()) outDir.createSync(recursive: true); |
238 | 307 |
239 new File(filePath).writeAsStringSync(contents); | 308 new File(filePath).writeAsStringSync(contents); |
240 } | 309 } |
241 | 310 |
242 /// Merges dart:* library code with code from *_patch.dart file. | 311 /// Merges dart:* library code with code from *_patch.dart file. |
243 /// | 312 /// |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
569 if (diff != 0) return diff; | 638 if (diff != 0) return diff; |
570 return end - other.end; | 639 return end - other.end; |
571 } | 640 } |
572 } | 641 } |
573 | 642 |
574 List<SdkLibrary> _getSdkLibraries(String contents) { | 643 List<SdkLibrary> _getSdkLibraries(String contents) { |
575 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); | 644 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); |
576 parseCompilationUnit(contents).accept(libraryBuilder); | 645 parseCompilationUnit(contents).accept(libraryBuilder); |
577 return libraryBuilder.librariesMap.sdkLibraries; | 646 return libraryBuilder.librariesMap.sdkLibraries; |
578 } | 647 } |
OLD | NEW |