Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1121)

Side by Side Diff: tools/patch_sdk.dart

Issue 2742333006: Move patch file generation to fasta. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/front_end/lib/src/fasta/vm.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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:async'; 11 import 'dart:async';
11 import 'dart:math' as math; 12 import 'dart:math' as math;
12 13
13 import 'package:analyzer/analyzer.dart'; 14 import 'package:analyzer/analyzer.dart';
14 import 'package:analyzer/src/generated/sdk.dart'; 15 import 'package:analyzer/src/generated/sdk.dart';
15 import 'package:path/path.dart' as path; 16 import 'package:path/path.dart' as path;
16 import 'package:front_end/src/fasta/compile_platform.dart' as compile_platform;
17 17
18 import 'package:front_end/src/fasta/fasta.dart' show CompileTask; 18 import 'package:front_end/src/fasta/fasta.dart'
19 19 show compilePlatform, writeDepsFile;
20 import 'package:front_end/src/fasta/compiler_command_line.dart'
21 show CompilerCommandLine;
22
23 import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
24
25 import 'package:front_end/src/fasta/ticker.dart' show Ticker;
26 20
27 /// Set of input files that were read by this script to generate patched SDK. 21 /// Set of input files that were read by this script to generate patched SDK.
28 /// We will dump it out into the depfile for ninja to use. 22 /// We will dump it out into the depfile for ninja to use.
29 /// 23 ///
30 /// For more information see GN and Ninja references: 24 /// For more information see GN and Ninja references:
31 /// https://chromium.googlesource.com/chromium/src/+/56807c6cb383140af0c03da8 f6731d77785d7160/tools/gn/docs/reference.md#depfile_string_File-name-for-input-d ependencies-for-actions 25 /// https://chromium.googlesource.com/chromium/src/+/56807c6cb383140af0c03da8 f6731d77785d7160/tools/gn/docs/reference.md#depfile_string_File-name-for-input-d ependencies-for-actions
32 /// https://ninja-build.org/manual.html#_depfile 26 /// https://ninja-build.org/manual.html#_depfile
33 /// 27 ///
34 final deps = new Set<String>(); 28 final deps = new Set<Uri>();
35 29
36 /// Create [File] object from the given path and register it as a dependency. 30 /// Create [File] object from the given path and register it as a dependency.
37 File getInputFile(String path, {canBeMissing: false}) { 31 File getInputFile(String path, {canBeMissing: false}) {
38 final file = new File(path); 32 final file = new File(path);
39 if (!file.existsSync()) { 33 if (!file.existsSync()) {
40 if (!canBeMissing) throw "patch_sdk.dart expects all inputs to exist"; 34 if (!canBeMissing) throw "patch_sdk.dart expects all inputs to exist";
41 return null; 35 return null;
42 } 36 }
43 deps.add(file.absolute.path); 37 deps.add(Uri.base.resolveUri(file.uri));
44 return file; 38 return file;
45 } 39 }
46 40
47 /// Read the given file synchronously as a string and register this path as 41 /// Read the given file synchronously as a string and register this path as
48 /// a dependency. 42 /// a dependency.
49 String readInputFile(String path, {canBeMissing: false}) => 43 String readInputFile(String path, {canBeMissing: false}) =>
50 getInputFile(path, canBeMissing: canBeMissing)?.readAsStringSync(); 44 getInputFile(path, canBeMissing: canBeMissing)?.readAsStringSync();
51 45
52 Future main(List<String> argv) async { 46 Future main(List<String> argv) async {
53 var base = path.fromUri(Platform.script); 47 var port = new RawReceivePort();
54 var dartDir = path.dirname(path.dirname(path.absolute(base))); 48 try {
Vyacheslav Egorov (Google) 2017/03/15 13:43:59 With such a gigantic try { } finally { } it might
ahe 2017/03/31 15:05:02 Done.
49 var base = path.fromUri(Platform.script);
50 var dartDir = path.dirname(path.dirname(path.absolute(base)));
55 51
56 if (argv.length != 5 || argv.first != 'vm') { 52 if (argv.length != 5 || argv.first != 'vm') {
57 final self = path.relative(base); 53 final self = path.relative(base);
58 print('Usage: $self vm SDK_DIR PATCH_DIR OUTPUT_DIR PACKAGES'); 54 print('Usage: $self vm SDK_DIR PATCH_DIR OUTPUT_DIR PACKAGES');
59 55
60 final repositoryDir = path.relative(path.dirname(path.dirname(base))); 56 final repositoryDir = path.relative(path.dirname(path.dirname(base)));
61 final sdkExample = path.relative(path.join(repositoryDir, 'sdk')); 57 final sdkExample = path.relative(path.join(repositoryDir, 'sdk'));
62 final patchExample = path.relative( 58 final patchExample = path.relative(
63 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patch')); 59 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patch'));
64 final outExample = path.relative(path.join( 60 final outExample = path.relative(path.join(
65 repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patched_sdk')); 61 repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patched_sdk'));
66 print('For example:'); 62 print('For example:');
67 print('\$ $self vm $sdkExample $patchExample $outExample'); 63 print('\$ $self vm $sdkExample $patchExample $outExample');
68 64
69 exit(1); 65 exit(1);
70 } 66 }
71 67
72 var mode = argv[0]; 68 var mode = argv[0];
73 assert(mode == "vm"); 69 assert(mode == "vm");
74 var input = argv[1]; 70 var input = argv[1];
75 var sdkLibIn = path.join(input, 'lib'); 71 var sdkLibIn = path.join(input, 'lib');
76 var patchIn = argv[2]; 72 var patchIn = argv[2];
77 var outDir = argv[3]; 73 var outDir = argv[3];
78 var sdkOut = path.join(outDir, 'lib'); 74 var sdkOut = path.join(outDir, 'lib');
79 var packagesFile = argv[4]; 75 var packagesFile = argv[4];
80 76
81 // Copy and patch libraries.dart and version 77 // Copy and patch libraries.dart and version
82 var libContents = readInputFile(path.join( 78 var libContents = readInputFile(path.join(sdkLibIn, '_internal',
83 sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); 79 'sdk_library_metadata', 'lib', 'libraries.dart'));
84 libContents = libContents.replaceAll( 80 libContents = libContents.replaceAll(
85 ' libraries = const {', 81 ' libraries = const {',
86 ''' libraries = const { 82 ''' libraries = const {
87 83
88 "_builtin": const LibraryInfo( 84 "_builtin": const LibraryInfo(
89 "_builtin/_builtin.dart", 85 "_builtin/_builtin.dart",
90 categories: "Client,Server", 86 categories: "Client,Server",
91 implementation: true, 87 implementation: true,
92 documented: false, 88 documented: false,
93 platforms: VM_PLATFORM), 89 platforms: VM_PLATFORM),
94 90
95 "profiler": const LibraryInfo( 91 "profiler": const LibraryInfo(
96 "profiler/profiler.dart", 92 "profiler/profiler.dart",
97 maturity: Maturity.DEPRECATED, 93 maturity: Maturity.DEPRECATED,
98 documented: false), 94 documented: false),
99 95
100 "_vmservice": const LibraryInfo( 96 "_vmservice": const LibraryInfo(
101 "vmservice/vmservice.dart", 97 "vmservice/vmservice.dart",
102 implementation: true, 98 implementation: true,
103 documented: false, 99 documented: false,
104 platforms: VM_PLATFORM), 100 platforms: VM_PLATFORM),
105 101
106 "vmservice_io": const LibraryInfo( 102 "vmservice_io": const LibraryInfo(
107 "vmservice_io/vmservice_io.dart", 103 "vmservice_io/vmservice_io.dart",
108 implementation: true, 104 implementation: true,
109 documented: false, 105 documented: false,
110 platforms: VM_PLATFORM), 106 platforms: VM_PLATFORM),
111 107
112 '''); 108 ''');
113 _writeSync( 109 _writeSync(
114 path.join( 110 path.join(sdkOut, '_internal', 'sdk_library_metadata', 'lib',
115 sdkOut, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'), 111 'libraries.dart'),
116 libContents); 112 libContents);
117 113
118 // Parse libraries.dart 114 // Parse libraries.dart
119 var sdkLibraries = _getSdkLibraries(libContents); 115 var sdkLibraries = _getSdkLibraries(libContents);
120 116
121 // Enumerate core libraries and apply patches 117 // Enumerate core libraries and apply patches
122 for (SdkLibrary library in sdkLibraries) { 118 for (SdkLibrary library in sdkLibraries) {
123 if (library.isDart2JsLibrary) { 119 if (library.isDart2JsLibrary) {
124 continue; 120 continue;
125 }
126
127 var libraryOut = path.join(sdkLibIn, library.path);
128 var libraryIn = libraryOut;
129
130 var libraryFile = getInputFile(libraryIn, canBeMissing: true);
131 if (libraryFile != null) {
132 var outPaths = <String>[libraryOut];
133 var libraryContents = libraryFile.readAsStringSync();
134
135 int inputModifyTime =
136 libraryFile.lastModifiedSync().millisecondsSinceEpoch;
137 var partFiles = <File>[];
138 for (var part in parseDirectives(libraryContents).directives) {
139 if (part is PartDirective) {
140 var partPath = part.uri.stringValue;
141 outPaths.add(path.join(path.dirname(libraryOut), partPath));
142
143 var partFile =
144 getInputFile(path.join(path.dirname(libraryIn), partPath));
145 partFiles.add(partFile);
146 inputModifyTime = math.max(inputModifyTime,
147 partFile.lastModifiedSync().millisecondsSinceEpoch);
148 }
149 } 121 }
150 122
151 // See if we can find a patch file. 123 var libraryOut = path.join(sdkLibIn, library.path);
152 var patchPath = path.join( 124 var libraryIn = libraryOut;
153 patchIn, path.basenameWithoutExtension(libraryIn) + '_patch.dart');
154 125
155 var patchFile = getInputFile(patchPath, canBeMissing: true); 126 var libraryFile = getInputFile(libraryIn, canBeMissing: true);
156 if (patchFile != null) { 127 if (libraryFile != null) {
157 inputModifyTime = math.max(inputModifyTime, 128 var outPaths = <String>[libraryOut];
158 patchFile.lastModifiedSync().millisecondsSinceEpoch); 129 var libraryContents = libraryFile.readAsStringSync();
159 }
160 130
161 // Compute output paths 131 int inputModifyTime =
162 outPaths = outPaths 132 libraryFile.lastModifiedSync().millisecondsSinceEpoch;
163 .map((p) => path.join(sdkOut, path.relative(p, from: sdkLibIn))) 133 var partFiles = <File>[];
164 .toList(); 134 for (var part in parseDirectives(libraryContents).directives) {
135 if (part is PartDirective) {
136 var partPath = part.uri.stringValue;
137 outPaths.add(path.join(path.dirname(libraryOut), partPath));
165 138
166 // Compare output modify time with input modify time. 139 var partFile =
167 bool needsUpdate = false; 140 getInputFile(path.join(path.dirname(libraryIn), partPath));
168 for (var outPath in outPaths) { 141 partFiles.add(partFile);
169 var outFile = new File(outPath); 142 inputModifyTime = math.max(inputModifyTime,
170 if (!outFile.existsSync() || 143 partFile.lastModifiedSync().millisecondsSinceEpoch);
171 outFile.lastModifiedSync().millisecondsSinceEpoch < 144 }
172 inputModifyTime) {
173 needsUpdate = true;
174 break;
175 }
176 }
177
178 if (needsUpdate) {
179 var contents = <String>[libraryContents];
180 contents.addAll(partFiles.map((f) => f.readAsStringSync()));
181 if (patchFile != null) {
182 var patchContents = patchFile.readAsStringSync();
183 contents = _patchLibrary(patchFile.path, contents, patchContents);
184 } 145 }
185 146
186 for (var i = 0; i < outPaths.length; i++) { 147 // See if we can find a patch file.
187 _writeSync(outPaths[i], contents[i]); 148 var patchPath = path.join(
149 patchIn, path.basenameWithoutExtension(libraryIn) + '_patch.dart');
150
151 var patchFile = getInputFile(patchPath, canBeMissing: true);
152 if (patchFile != null) {
153 inputModifyTime = math.max(inputModifyTime,
154 patchFile.lastModifiedSync().millisecondsSinceEpoch);
155 }
156
157 // Compute output paths
158 outPaths = outPaths
159 .map((p) => path.join(sdkOut, path.relative(p, from: sdkLibIn)))
160 .toList();
161
162 // Compare output modify time with input modify time.
163 bool needsUpdate = false;
164 for (var outPath in outPaths) {
165 var outFile = new File(outPath);
166 if (!outFile.existsSync() ||
167 outFile.lastModifiedSync().millisecondsSinceEpoch <
168 inputModifyTime) {
169 needsUpdate = true;
170 break;
171 }
172 }
173
174 if (needsUpdate) {
175 var contents = <String>[libraryContents];
176 contents.addAll(partFiles.map((f) => f.readAsStringSync()));
177 if (patchFile != null) {
178 var patchContents = patchFile.readAsStringSync();
179 contents = _patchLibrary(patchFile.path, contents, patchContents);
180 }
181
182 for (var i = 0; i < outPaths.length; i++) {
183 _writeSync(outPaths[i], contents[i]);
184 }
188 } 185 }
189 } 186 }
190 } 187 }
191 }
192 188
193 for (var tuple in [ 189 for (var tuple in [
194 ['_builtin', 'builtin.dart'] 190 ['_builtin', 'builtin.dart']
195 ]) { 191 ]) {
196 var vmLibrary = tuple[0]; 192 var vmLibrary = tuple[0];
197 var dartFile = tuple[1]; 193 var dartFile = tuple[1];
198 194
199 // The "dart:_builtin" library is only available for the DartVM. 195 // The "dart:_builtin" library is only available for the DartVM.
200 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile); 196 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile);
201 var builtinLibraryOut = path.join(sdkOut, vmLibrary, '${vmLibrary}.dart'); 197 var builtinLibraryOut = path.join(sdkOut, vmLibrary, '${vmLibrary}.dart');
202 _writeSync(builtinLibraryOut, readInputFile(builtinLibraryIn)); 198 _writeSync(builtinLibraryOut, readInputFile(builtinLibraryIn));
203 } 199 }
204 200
205 for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) { 201 for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) {
206 var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file); 202 var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file);
207 var libraryOut = path.join(sdkOut, 'vmservice_io', file); 203 var libraryOut = path.join(sdkOut, 'vmservice_io', file);
208 _writeSync(libraryOut, readInputFile(libraryIn)); 204 _writeSync(libraryOut, readInputFile(libraryIn));
209 } 205 }
210 206
211 final platform = path.join(outDir, 'platform.dill'); 207 Uri platform = Uri.base
208 .resolveUri(new Uri.directory(outDir).resolve('platform.dill.tmp'));
209 Uri packages = Uri.base.resolveUri(new Uri.file(packagesFile));
210 await compilePlatform(
211 Uri.base.resolveUri(new Uri.directory(outDir)), platform,
212 packages: packages, verbose: false);
212 213
213 await compile_platform.mainEntryPoint(<String>[ 214 Uri platformFinalLocation =
214 '--packages', 215 Uri.base.resolveUri(new Uri.directory(outDir).resolve('platform.dill'));
215 new Uri.file(packagesFile).toString(),
216 new Uri.directory(outDir).toString(),
217 platform,
218 ]);
219 216
220 // TODO(kustermann): We suppress compiler hints/warnings/errors temporarily 217 await writeDepsFile(Platform.script,
221 // because everyone building the `runtime` target will get these now. 218 Uri.base.resolveUri(new Uri.file("$outDir.d")), platformFinalLocation,
222 // We should remove the suppression again once the underlying issues have 219 packages: packages,
223 // been fixed (either in fasta or the dart files in the patched_sdk). 220 platform: platform,
224 final capturedLines = <String>[]; 221 extraDependencies: deps,
225 try { 222 verbose: false);
226 await runZoned(() async {
227 // platform.dill was generated, now generate platform.dill.d depfile
228 // that captures all dependencies that participated in the generation.
229 // There are two types of dependencies:
230 // (1) all Dart sources that constitute this tool itself
231 // (2) Dart SDK and patch sources.
232 // We already collected all inputs from the second category in the deps
233 // set. To collect inputs from the first category we actually use Fasta:
234 // we ask Fasta to outline patch_sdk.dart and generate a depfile which
235 // would list all the sources.
236 final depfile = "${outDir}.d";
237 await CompilerCommandLine.withGlobalOptions("outline", [
238 '--packages',
239 new Uri.file(packagesFile).toString(),
240 '--platform',
241 new Uri.file(platform).toString(), // platform.dill
242 Platform.script.toString() // patch_sdk.dart
243 ], (CompilerContext c) async {
244 CompileTask task =
245 new CompileTask(c, new Ticker(isVerbose: c.options.verbose));
246 final kernelTarget = await task.buildOutline(null);
247 await kernelTarget.writeDepsFile(
248 new Uri.file(platform), new Uri.file(depfile));
249 });
250 223
251 // Read depfile generated by Fasta and append deps that we have collected 224 await new File.fromUri(platform).rename(platformFinalLocation.toFilePath());
252 // during generation of patched_sdk to it. 225 } finally {
253 // Note: we are splitting by ': ' because Windows paths can start with 226 port.close();
254 // drive letter followed by a colon.
255 final list = new File(depfile).readAsStringSync().split(': ');
256 assert(list.length == 2);
257 deps.addAll(list[1].split(' ').where((str) => str.isNotEmpty));
258 assert(list[0] == path.join('patched_sdk', 'platform.dill'));
259 new File(depfile).writeAsStringSync("${list[0]}: ${deps.join(' ')}\n");
260 }, zoneSpecification: new ZoneSpecification(print: (_, _2, _3, line) {
261 capturedLines.add(line);
262 }));
263 } catch (_) {
264 for (final line in capturedLines) {
265 print(line);
266 }
267 rethrow;
268 } 227 }
269 } 228 }
270 229
271 /// Writes a file, creating the directory if needed. 230 /// Writes a file, creating the directory if needed.
272 void _writeSync(String filePath, String contents) { 231 void _writeSync(String filePath, String contents) {
273 var outDir = new Directory(path.dirname(filePath)); 232 var outDir = new Directory(path.dirname(filePath));
274 if (!outDir.existsSync()) outDir.createSync(recursive: true); 233 if (!outDir.existsSync()) outDir.createSync(recursive: true);
275 234
276 new File(filePath).writeAsStringSync(contents); 235 new File(filePath).writeAsStringSync(contents);
277 } 236 }
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 if (diff != 0) return diff; 565 if (diff != 0) return diff;
607 return end - other.end; 566 return end - other.end;
608 } 567 }
609 } 568 }
610 569
611 List<SdkLibrary> _getSdkLibraries(String contents) { 570 List<SdkLibrary> _getSdkLibraries(String contents) {
612 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); 571 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true);
613 parseCompilationUnit(contents).accept(libraryBuilder); 572 parseCompilationUnit(contents).accept(libraryBuilder);
614 return libraryBuilder.librariesMap.sdkLibraries; 573 return libraryBuilder.librariesMap.sdkLibraries;
615 } 574 }
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/vm.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698