flx.dart 6.92 KB
Newer Older
1 2 3 4 5 6
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

7
import 'artifacts.dart';
8
import 'asset.dart';
9
import 'base/common.dart';
10
import 'base/file_system.dart';
11
import 'base/platform.dart';
12
import 'base/process.dart';
13
import 'build_info.dart';
14
import 'dart/package_map.dart';
15
import 'devfs.dart';
16
import 'globals.dart';
Devon Carew's avatar
Devon Carew committed
17
import 'zip.dart';
18 19

const String defaultMainPath = 'lib/main.dart';
20
const String defaultAssetBasePath = '.';
21
const String defaultManifestPath = 'pubspec.yaml';
22 23 24
String get defaultFlxOutputPath => fs.path.join(getBuildDirectory(), 'app.flx');
String get defaultSnapshotPath => fs.path.join(getBuildDirectory(), 'snapshot_blob.bin');
String get defaultDepfilePath => fs.path.join(getBuildDirectory(), 'snapshot_blob.bin.d');
25
String get defaultKernelPath => fs.path.join(getBuildDirectory(), 'kernel_blob.bin');
26 27
const String defaultPrivateKeyPath = 'privatekey.der';

28
const String _kKernelKey = 'kernel_blob.bin';
29 30
const String _kSnapshotKey = 'snapshot_blob.bin';

31 32 33
Future<int> createSnapshot({
  String mainPath,
  String snapshotPath,
34 35
  String depfilePath,
  String packages
36
}) {
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
  if (platform.isWindows) {
    return _creteScriptSnapshotWithGenSnapshot(
        mainPath: mainPath,
        snapshotPath: snapshotPath,
        depfilePath: depfilePath,
        packages: packages
    );
  }
  return _createScriptSnapshotWithSkySnapshot(
      mainPath: mainPath,
      snapshotPath: snapshotPath,
      depfilePath: depfilePath,
      packages: packages
  );
}

Future<int> _createScriptSnapshotWithSkySnapshot({
  String mainPath,
  String snapshotPath,
  String depfilePath,
  String packages
}) {
59 60
  assert(mainPath != null);
  assert(snapshotPath != null);
61
  assert(packages != null);
62
  final String snapshotterPath = artifacts.getArtifactPath(Artifact.skySnapshot);
63 64

  final List<String> args = <String>[
65 66
    snapshotterPath,
    '--packages=$packages',
67 68
    '--snapshot=$snapshotPath'
  ];
69
  if (depfilePath != null) {
70
    args.add('--depfile=$depfilePath');
71 72 73
    args.add('--build-output=$snapshotPath');
  }
  args.add(mainPath);
74 75 76
  return runCommandAndStreamOutput(args);
}

77 78 79 80 81 82 83 84 85
Future<int> _creteScriptSnapshotWithGenSnapshot({
  String mainPath,
  String snapshotPath,
  String depfilePath,
  String packages
}) {
  assert(mainPath != null);
  assert(snapshotPath != null);
  assert(packages != null);
86 87 88
  final String snapshotterPath = artifacts.getArtifactPath(Artifact.genSnapshot);
  final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData);
  final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData);
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104

  final List<String> args = <String>[
    snapshotterPath,
    '--snapshot_kind=script',
    '--vm_snapshot_data=$vmSnapshotData',
    '--isolate_snapshot_data=$isolateSnapshotData',
    '--packages=$packages',
    '--script_snapshot=$snapshotPath'
  ];
  if (depfilePath != null) {
    args.add('--dependencies=$depfilePath');
  }
  args.add(mainPath);
  return runCommandAndStreamOutput(args);
}

105
/// Build the flx in the build directory and return `localBundlePath` on success.
106 107
///
/// Return `null` on failure.
108
Future<String> buildFlx({
109
  String mainPath: defaultMainPath,
110
  DevFSContent kernelContent,
111
  bool precompiledSnapshot: false,
112
  bool includeRobotoFonts: true
113
}) async {
114
  await build(
115 116
    snapshotPath: defaultSnapshotPath,
    outputPath: defaultFlxOutputPath,
117
    mainPath: mainPath,
118
    kernelContent: kernelContent,
119
    precompiledSnapshot: precompiledSnapshot,
120
    includeRobotoFonts: includeRobotoFonts
121
  );
122
  return defaultFlxOutputPath;
123 124
}

125
Future<Null> build({
126 127
  String mainPath: defaultMainPath,
  String manifestPath: defaultManifestPath,
128 129 130
  String outputPath,
  String snapshotPath,
  String depfilePath,
131
  String privateKeyPath: defaultPrivateKeyPath,
132
  String workingDirPath,
133
  String packagesPath,
134 135
  String kernelPath,
  DevFSContent kernelContent,
136
  bool precompiledSnapshot: false,
137 138
  bool includeRobotoFonts: true,
  bool reportLicensedPackages: false
139
}) async {
140
  outputPath ??= defaultFlxOutputPath;
141
  kernelPath ??= defaultKernelPath;
142 143 144
  snapshotPath ??= defaultSnapshotPath;
  depfilePath ??= defaultDepfilePath;
  workingDirPath ??= getAssetBuildDirectory();
145
  packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath);
146
  File snapshotFile;
Devon Carew's avatar
Devon Carew committed
147

148 149 150 151
  File kernelFile;
  if (kernelContent != null) {
    // TODO(danrubel) in the future, call the VM to generate this file
    kernelFile = fs.file(kernelPath);
152
    final IOSink sink = kernelFile.openWrite();
153 154 155
    await sink.addStream(kernelContent.contentsAsStream());
    sink.close();
  }
156 157 158 159 160
  if (!precompiledSnapshot) {
    ensureDirectoryExists(snapshotPath);

    // In a precompiled snapshot, the instruction buffer contains script
    // content equivalents
161
    final int result = await createSnapshot(
162 163
      mainPath: mainPath,
      snapshotPath: snapshotPath,
164 165
      depfilePath: depfilePath,
      packages: packagesPath
166
    );
167 168
    if (result != 0)
      throwToolExit('Failed to run the Flutter compiler. Exit code: $result', exitCode: result);
169

170
    snapshotFile = fs.file(snapshotPath);
171
  }
172

173
  return assemble(
174
    manifestPath: manifestPath,
175
    kernelFile: kernelFile,
Ian Hickson's avatar
Ian Hickson committed
176 177 178 179
    snapshotFile: snapshotFile,
    outputPath: outputPath,
    privateKeyPath: privateKeyPath,
    workingDirPath: workingDirPath,
180
    packagesPath: packagesPath,
181 182
    includeRobotoFonts: includeRobotoFonts,
    reportLicensedPackages: reportLicensedPackages
183 184 185
  );
}

186
Future<Null> assemble({
187
  String manifestPath,
188
  File kernelFile,
Devon Carew's avatar
Devon Carew committed
189
  File snapshotFile,
190
  String outputPath,
191
  String privateKeyPath: defaultPrivateKeyPath,
192
  String workingDirPath,
193
  String packagesPath,
194
  bool includeDefaultFonts: true,
195 196
  bool includeRobotoFonts: true,
  bool reportLicensedPackages: false
197
}) async {
198 199
  outputPath ??= defaultFlxOutputPath;
  workingDirPath ??= getAssetBuildDirectory();
200
  packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath);
201 202
  printTrace('Building $outputPath');

203
  // Build the asset bundle.
204 205
  final AssetBundle assetBundle = new AssetBundle();
  final int result = await assetBundle.build(
206 207
    manifestPath: manifestPath,
    workingDirPath: workingDirPath,
208
    packagesPath: packagesPath,
209
    includeDefaultFonts: includeDefaultFonts,
210 211 212
    includeRobotoFonts: includeRobotoFonts,
    reportLicensedPackages: reportLicensedPackages
  );
213 214
  if (result != 0)
    throwToolExit('Error building $outputPath: $result', exitCode: result);
215

216
  final ZipBuilder zipBuilder = new ZipBuilder();
217

218 219
  // Add all entries from the asset bundle.
  zipBuilder.entries.addAll(assetBundle.entries);
220

221 222
  if (kernelFile != null)
    zipBuilder.entries[_kKernelKey] = new DevFSFileContent(kernelFile);
223
  if (snapshotFile != null)
224
    zipBuilder.entries[_kSnapshotKey] = new DevFSFileContent(snapshotFile);
Ian Hickson's avatar
Ian Hickson committed
225

226
  ensureDirectoryExists(outputPath);
227

228
  printTrace('Encoding zip file to $outputPath');
229
  await zipBuilder.createZip(fs.file(outputPath), fs.directory(workingDirPath));
230

Devon Carew's avatar
Devon Carew committed
231
  printTrace('Built $outputPath.');
232
}