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 |