• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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