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' | 18 import 'package:front_end/src/fasta/fasta.dart' as fasta |
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 |
21 /// Set of input files that were read by this script to generate patched SDK. | 24 /// Set of input files that were read by this script to generate patched SDK. |
22 /// We will dump it out into the depfile for ninja to use. | 25 /// We will dump it out into the depfile for ninja to use. |
23 /// | 26 /// |
24 /// For more information see GN and Ninja references: | 27 /// For more information see GN and Ninja references: |
25 /// https://chromium.googlesource.com/chromium/src/+/56807c6cb383140af0c03da8
f6731d77785d7160/tools/gn/docs/reference.md#depfile_string_File-name-for-input-d
ependencies-for-actions | 28 /// https://chromium.googlesource.com/chromium/src/+/56807c6cb383140af0c03da8
f6731d77785d7160/tools/gn/docs/reference.md#depfile_string_File-name-for-input-d
ependencies-for-actions |
26 /// https://ninja-build.org/manual.html#_depfile | 29 /// https://ninja-build.org/manual.html#_depfile |
27 /// | 30 /// |
28 final deps = new Set<Uri>(); | 31 final deps = new Set<Uri>(); |
29 | 32 |
30 /// Create [File] object from the given path and register it as a dependency. | 33 /// Create [File] object from the given path and register it as a dependency. |
(...skipping 14 matching lines...) Expand all Loading... |
45 | 48 |
46 Future main(List<String> argv) async { | 49 Future main(List<String> argv) async { |
47 var port = new RawReceivePort(); | 50 var port = new RawReceivePort(); |
48 try { | 51 try { |
49 await _main(argv); | 52 await _main(argv); |
50 } finally { | 53 } finally { |
51 port.close(); | 54 port.close(); |
52 } | 55 } |
53 } | 56 } |
54 | 57 |
| 58 void usage(String mode) { |
| 59 var base = path.fromUri(Platform.script); |
| 60 final self = path.relative(base); |
| 61 print('Usage: $self $mode 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( |
| 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 |
| 73 exit(1); |
| 74 } |
| 75 |
55 Future _main(List<String> argv) async { | 76 Future _main(List<String> argv) async { |
56 var base = path.fromUri(Platform.script); | 77 var mode = argv.first; |
57 var dartDir = path.dirname(path.dirname(path.absolute(base))); | 78 if (mode != 'vm' && mode != 'dart2js') usage('[vm|dart2js]'); |
| 79 if (argv.length != 5) usage(mode); |
58 | 80 |
59 if (argv.length != 5 || argv.first != 'vm') { | 81 bool forVm = mode == 'vm'; |
60 final self = path.relative(base); | 82 bool forDart2js = mode == 'dart2js'; |
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 } | |
74 | |
75 var mode = argv[0]; | |
76 assert(mode == "vm"); | |
77 var input = argv[1]; | 83 var input = argv[1]; |
78 var sdkLibIn = path.join(input, 'lib'); | 84 var sdkLibIn = path.join(input, 'lib'); |
79 var patchIn = argv[2]; | 85 var patchIn = argv[2]; |
80 var outDir = argv[3]; | 86 var outDir = argv[3]; |
| 87 var outDirUri = Uri.base.resolveUri(new Uri.directory(outDir)); |
81 var sdkOut = path.join(outDir, 'lib'); | 88 var sdkOut = path.join(outDir, 'lib'); |
82 var packagesFile = argv[4]; | 89 var packagesFile = argv[4]; |
83 | 90 |
84 // Copy and patch libraries.dart and version | 91 // Parse libraries.dart |
85 var libContents = readInputFile(path.join( | 92 var libContents = readInputFile(path.join( |
86 sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); | 93 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 |
87 libContents = libContents.replaceAll( | 144 libContents = libContents.replaceAll( |
88 ' libraries = const {', | 145 ' libraries = const {', |
89 ''' libraries = const { | 146 ''' libraries = const { |
90 | 147 |
91 "_builtin": const LibraryInfo( | 148 "_builtin": const LibraryInfo( |
92 "_builtin/_builtin.dart", | 149 "_builtin/_builtin.dart", |
93 categories: "Client,Server", | 150 categories: "Client,Server", |
94 implementation: true, | 151 implementation: true, |
95 documented: false, | 152 documented: false, |
96 platforms: VM_PLATFORM), | 153 platforms: VM_PLATFORM), |
(...skipping 13 matching lines...) Expand all Loading... |
110 "vmservice_io/vmservice_io.dart", | 167 "vmservice_io/vmservice_io.dart", |
111 implementation: true, | 168 implementation: true, |
112 documented: false, | 169 documented: false, |
113 platforms: VM_PLATFORM), | 170 platforms: VM_PLATFORM), |
114 | 171 |
115 '''); | 172 '''); |
116 _writeSync( | 173 _writeSync( |
117 path.join( | 174 path.join( |
118 sdkOut, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'), | 175 sdkOut, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'), |
119 libContents); | 176 libContents); |
| 177 return libContents; |
| 178 } |
120 | 179 |
121 // Parse libraries.dart | 180 /// Copy internal libraries that are developed under 'runtime/bin/' to the |
122 var sdkLibraries = _getSdkLibraries(libContents); | 181 /// patched_sdk folder. |
123 | 182 _copyExtraVmLibraries(String sdkOut) { |
124 // Enumerate core libraries and apply patches | 183 var base = path.fromUri(Platform.script); |
125 for (SdkLibrary library in sdkLibraries) { | 184 var dartDir = path.dirname(path.dirname(path.absolute(base))); |
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 } | |
195 | 185 |
196 for (var tuple in [ | 186 for (var tuple in [ |
197 ['_builtin', 'builtin.dart'] | 187 ['_builtin', 'builtin.dart'] |
198 ]) { | 188 ]) { |
199 var vmLibrary = tuple[0]; | 189 var vmLibrary = tuple[0]; |
200 var dartFile = tuple[1]; | 190 var dartFile = tuple[1]; |
201 | 191 |
202 // The "dart:_builtin" library is only available for the DartVM. | 192 // The "dart:_builtin" library is only available for the DartVM. |
203 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile); | 193 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile); |
204 var builtinLibraryOut = path.join(sdkOut, vmLibrary, '${vmLibrary}.dart'); | 194 var builtinLibraryOut = path.join(sdkOut, vmLibrary, '${vmLibrary}.dart'); |
205 _writeSync(builtinLibraryOut, readInputFile(builtinLibraryIn)); | 195 _writeSync(builtinLibraryOut, readInputFile(builtinLibraryIn)); |
206 } | 196 } |
207 | 197 |
208 for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) { | 198 for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) { |
209 var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file); | 199 var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file); |
210 var libraryOut = path.join(sdkOut, 'vmservice_io', file); | 200 var libraryOut = path.join(sdkOut, 'vmservice_io', file); |
211 _writeSync(libraryOut, readInputFile(libraryIn)); | 201 _writeSync(libraryOut, readInputFile(libraryIn)); |
212 } | 202 } |
| 203 } |
213 | 204 |
214 Uri platform = Uri.base | 205 _applyPatch( |
215 .resolveUri(new Uri.directory(outDir).resolve('platform.dill.tmp')); | 206 SdkLibrary library, String sdkLibIn, String patchIn, String sdkOut) { |
216 Uri packages = Uri.base.resolveUri(new Uri.file(packagesFile)); | 207 var libraryOut = path.join(sdkLibIn, library.path); |
217 await compilePlatform( | 208 var libraryIn = libraryOut; |
218 Uri.base.resolveUri(new Uri.directory(outDir)), platform, | |
219 packages: packages, verbose: false); | |
220 | 209 |
221 Uri platformFinalLocation = | 210 var libraryFile = getInputFile(libraryIn, canBeMissing: true); |
222 Uri.base.resolveUri(new Uri.directory(outDir).resolve('platform.dill')); | 211 if (libraryFile != null) { |
| 212 var outPaths = <String>[libraryOut]; |
| 213 var libraryContents = libraryFile.readAsStringSync(); |
223 | 214 |
224 await writeDepsFile(Platform.script, | 215 int inputModifyTime = libraryFile.lastModifiedSync().millisecondsSinceEpoch; |
225 Uri.base.resolveUri(new Uri.file("$outDir.d")), platformFinalLocation, | 216 var partFiles = <File>[]; |
226 packages: packages, | 217 for (var part in parseDirectives(libraryContents).directives) { |
227 platform: platform, | 218 if (part is PartDirective) { |
228 extraDependencies: deps, | 219 var partPath = part.uri.stringValue; |
229 verbose: false); | 220 outPaths.add(path.join(path.dirname(libraryOut), partPath)); |
230 | 221 |
231 await new File.fromUri(platform).rename(platformFinalLocation.toFilePath()); | 222 var partFile = |
| 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 } |
232 } | 269 } |
233 | 270 |
234 /// Writes a file, creating the directory if needed. | 271 /// Writes a file, creating the directory if needed. |
235 void _writeSync(String filePath, String contents) { | 272 void _writeSync(String filePath, String contents) { |
236 var outDir = new Directory(path.dirname(filePath)); | 273 var outDir = new Directory(path.dirname(filePath)); |
237 if (!outDir.existsSync()) outDir.createSync(recursive: true); | 274 if (!outDir.existsSync()) outDir.createSync(recursive: true); |
238 | 275 |
239 new File(filePath).writeAsStringSync(contents); | 276 new File(filePath).writeAsStringSync(contents); |
240 } | 277 } |
241 | 278 |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 if (diff != 0) return diff; | 606 if (diff != 0) return diff; |
570 return end - other.end; | 607 return end - other.end; |
571 } | 608 } |
572 } | 609 } |
573 | 610 |
574 List<SdkLibrary> _getSdkLibraries(String contents) { | 611 List<SdkLibrary> _getSdkLibraries(String contents) { |
575 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); | 612 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); |
576 parseCompilationUnit(contents).accept(libraryBuilder); | 613 parseCompilationUnit(contents).accept(libraryBuilder); |
577 return libraryBuilder.librariesMap.sdkLibraries; | 614 return libraryBuilder.librariesMap.sdkLibraries; |
578 } | 615 } |
OLD | NEW |