Chromium Code Reviews| Index: tools/patch_sdk.dart |
| diff --git a/tools/patch_sdk.dart b/tools/patch_sdk.dart |
| index 1f64d6366c39473b448b33820cc244678c46b033..005b36a06c8e910b10c70d327713d2ea74e64d10 100644 |
| --- a/tools/patch_sdk.dart |
| +++ b/tools/patch_sdk.dart |
| @@ -52,28 +52,39 @@ Future main(List<String> argv) async { |
| } |
| } |
| -Future _main(List<String> argv) async { |
| +void usage(String mode) { |
|
Vyacheslav Egorov (Google)
2017/04/27 14:07:23
mode is not used in the body of this function
Siggi Cherem (dart-lang)
2017/04/28 21:37:21
oops. Done.
|
| var base = path.fromUri(Platform.script); |
| - var dartDir = path.dirname(path.dirname(path.absolute(base))); |
| + final self = path.relative(base); |
| + print('Usage: $self [vm|dart2js] SDK_DIR PATCH_DIR OUTPUT_DIR PACKAGES'); |
| + |
| + final repositoryDir = path.relative(path.dirname(path.dirname(base))); |
| + final sdkExample = path.relative(path.join(repositoryDir, 'sdk')); |
| + final patchExample = path.relative( |
| + path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patch')); |
| + final outExample = path.relative( |
| + path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patched_sdk')); |
| + final packagesExample = path.relative(path.join(repositoryDir, '.packages')); |
| + print('For example:'); |
| + print('\$ $self vm $sdkExample $patchExample $outExample $packagesExample'); |
| + |
| + exit(1); |
| +} |
| +Future _main(List<String> argv) { |
| + var mode = argv.first; |
| + if (mode == 'vm') return _vmMain(argv); |
| + if (mode == 'dart2js') return _dart2jsMain(argv); |
| + usage('[vm|dart2js]'); |
| + return null; |
| +} |
| + |
| +Future _vmMain(List<String> argv) async { |
|
Vyacheslav Egorov (Google)
2017/04/27 14:07:23
vmMain and dart2jsMain have very similar prefix an
Siggi Cherem (dart-lang)
2017/04/28 21:37:21
Done.
|
| + var base = path.fromUri(Platform.script); |
| + var dartDir = path.dirname(path.dirname(path.absolute(base))); |
| if (argv.length != 5 || argv.first != 'vm') { |
|
Vyacheslav Egorov (Google)
2017/04/27 14:07:23
argv.first != 'vm' can't happen anymore.
Siggi Cherem (dart-lang)
2017/04/28 21:37:21
Done.
|
| - final self = path.relative(base); |
| - print('Usage: $self vm SDK_DIR PATCH_DIR OUTPUT_DIR PACKAGES'); |
| - |
| - final repositoryDir = path.relative(path.dirname(path.dirname(base))); |
| - final sdkExample = path.relative(path.join(repositoryDir, 'sdk')); |
| - final patchExample = path.relative( |
| - path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patch')); |
| - final outExample = path.relative(path.join( |
| - repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patched_sdk')); |
| - print('For example:'); |
| - print('\$ $self vm $sdkExample $patchExample $outExample'); |
| - |
| - exit(1); |
| + usage('vm'); |
| } |
| - var mode = argv[0]; |
| - assert(mode == "vm"); |
| var input = argv[1]; |
| var sdkLibIn = path.join(input, 'lib'); |
| var patchIn = argv[2]; |
| @@ -126,71 +137,7 @@ Future _main(List<String> argv) async { |
| if (library.isDart2JsLibrary) { |
| continue; |
| } |
| - |
| - var libraryOut = path.join(sdkLibIn, library.path); |
| - var libraryIn = libraryOut; |
| - |
| - var libraryFile = getInputFile(libraryIn, canBeMissing: true); |
| - if (libraryFile != null) { |
| - var outPaths = <String>[libraryOut]; |
| - var libraryContents = libraryFile.readAsStringSync(); |
| - |
| - int inputModifyTime = |
| - libraryFile.lastModifiedSync().millisecondsSinceEpoch; |
| - var partFiles = <File>[]; |
| - for (var part in parseDirectives(libraryContents).directives) { |
| - if (part is PartDirective) { |
| - var partPath = part.uri.stringValue; |
| - outPaths.add(path.join(path.dirname(libraryOut), partPath)); |
| - |
| - var partFile = |
| - getInputFile(path.join(path.dirname(libraryIn), partPath)); |
| - partFiles.add(partFile); |
| - inputModifyTime = math.max(inputModifyTime, |
| - partFile.lastModifiedSync().millisecondsSinceEpoch); |
| - } |
| - } |
| - |
| - // See if we can find a patch file. |
| - var patchPath = path.join( |
| - patchIn, path.basenameWithoutExtension(libraryIn) + '_patch.dart'); |
| - |
| - var patchFile = getInputFile(patchPath, canBeMissing: true); |
| - if (patchFile != null) { |
| - inputModifyTime = math.max(inputModifyTime, |
| - patchFile.lastModifiedSync().millisecondsSinceEpoch); |
| - } |
| - |
| - // Compute output paths |
| - outPaths = outPaths |
| - .map((p) => path.join(sdkOut, path.relative(p, from: sdkLibIn))) |
| - .toList(); |
| - |
| - // Compare output modify time with input modify time. |
| - bool needsUpdate = false; |
| - for (var outPath in outPaths) { |
| - var outFile = new File(outPath); |
| - if (!outFile.existsSync() || |
| - outFile.lastModifiedSync().millisecondsSinceEpoch < |
| - inputModifyTime) { |
| - needsUpdate = true; |
| - break; |
| - } |
| - } |
| - |
| - if (needsUpdate) { |
| - var contents = <String>[libraryContents]; |
| - contents.addAll(partFiles.map((f) => f.readAsStringSync())); |
| - if (patchFile != null) { |
| - var patchContents = patchFile.readAsStringSync(); |
| - contents = _patchLibrary(patchFile.path, contents, patchContents); |
| - } |
| - |
| - for (var i = 0; i < outPaths.length; i++) { |
| - _writeSync(outPaths[i], contents[i]); |
| - } |
| - } |
| - } |
| + _applyPatch(library, sdkLibIn, patchIn, sdkOut); |
| } |
| for (var tuple in [ |
| @@ -231,6 +178,128 @@ Future _main(List<String> argv) async { |
| await new File.fromUri(platform).rename(platformFinalLocation.toFilePath()); |
| } |
| +Future _dart2jsMain(List<String> argv) async { |
| + if (argv.length != 5 || argv.first != 'dart2js') { |
| + usage('dart2js'); |
| + } |
| + |
| + var input = argv[1]; |
| + var sdkLibIn = path.join(input, 'lib'); |
| + var patchIn = argv[2]; |
| + var outDir = argv[3]; |
| + var sdkOut = path.join(outDir, 'lib'); |
| + var packagesFile = argv[4]; |
| + |
| + // Parse libraries.dart |
| + var libContents = readInputFile(path.join( |
| + sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); |
| + var sdkLibraries = _getSdkLibraries(libContents); |
| + |
| + // Enumerate core libraries and apply patches |
| + for (SdkLibrary library in sdkLibraries) { |
| + if (library.isVmLibrary) continue; |
| + _applyPatch(library, sdkLibIn, patchIn, sdkOut); |
| + } |
| + |
| + Uri platform = Uri.base |
| + .resolveUri(new Uri.directory(outDir).resolve('platform.dill.tmp')); |
| + Uri packages = Uri.base.resolveUri(new Uri.file(packagesFile)); |
| + await compilePlatform( |
| + Uri.base.resolveUri(new Uri.directory(outDir)), platform, |
| + packages: packages, verbose: false, targetDart2js: true); |
| + |
| + Uri platformFinalLocation = |
| + Uri.base.resolveUri(new Uri.directory(outDir).resolve('platform.dill')); |
| + |
| + // To properly regenerate the patched_dart2js_sdk and platform.dill only when |
| + // necessary, we track dependencies as follows: |
| + // - inputs like the sdk libraries and dart2js patch files are covered by the |
| + // extraDependencies argument. |
| + // - this script and its script dependencies are handled by writeDepsFile. |
| + // - the internal platform libraries that may affect how this script |
| + // runs are tracked at the BUILD.gn level (patched_dart2js_sdk depends on |
| + // patched_sdk). |
| + await writeDepsFile(Platform.script, |
| + Uri.base.resolveUri(new Uri.file("$outDir.d")), platformFinalLocation, |
| + packages: packages, |
| + // To track dependencies of this script, we need to use a platform.dill |
| + // file generated for the VM. The dependency on the patched_sdk at the |
| + // BUILD level guarantees that this file already exists. |
| + platform: Uri.base.resolveUri( |
| + new Uri.directory(outDir).resolve('../patched_sdk/platform.dill')), |
| + extraDependencies: deps, |
| + verbose: false, |
| + targetDart2js: false); |
| + |
| + await new File.fromUri(platform).rename(platformFinalLocation.toFilePath()); |
| +} |
| + |
| +_applyPatch( |
| + SdkLibrary library, String sdkLibIn, String patchIn, String sdkOut) { |
| + var libraryOut = path.join(sdkLibIn, library.path); |
| + var libraryIn = libraryOut; |
| + |
| + var libraryFile = getInputFile(libraryIn, canBeMissing: true); |
| + if (libraryFile != null) { |
| + var outPaths = <String>[libraryOut]; |
| + var libraryContents = libraryFile.readAsStringSync(); |
| + |
| + int inputModifyTime = libraryFile.lastModifiedSync().millisecondsSinceEpoch; |
| + var partFiles = <File>[]; |
| + for (var part in parseDirectives(libraryContents).directives) { |
| + if (part is PartDirective) { |
| + var partPath = part.uri.stringValue; |
| + outPaths.add(path.join(path.dirname(libraryOut), partPath)); |
| + |
| + var partFile = |
| + getInputFile(path.join(path.dirname(libraryIn), partPath)); |
| + partFiles.add(partFile); |
| + inputModifyTime = math.max(inputModifyTime, |
| + partFile.lastModifiedSync().millisecondsSinceEpoch); |
| + } |
| + } |
| + |
| + // See if we can find a patch file. |
| + var patchPath = path.join( |
| + patchIn, path.basenameWithoutExtension(libraryIn) + '_patch.dart'); |
| + |
| + var patchFile = getInputFile(patchPath, canBeMissing: true); |
| + if (patchFile != null) { |
| + inputModifyTime = math.max( |
| + inputModifyTime, patchFile.lastModifiedSync().millisecondsSinceEpoch); |
| + } |
| + |
| + // Compute output paths |
| + outPaths = outPaths |
| + .map((p) => path.join(sdkOut, path.relative(p, from: sdkLibIn))) |
| + .toList(); |
| + |
| + // Compare output modify time with input modify time. |
| + bool needsUpdate = false; |
| + for (var outPath in outPaths) { |
| + var outFile = new File(outPath); |
| + if (!outFile.existsSync() || |
| + outFile.lastModifiedSync().millisecondsSinceEpoch < inputModifyTime) { |
| + needsUpdate = true; |
| + break; |
| + } |
| + } |
| + |
| + if (needsUpdate) { |
| + var contents = <String>[libraryContents]; |
| + contents.addAll(partFiles.map((f) => f.readAsStringSync())); |
| + if (patchFile != null) { |
| + var patchContents = patchFile.readAsStringSync(); |
| + contents = _patchLibrary(patchFile.path, contents, patchContents); |
| + } |
| + |
| + for (var i = 0; i < outPaths.length; i++) { |
| + _writeSync(outPaths[i], contents[i]); |
| + } |
| + } |
| + } |
| +} |
| + |
| /// Writes a file, creating the directory if needed. |
| void _writeSync(String filePath, String contents) { |
| var outDir = new Directory(path.dirname(filePath)); |