| 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 |