1// Copyright 2013 The Flutter Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5import 'dart:async'; 6import 'dart:io'; 7 8import 'package:args/args.dart'; 9import 'package:crypto/crypto.dart'; 10 11import 'package:vm/kernel_front_end.dart' 12 show createCompilerArgParser, runCompiler, successExitCode; 13 14final ArgParser _argParser = createCompilerArgParser() 15 ..addFlag('train', 16 help: 'Run through sample command line to produce snapshot', 17 negatable: false) 18 ..addOption('component-name', help: 'Name of the component') 19 ..addOption('data-dir', 20 help: 'Name of the subdirectory of //data for output files') 21 ..addOption('manifest', help: 'Path to output Fuchsia package manifest'); 22 23String _usage = ''' 24Usage: compiler [options] input.dart 25 26Options: 27${_argParser.usage} 28'''; 29 30Future<void> main(List<String> args) async { 31 ArgResults options; 32 33 try { 34 options = _argParser.parse(args); 35 36 if (options['train']) { 37 final Directory temp = 38 Directory.systemTemp.createTempSync('train_kernel_compiler'); 39 try { 40 options = _argParser.parse(<String>[ 41 '--manifest=flutter', 42 '--data-dir=${temp.absolute}', 43 ]); 44 45 await runCompiler(options, _usage); 46 return; 47 } finally { 48 temp.deleteSync(recursive: true); 49 } 50 } 51 52 if (!options.rest.isNotEmpty) { 53 throw Exception('Must specify input.dart'); 54 } 55 } on Exception catch (error) { 56 print('ERROR: $error\n'); 57 print(_usage); 58 exitCode = 1; 59 return; 60 } 61 62 final compilerExitCode = await runCompiler(options, _usage); 63 if (compilerExitCode != successExitCode) { 64 exitCode = compilerExitCode; 65 return; 66 } 67 68 final String output = options['output']; 69 final String dataDir = options.options.contains('component-name') 70 ? options['component-name'] 71 : options['data-dir']; 72 final String manifestFilename = options['manifest']; 73 74 if (manifestFilename != null) { 75 await createManifest(manifestFilename, dataDir, output); 76 } 77} 78 79Future createManifest( 80 String packageManifestFilename, String dataDir, String output) async { 81 List<String> packages = await File('$output-packages').readAsLines(); 82 83 // Make sure the 'main' package is the last (convention with package loader). 84 packages.remove('main'); 85 packages.add('main'); 86 87 final IOSink packageManifest = File(packageManifestFilename).openWrite(); 88 89 final String kernelListFilename = '$packageManifestFilename.dilplist'; 90 final IOSink kernelList = File(kernelListFilename).openWrite(); 91 for (String package in packages) { 92 final String filenameInPackage = '$package.dilp'; 93 final String filenameInBuild = '$output-$package.dilp'; 94 packageManifest 95 .write('data/$dataDir/$filenameInPackage=$filenameInBuild\n'); 96 kernelList.write('$filenameInPackage\n'); 97 } 98 await kernelList.close(); 99 100 final String frameworkVersionFilename = 101 '$packageManifestFilename.frameworkversion'; 102 final IOSink frameworkVersion = File(frameworkVersionFilename).openWrite(); 103 for (String package in [ 104 'collection', 105 'flutter', 106 'meta', 107 'typed_data', 108 'vector_math' 109 ]) { 110 Digest digest; 111 if (packages.contains(package)) { 112 final filenameInBuild = '$output-$package.dilp'; 113 final bytes = await File(filenameInBuild).readAsBytes(); 114 digest = sha256.convert(bytes); 115 } 116 frameworkVersion.write('$package=$digest\n'); 117 } 118 await frameworkVersion.close(); 119 120 packageManifest.write('data/$dataDir/app.dilplist=$kernelListFilename\n'); 121 packageManifest 122 .write('data/$dataDir/app.frameworkversion=$frameworkVersionFilename\n'); 123 await packageManifest.close(); 124} 125