| 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patch')); | 67 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patch')); |
| 68 final outExample = path.relative( | 68 final outExample = path.relative( |
| 69 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patched_sdk')); | 69 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patched_sdk')); |
| 70 final packagesExample = path.relative(path.join(repositoryDir, '.packages')); | 70 final packagesExample = path.relative(path.join(repositoryDir, '.packages')); |
| 71 print('For example:'); | 71 print('For example:'); |
| 72 print('\$ $self vm $sdkExample $patchExample $outExample $packagesExample'); | 72 print('\$ $self vm $sdkExample $patchExample $outExample $packagesExample'); |
| 73 | 73 |
| 74 exit(1); | 74 exit(1); |
| 75 } | 75 } |
| 76 | 76 |
| 77 const validModes = const ['vm', 'dart2js', 'flutter']; |
| 78 String mode; |
| 79 bool get forVm => mode == 'vm'; |
| 80 bool get forFlutter => mode == 'flutter'; |
| 81 bool get forDart2js => mode == 'dart2js'; |
| 82 |
| 77 Future _main(List<String> argv) async { | 83 Future _main(List<String> argv) async { |
| 78 if (argv.isEmpty) usage('[vm|dart2js]'); | 84 if (argv.isEmpty) usage('[${validModes.join('|')}]'); |
| 79 var mode = argv.first; | 85 mode = argv.first; |
| 80 if (mode != 'vm' && mode != 'dart2js') usage('[vm|dart2js]'); | 86 if (!validModes.contains(mode)) usage('[${validModes.join('|')}]'); |
| 81 if (argv.length != 5) usage(mode); | 87 if (argv.length != 5) usage(mode); |
| 82 | 88 |
| 83 bool forVm = mode == 'vm'; | |
| 84 bool forDart2js = mode == 'dart2js'; | |
| 85 var input = argv[1]; | 89 var input = argv[1]; |
| 86 var sdkLibIn = path.join(input, 'lib'); | 90 var sdkLibIn = path.join(input, 'lib'); |
| 87 var patchIn = argv[2]; | 91 var patchIn = argv[2]; |
| 88 var outDir = argv[3]; | 92 var outDir = argv[3]; |
| 89 var outDirUri = Uri.base.resolveUri(new Uri.directory(outDir)); | 93 var outDirUri = Uri.base.resolveUri(new Uri.directory(outDir)); |
| 90 var sdkOut = path.join(outDir, 'lib'); | 94 var sdkOut = path.join(outDir, 'lib'); |
| 91 var packagesFile = argv[4]; | 95 var packagesFile = argv[4]; |
| 92 | 96 |
| 93 // Parse libraries.dart | 97 // Parse libraries.dart |
| 94 var libContents = readInputFile(path.join( | 98 var libContents = readInputFile(path.join( |
| 95 sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); | 99 sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); |
| 96 if (forVm) libContents = _updateLibraryMetadata(sdkOut, libContents); | 100 libContents = _updateLibraryMetadata(sdkOut, libContents); |
| 97 var sdkLibraries = _getSdkLibraries(libContents, forDart2js); | 101 var sdkLibraries = _getSdkLibraries(libContents); |
| 98 | 102 |
| 99 Map<String, String> locations = <String, String>{}; | 103 Map<String, String> locations = <String, String>{}; |
| 100 | 104 |
| 101 // Enumerate core libraries and apply patches | 105 // Enumerate core libraries and apply patches |
| 102 for (SdkLibrary library in sdkLibraries) { | 106 for (SdkLibrary library in sdkLibraries) { |
| 103 if (forDart2js && library.isVmLibrary) continue; | 107 if (forDart2js && library.isVmLibrary) continue; |
| 104 if (forVm && library.isDart2JsLibrary) continue; | 108 if (!forDart2js && library.isDart2JsLibrary) continue; |
| 105 _applyPatch(library, sdkLibIn, patchIn, sdkOut, locations); | 109 _applyPatch(library, sdkLibIn, patchIn, sdkOut, locations); |
| 106 } | 110 } |
| 107 | 111 |
| 108 if (forVm) _copyExtraVmLibraries(sdkOut, locations); | 112 _copyExtraLibraries(sdkOut, locations); |
| 109 | 113 |
| 110 Uri platform = outDirUri.resolve('platform.dill.tmp'); | 114 Uri platform = outDirUri.resolve('platform.dill.tmp'); |
| 111 Uri outline = outDirUri.resolve('outline.dill'); | 115 Uri outline = outDirUri.resolve('outline.dill'); |
| 112 Uri vmserviceIo = outDirUri.resolve('vmservice_io.dill'); | |
| 113 Uri librariesJson = outDirUri.resolve("lib/libraries.json"); | 116 Uri librariesJson = outDirUri.resolve("lib/libraries.json"); |
| 114 Uri packages = Uri.base.resolveUri(new Uri.file(packagesFile)); | 117 Uri packages = Uri.base.resolveUri(new Uri.file(packagesFile)); |
| 115 | 118 |
| 116 await _writeSync( | 119 await _writeSync( |
| 117 librariesJson.toFilePath(), JSON.encode({"libraries": locations})); | 120 librariesJson.toFilePath(), JSON.encode({"libraries": locations})); |
| 118 | 121 |
| 119 if (forVm) { | 122 if (forVm || forFlutter) { |
| 123 var vmserviceName = forVm ? 'vmservice_io' : 'vmservice_sky'; |
| 124 var targetName = forVm ? 'vm_fasta' : 'flutter_fasta'; |
| 125 Uri vmserviceUri = outDirUri.resolve('$vmserviceName.dill'); |
| 120 await fasta.compilePlatform(outDirUri, platform, | 126 await fasta.compilePlatform(outDirUri, platform, |
| 121 packages: packages, outlineOutput: outline); | 127 packages: packages, |
| 128 outlineOutput: outline, |
| 129 backendTarget: forVm ? 'vm_fasta' : 'flutter_fasta'); |
| 122 await fasta.compile([ | 130 await fasta.compile([ |
| 123 "--sdk=${outDirUri.toString()}", | 131 "--sdk=$outDirUri", |
| 124 "--platform=${outline.toString()}", | 132 "--platform=$outline", |
| 125 "--packages=${packages.toString()}", | 133 "--target=$targetName", |
| 126 "dart:vmservice_io", | 134 "--packages=$packages", |
| 135 "dart:$vmserviceName", |
| 127 "-o", | 136 "-o", |
| 128 vmserviceIo.toString() | 137 "$vmserviceUri", |
| 129 ]); | 138 ]); |
| 130 } else { | 139 } else { |
| 131 await dart2js.compilePlatform(outDirUri, platform, | 140 await dart2js.compilePlatform(outDirUri, platform, |
| 132 packages: packages, outlineOutput: outline); | 141 packages: packages, outlineOutput: outline); |
| 133 } | 142 } |
| 134 | 143 |
| 135 Uri platformFinalLocation = outDirUri.resolve('platform.dill'); | 144 Uri platformFinalLocation = outDirUri.resolve('platform.dill'); |
| 136 | 145 |
| 137 // To properly regenerate the patched_sdk, patched_dart2js_sdk, and | 146 // We generate a dependency file for GN to properly regenerate the patched sdk |
| 138 // platform.dill only when necessary, we track dependencies as follows: | 147 // folder, outline.dill and platform.dill files when necessary: either when |
| 139 // - inputs like the sdk libraries and patch files are covered by the | 148 // the sdk sources change or when this script is updated. In particular: |
| 140 // extraDependencies argument. | 149 // |
| 141 // - this script and its script dependencies are handled by writeDepsFile | 150 // - sdk changes: we track the actual sources we are compiling. If we are |
| 142 // here. | 151 // building the dart2js sdk, this includes the dart2js-specific patch |
| 143 // - the internal platform libraries that may affect how this script | 152 // files. |
| 144 // runs in the VM are discovered by providing the `platform` argument | 153 // |
| 145 // below. Regardless of patched_sdk or patched_dart2js_sdk we provide below | 154 // These files are tracked by [deps] and passed below to [writeDepsFile] in |
| 146 // the .dill file of patched_sdk (since the script runs in the VM and not | 155 // the extraDependencies argument. |
| 147 // in dart2js). At the BUILD.gn level we have a dependency from | 156 // |
| 148 // patched_dart2js_sdk to patched_sdk to ensure that file already exists. | 157 // - script updates: we track this script file and any code it imports (even |
| 158 // sdk libraries). Note that this script runs on the standalone VM, so any |
| 159 // sdk library used by this script indirectly depends on a VM-specific |
| 160 // patch file. |
| 161 // |
| 162 // These set of files is discovered by `writeDepsFile` below, and the |
| 163 // [platformForDeps] is always the VM-specific `platform.dill` file. |
| 164 // |
| 165 // TODO(sigmund): we should change this: |
| 166 // - we should rewrite writeDepsFile: fasta could provide an API to crawl |
| 167 // the dependencies, but anything that is GN specific, should be on |
| 168 // this file instead. |
| 169 // |
| 170 // - We don't need to include sdk dependencies of the script because |
| 171 // those are already included indirectly (either in [deps] when |
| 172 // building the sdk for the VM, or via the .GN dependencies in the |
| 173 // build files for dart2js and flutter). |
| 174 var platformForDeps = platform; |
| 175 var sdkDir = outDirUri; |
| 176 if (forDart2js || forFlutter) { |
| 177 // Note: this would fail if `../patched_sdk/platform.dill` doesn't exist. We |
| 178 // added an explicit dependency in the .GN rules so patched_dart2js_sdk (and |
| 179 // patched_flutter_sdk) depend on patched_sdk to ensure that it exists. |
| 180 platformForDeps = outDirUri.resolve('../patched_sdk/platform.dill'); |
| 181 sdkDir = outDirUri.resolve('../patched_sdk/'); |
| 182 } |
| 149 await fasta.writeDepsFile(Platform.script, | 183 await fasta.writeDepsFile(Platform.script, |
| 150 Uri.base.resolveUri(new Uri.file("$outDir.d")), platformFinalLocation, | 184 Uri.base.resolveUri(new Uri.file("$outDir.d")), platformFinalLocation, |
| 151 sdk: outDirUri, | 185 sdk: sdkDir, |
| 152 packages: packages, | 186 packages: packages, |
| 153 platform: | 187 platform: platformForDeps, |
| 154 forVm ? platform : outDirUri.resolve('../patched_sdk/platform.dill'), | |
| 155 extraDependencies: deps); | 188 extraDependencies: deps); |
| 156 | 189 |
| 157 await new File.fromUri(platform).rename(platformFinalLocation.toFilePath()); | 190 await new File.fromUri(platform).rename(platformFinalLocation.toFilePath()); |
| 158 } | 191 } |
| 159 | 192 |
| 160 /// Updates the contents of | 193 /// Updates the contents of |
| 161 /// sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart to include | 194 /// sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart to include |
| 162 /// declarations for vm internal libraries. | 195 /// declarations for vm internal libraries. |
| 163 String _updateLibraryMetadata(String sdkOut, String libContents) { | 196 String _updateLibraryMetadata(String sdkOut, String libContents) { |
| 164 // Copy and patch libraries.dart and version | 197 if (!forVm && !forFlutter) return libContents; |
| 165 libContents = libContents.replaceAll( | 198 var extraLibraries = new StringBuffer(); |
| 166 ' libraries = const {', | 199 extraLibraries.write(''' |
| 167 ''' libraries = const { | |
| 168 | |
| 169 "_builtin": const LibraryInfo( | 200 "_builtin": const LibraryInfo( |
| 170 "_builtin/_builtin.dart", | 201 "_builtin/_builtin.dart", |
| 171 categories: "Client,Server", | 202 categories: "Client,Server", |
| 172 implementation: true, | 203 implementation: true, |
| 173 documented: false, | 204 documented: false, |
| 174 platforms: VM_PLATFORM), | 205 platforms: VM_PLATFORM), |
| 175 | 206 |
| 176 "profiler": const LibraryInfo( | 207 "profiler": const LibraryInfo( |
| 177 "profiler/profiler.dart", | 208 "profiler/profiler.dart", |
| 178 maturity: Maturity.DEPRECATED, | 209 maturity: Maturity.DEPRECATED, |
| 179 documented: false), | 210 documented: false), |
| 180 '''); | 211 '''); |
| 212 |
| 213 if (forFlutter) { |
| 214 extraLibraries.write(''' |
| 215 "ui": const LibraryInfo( |
| 216 "ui/ui.dart", |
| 217 categories: "Client,Server", |
| 218 implementation: true, |
| 219 documented: false, |
| 220 platforms: VM_PLATFORM), |
| 221 '''); |
| 222 } |
| 223 |
| 224 libContents = libContents.replaceAll( |
| 225 ' libraries = const {', ' libraries = const { $extraLibraries'); |
| 181 _writeSync( | 226 _writeSync( |
| 182 path.join( | 227 path.join( |
| 183 sdkOut, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'), | 228 sdkOut, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'), |
| 184 libContents); | 229 libContents); |
| 185 return libContents; | 230 return libContents; |
| 186 } | 231 } |
| 187 | 232 |
| 188 /// Copy internal libraries that are developed under 'runtime/bin/' to the | 233 /// Copy internal libraries that are developed outside the sdk folder into the |
| 189 /// patched_sdk folder. | 234 /// patched_sdk folder. For the VM< this includes files under 'runtime/bin/', |
| 190 _copyExtraVmLibraries(String sdkOut, Map<String, String> locations) { | 235 /// for flutter, this is includes also the ui library. |
| 236 _copyExtraLibraries(String sdkOut, Map<String, String> locations) { |
| 237 if (forDart2js) return; |
| 191 var base = path.fromUri(Platform.script); | 238 var base = path.fromUri(Platform.script); |
| 192 var dartDir = path.dirname(path.dirname(path.absolute(base))); | 239 var dartDir = path.dirname(path.dirname(path.absolute(base))); |
| 193 | 240 |
| 194 for (var tuple in [ | 241 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', 'builtin.dart'); |
| 195 ['_builtin', 'builtin.dart'] | 242 var builtinLibraryOut = path.join(sdkOut, '_builtin', '_builtin.dart'); |
| 196 ]) { | 243 _writeSync(builtinLibraryOut, readInputFile(builtinLibraryIn)); |
| 197 var vmLibrary = tuple[0]; | 244 locations['_builtin'] = path.join('_builtin', '_builtin.dart'); |
| 198 var dartFile = tuple[1]; | |
| 199 | |
| 200 // The "dart:_builtin" library is only available for the DartVM. | |
| 201 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile); | |
| 202 var builtinLibraryOut = path.join(sdkOut, vmLibrary, '${vmLibrary}.dart'); | |
| 203 _writeSync(builtinLibraryOut, readInputFile(builtinLibraryIn)); | |
| 204 locations[vmLibrary] = path.join(vmLibrary, '${vmLibrary}.dart'); | |
| 205 } | |
| 206 | 245 |
| 207 for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) { | 246 for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) { |
| 208 var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file); | 247 var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file); |
| 209 var libraryOut = path.join(sdkOut, 'vmservice_io', file); | 248 var libraryOut = path.join(sdkOut, 'vmservice_io', file); |
| 210 _writeSync(libraryOut, readInputFile(libraryIn)); | 249 _writeSync(libraryOut, readInputFile(libraryIn)); |
| 211 } | 250 } |
| 212 locations["vmservice_io"] = "vmservice_io/vmservice_io.dart"; | 251 |
| 213 locations["_vmservice"] = "vmservice/vmservice.dart"; | 252 locations[forVm ? "vmservice_io" : "vmservice_sky"] = |
| 253 path.join('vmservice_io', 'vmservice_io.dart'); |
| 254 locations["_vmservice"] = path.join('vmservice', 'vmservice.dart'); |
| 255 |
| 256 if (forFlutter) { |
| 257 // Flutter repo has this layout: |
| 258 // engine/src/ |
| 259 // dart/ |
| 260 // flutter/ |
| 261 var srcDir = path.dirname(path.dirname(path.dirname(path.absolute(base)))); |
| 262 var uiLibraryInDir = path.join(srcDir, 'flutter', 'lib', 'ui'); |
| 263 for (var file in new Directory(uiLibraryInDir).listSync()) { |
| 264 if (!file.path.endsWith('.dart')) continue; |
| 265 var name = path.basename(file.path); |
| 266 var uiLibraryOut = path.join(sdkOut, 'ui', name); |
| 267 _writeSync(uiLibraryOut, readInputFile(file.path)); |
| 268 } |
| 269 locations['ui'] = 'ui/ui.dart'; |
| 270 } |
| 214 } | 271 } |
| 215 | 272 |
| 216 _applyPatch(SdkLibrary library, String sdkLibIn, String patchIn, String sdkOut, | 273 _applyPatch(SdkLibrary library, String sdkLibIn, String patchIn, String sdkOut, |
| 217 Map<String, String> locations) { | 274 Map<String, String> locations) { |
| 218 var libraryOut = path.join(sdkLibIn, library.path); | 275 var libraryOut = path.join(sdkLibIn, library.path); |
| 219 var libraryIn = libraryOut; | 276 var libraryIn = libraryOut; |
| 220 | 277 |
| 221 var libraryFile = getInputFile(libraryIn, canBeMissing: true); | 278 var libraryFile = getInputFile(libraryIn, canBeMissing: true); |
| 222 if (libraryFile != null) { | 279 if (libraryFile != null) { |
| 223 locations[Uri.parse(library.shortName).path] = | 280 locations[Uri.parse(library.shortName).path] = |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 | 671 |
| 615 String toString() => '(Edit @ $begin,$end: "$replace")'; | 672 String toString() => '(Edit @ $begin,$end: "$replace")'; |
| 616 | 673 |
| 617 int compareTo(_StringEdit other) { | 674 int compareTo(_StringEdit other) { |
| 618 int diff = begin - other.begin; | 675 int diff = begin - other.begin; |
| 619 if (diff != 0) return diff; | 676 if (diff != 0) return diff; |
| 620 return end - other.end; | 677 return end - other.end; |
| 621 } | 678 } |
| 622 } | 679 } |
| 623 | 680 |
| 624 List<SdkLibrary> _getSdkLibraries(String contents, bool useDart2js) { | 681 List<SdkLibrary> _getSdkLibraries(String contents) { |
| 625 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(useDart2js); | 682 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(forDart2js); |
| 626 parseCompilationUnit(contents).accept(libraryBuilder); | 683 parseCompilationUnit(contents).accept(libraryBuilder); |
| 627 return libraryBuilder.librariesMap.sdkLibraries; | 684 return libraryBuilder.librariesMap.sdkLibraries; |
| 628 } | 685 } |
| OLD | NEW |