
There's very little code-sharing between the two, and what little there is is concentrated in the GenSnapshotClass and the fingerprint reading/writing utility methods.
228 lines
7.8 KiB
Dart
228 lines
7.8 KiB
Dart
// 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';
|
|
|
|
import 'artifacts.dart';
|
|
import 'asset.dart';
|
|
import 'base/build.dart';
|
|
import 'base/common.dart';
|
|
import 'base/file_system.dart';
|
|
import 'build_info.dart';
|
|
import 'compile.dart';
|
|
import 'dart/package_map.dart';
|
|
import 'devfs.dart';
|
|
import 'globals.dart';
|
|
|
|
const String defaultMainPath = 'lib/main.dart';
|
|
const String defaultAssetBasePath = '.';
|
|
const String defaultManifestPath = 'pubspec.yaml';
|
|
String get defaultSnapshotPath => fs.path.join(getBuildDirectory(), 'snapshot_blob.bin');
|
|
String get defaultDepfilePath => fs.path.join(getBuildDirectory(), 'snapshot_blob.bin.d');
|
|
String get defaultApplicationKernelPath => fs.path.join(getBuildDirectory(), 'app.dill');
|
|
const String defaultPrivateKeyPath = 'privatekey.der';
|
|
|
|
const String _kKernelKey = 'kernel_blob.bin';
|
|
const String _kSnapshotKey = 'snapshot_blob.bin';
|
|
const String _kDylibKey = 'libapp.so';
|
|
const String _kPlatformKernelKey = 'platform.dill';
|
|
|
|
Future<void> build({
|
|
String mainPath: defaultMainPath,
|
|
String manifestPath: defaultManifestPath,
|
|
String snapshotPath,
|
|
String applicationKernelFilePath,
|
|
String depfilePath,
|
|
String privateKeyPath: defaultPrivateKeyPath,
|
|
String assetDirPath,
|
|
String packagesPath,
|
|
bool previewDart2 : false,
|
|
bool precompiledSnapshot: false,
|
|
bool reportLicensedPackages: false,
|
|
bool trackWidgetCreation: false,
|
|
List<String> fileSystemRoots,
|
|
String fileSystemScheme,
|
|
}) async {
|
|
snapshotPath ??= defaultSnapshotPath;
|
|
depfilePath ??= defaultDepfilePath;
|
|
assetDirPath ??= getAssetBuildDirectory();
|
|
packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath);
|
|
applicationKernelFilePath ??= defaultApplicationKernelPath;
|
|
File snapshotFile;
|
|
|
|
if (!precompiledSnapshot && !previewDart2) {
|
|
ensureDirectoryExists(snapshotPath);
|
|
|
|
// In a precompiled snapshot, the instruction buffer contains script
|
|
// content equivalents
|
|
final int result = await new ScriptSnapshotter().build(
|
|
mainPath: mainPath,
|
|
snapshotPath: snapshotPath,
|
|
depfilePath: depfilePath,
|
|
packagesPath: packagesPath,
|
|
);
|
|
if (result != 0)
|
|
throwToolExit('Failed to run the Flutter compiler. Exit code: $result', exitCode: result);
|
|
|
|
snapshotFile = fs.file(snapshotPath);
|
|
}
|
|
|
|
DevFSContent kernelContent;
|
|
if (!precompiledSnapshot && previewDart2) {
|
|
final File fingerprintFile = fs.file('$depfilePath.fingerprint');
|
|
final List<String> inputPaths = <String>[
|
|
mainPath,
|
|
];
|
|
|
|
bool needBuild = true;
|
|
final List<File> fingerprintFiles = <File>[fingerprintFile, fs.file(depfilePath)]
|
|
..addAll(inputPaths.map(fs.file));
|
|
|
|
Future<Fingerprint> makeFingerprint() async {
|
|
final Set<String> compilerInputPaths = await readDepfile(depfilePath)
|
|
..add(mainPath);
|
|
final Map<String, String> properties = <String, String>{
|
|
'entryPoint': mainPath,
|
|
'trackWidgetCreation': trackWidgetCreation.toString(),
|
|
};
|
|
return new Fingerprint.fromBuildInputs(properties, compilerInputPaths);
|
|
}
|
|
|
|
if (fingerprintFiles.every((File file) => file.existsSync())) {
|
|
try {
|
|
final String json = await fingerprintFile.readAsString();
|
|
final Fingerprint oldFingerprint = new Fingerprint.fromJson(json);
|
|
if (oldFingerprint == await makeFingerprint()) {
|
|
needBuild = false;
|
|
printStatus('Skipping compilation. Fingerprint match.');
|
|
}
|
|
} catch (e) {
|
|
printTrace('Rebuilding kernel file due to fingerprint check error: $e');
|
|
}
|
|
}
|
|
|
|
String kernelBinaryFilename;
|
|
if (needBuild) {
|
|
ensureDirectoryExists(applicationKernelFilePath);
|
|
final CompilerOutput compilerOutput = await kernelCompiler.compile(
|
|
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
|
|
incrementalCompilerByteStorePath: fs.path.absolute(getIncrementalCompilerByteStoreDirectory()),
|
|
mainPath: fs.file(mainPath).absolute.path,
|
|
outputFilePath: applicationKernelFilePath,
|
|
depFilePath: depfilePath,
|
|
trackWidgetCreation: trackWidgetCreation,
|
|
fileSystemRoots: fileSystemRoots,
|
|
fileSystemScheme: fileSystemScheme,
|
|
packagesPath: packagesPath,
|
|
);
|
|
kernelBinaryFilename = compilerOutput?.outputFilename;
|
|
if (kernelBinaryFilename == null) {
|
|
throwToolExit('Compiler failed on $mainPath');
|
|
}
|
|
// Compute and record build fingerprint.
|
|
try {
|
|
final Fingerprint fingerprint = await makeFingerprint();
|
|
await fingerprintFile.writeAsString(fingerprint.toJson());
|
|
} catch (e, s) {
|
|
// Log exception and continue, this step is a performance improvement only.
|
|
printStatus('Error during compilation output fingerprinting: $e\n$s');
|
|
}
|
|
} else {
|
|
kernelBinaryFilename = applicationKernelFilePath;
|
|
}
|
|
kernelContent = new DevFSFileContent(fs.file(kernelBinaryFilename));
|
|
|
|
await fs.directory(getBuildDirectory()).childFile('frontend_server.d')
|
|
.writeAsString('frontend_server.d: ${artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk)}\n');
|
|
}
|
|
|
|
final AssetBundle assets = await buildAssets(
|
|
manifestPath: manifestPath,
|
|
assetDirPath: assetDirPath,
|
|
packagesPath: packagesPath,
|
|
reportLicensedPackages: reportLicensedPackages,
|
|
);
|
|
if (assets == null)
|
|
throwToolExit('Error building assets', exitCode: 1);
|
|
|
|
await assemble(
|
|
assetBundle: assets,
|
|
kernelContent: kernelContent,
|
|
snapshotFile: snapshotFile,
|
|
privateKeyPath: privateKeyPath,
|
|
assetDirPath: assetDirPath,
|
|
);
|
|
}
|
|
|
|
Future<AssetBundle> buildAssets({
|
|
String manifestPath,
|
|
String assetDirPath,
|
|
String packagesPath,
|
|
bool includeDefaultFonts: true,
|
|
bool reportLicensedPackages: false
|
|
}) async {
|
|
assetDirPath ??= getAssetBuildDirectory();
|
|
packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath);
|
|
|
|
// Build the asset bundle.
|
|
final AssetBundle assetBundle = AssetBundleFactory.instance.createBundle();
|
|
final int result = await assetBundle.build(
|
|
manifestPath: manifestPath,
|
|
assetDirPath: assetDirPath,
|
|
packagesPath: packagesPath,
|
|
includeDefaultFonts: includeDefaultFonts,
|
|
reportLicensedPackages: reportLicensedPackages
|
|
);
|
|
if (result != 0)
|
|
return null;
|
|
|
|
return assetBundle;
|
|
}
|
|
|
|
Future<void> assemble({
|
|
AssetBundle assetBundle,
|
|
DevFSContent kernelContent,
|
|
File snapshotFile,
|
|
File dylibFile,
|
|
String privateKeyPath: defaultPrivateKeyPath,
|
|
String assetDirPath,
|
|
}) async {
|
|
assetDirPath ??= getAssetBuildDirectory();
|
|
printTrace('Building bundle');
|
|
|
|
final Map<String, DevFSContent> assetEntries = new Map<String, DevFSContent>.from(assetBundle.entries);
|
|
|
|
if (kernelContent != null) {
|
|
final String platformKernelDill = artifacts.getArtifactPath(Artifact.platformKernelDill);
|
|
assetEntries[_kKernelKey] = kernelContent;
|
|
assetEntries[_kPlatformKernelKey] = new DevFSFileContent(fs.file(platformKernelDill));
|
|
}
|
|
if (snapshotFile != null)
|
|
assetEntries[_kSnapshotKey] = new DevFSFileContent(snapshotFile);
|
|
if (dylibFile != null)
|
|
assetEntries[_kDylibKey] = new DevFSFileContent(dylibFile);
|
|
|
|
printTrace('Writing asset files to $assetDirPath');
|
|
ensureDirectoryExists(assetDirPath);
|
|
|
|
await writeBundle(fs.directory(assetDirPath), assetEntries);
|
|
printTrace('Wrote $assetDirPath');
|
|
}
|
|
|
|
Future<void> writeBundle(
|
|
Directory bundleDir, Map<String, DevFSContent> assetEntries) async {
|
|
if (bundleDir.existsSync())
|
|
bundleDir.deleteSync(recursive: true);
|
|
bundleDir.createSync(recursive: true);
|
|
|
|
await Future.wait(
|
|
assetEntries.entries.map((MapEntry<String, DevFSContent> entry) async {
|
|
final File file = fs.file(fs.path.join(bundleDir.path, entry.key));
|
|
file.parent.createSync(recursive: true);
|
|
await file.writeAsBytes(await entry.value.contentsAsBytes());
|
|
}));
|
|
}
|
|
|
|
|