mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

* Renamed --save-compilation-trace to flutter run --train. * Renamed --precompile=<file> to --compilation-trace-file=<file>. * In dynamic mode, made JIT snapshot the default, instead of kernel file.
238 lines
8.7 KiB
Dart
238 lines
8.7 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 'package:meta/meta.dart';
|
|
|
|
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 defaultDepfilePath => fs.path.join(getBuildDirectory(), 'snapshot_blob.bin.d');
|
|
|
|
String getDefaultApplicationKernelPath({@required bool trackWidgetCreation}) {
|
|
return getKernelPathForTransformerOptions(
|
|
fs.path.join(getBuildDirectory(), 'app.dill'),
|
|
trackWidgetCreation: trackWidgetCreation,
|
|
);
|
|
}
|
|
|
|
String getKernelPathForTransformerOptions(
|
|
String path, {
|
|
@required bool trackWidgetCreation,
|
|
}) {
|
|
if (trackWidgetCreation) {
|
|
path += '.track.dill';
|
|
}
|
|
return path;
|
|
}
|
|
|
|
const String defaultPrivateKeyPath = 'privatekey.der';
|
|
|
|
const String _kKernelKey = 'kernel_blob.bin';
|
|
const String _kVMSnapshotData = 'vm_snapshot_data';
|
|
const String _kIsolateSnapshotData = 'isolate_snapshot_data';
|
|
const String _kIsolateSnapshotInstr = 'isolate_snapshot_instr';
|
|
|
|
Future<void> build({
|
|
TargetPlatform platform,
|
|
BuildMode buildMode,
|
|
String mainPath = defaultMainPath,
|
|
String manifestPath = defaultManifestPath,
|
|
String applicationKernelFilePath,
|
|
String depfilePath,
|
|
String privateKeyPath = defaultPrivateKeyPath,
|
|
String assetDirPath,
|
|
String packagesPath,
|
|
bool precompiledSnapshot = false,
|
|
bool reportLicensedPackages = false,
|
|
bool trackWidgetCreation = false,
|
|
String compilationTraceFilePath,
|
|
bool createPatch = false,
|
|
int buildNumber,
|
|
String baselineDir,
|
|
List<String> extraFrontEndOptions = const <String>[],
|
|
List<String> extraGenSnapshotOptions = const <String>[],
|
|
List<String> fileSystemRoots,
|
|
String fileSystemScheme,
|
|
}) async {
|
|
depfilePath ??= defaultDepfilePath;
|
|
assetDirPath ??= getAssetBuildDirectory();
|
|
packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath);
|
|
applicationKernelFilePath ??= getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation);
|
|
|
|
if (compilationTraceFilePath != null) {
|
|
if (buildMode != BuildMode.dynamicProfile && buildMode != BuildMode.dynamicRelease) {
|
|
// Silently ignore JIT snapshotting for those builds that don't support it.
|
|
compilationTraceFilePath = null;
|
|
|
|
} else if (compilationTraceFilePath.isEmpty) {
|
|
// Disable JIT snapshotting if flag is empty.
|
|
printStatus('JIT snapshot will be disabled for this build...');
|
|
compilationTraceFilePath = null;
|
|
|
|
} else if (!fs.file(compilationTraceFilePath).existsSync()) {
|
|
// Be forgiving if compilation trace file is missing.
|
|
printError('Warning: Ignoring missing compiler training file $compilationTraceFilePath...');
|
|
printStatus('JIT snapshot will not use compiler training...');
|
|
final File tmp = fs.systemTempDirectory.childFile('flutterEmptyCompilationTrace.txt');
|
|
compilationTraceFilePath = (tmp..createSync(recursive: true)).path;
|
|
|
|
} else {
|
|
printStatus('JIT snapshot will use compiler training file $compilationTraceFilePath...');
|
|
}
|
|
}
|
|
|
|
DevFSContent kernelContent;
|
|
if (!precompiledSnapshot) {
|
|
if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty)
|
|
printTrace('Extra front-end options: $extraFrontEndOptions');
|
|
ensureDirectoryExists(applicationKernelFilePath);
|
|
final CompilerOutput compilerOutput = await kernelCompiler.compile(
|
|
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
|
|
incrementalCompilerByteStorePath: compilationTraceFilePath != null ? null :
|
|
fs.path.absolute(getIncrementalCompilerByteStoreDirectory()),
|
|
mainPath: fs.file(mainPath).absolute.path,
|
|
outputFilePath: applicationKernelFilePath,
|
|
depFilePath: depfilePath,
|
|
trackWidgetCreation: trackWidgetCreation,
|
|
extraFrontEndOptions: extraFrontEndOptions,
|
|
fileSystemRoots: fileSystemRoots,
|
|
fileSystemScheme: fileSystemScheme,
|
|
packagesPath: packagesPath,
|
|
linkPlatformKernelIn: compilationTraceFilePath != null,
|
|
);
|
|
if (compilerOutput?.outputFilename == null) {
|
|
throwToolExit('Compiler failed on $mainPath');
|
|
}
|
|
kernelContent = DevFSFileContent(fs.file(compilerOutput.outputFilename));
|
|
|
|
await fs.directory(getBuildDirectory()).childFile('frontend_server.d')
|
|
.writeAsString('frontend_server.d: ${artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk)}\n');
|
|
|
|
if (compilationTraceFilePath != null) {
|
|
final JITSnapshotter snapshotter = JITSnapshotter();
|
|
final int snapshotExitCode = await snapshotter.build(
|
|
platform: platform,
|
|
buildMode: buildMode,
|
|
mainPath: applicationKernelFilePath,
|
|
outputPath: getBuildDirectory(),
|
|
packagesPath: packagesPath,
|
|
compilationTraceFilePath: compilationTraceFilePath,
|
|
extraGenSnapshotOptions: extraGenSnapshotOptions,
|
|
createPatch: createPatch,
|
|
buildNumber: buildNumber,
|
|
baselineDir: baselineDir,
|
|
);
|
|
if (snapshotExitCode != 0) {
|
|
throwToolExit('Snapshotting exited with non-zero exit code: $snapshotExitCode');
|
|
}
|
|
}
|
|
}
|
|
|
|
final AssetBundle assets = await buildAssets(
|
|
manifestPath: manifestPath,
|
|
assetDirPath: assetDirPath,
|
|
packagesPath: packagesPath,
|
|
reportLicensedPackages: reportLicensedPackages,
|
|
);
|
|
if (assets == null)
|
|
throwToolExit('Error building assets', exitCode: 1);
|
|
|
|
await assemble(
|
|
buildMode: buildMode,
|
|
assetBundle: assets,
|
|
kernelContent: kernelContent,
|
|
privateKeyPath: privateKeyPath,
|
|
assetDirPath: assetDirPath,
|
|
compilationTraceFilePath: compilationTraceFilePath,
|
|
);
|
|
}
|
|
|
|
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({
|
|
BuildMode buildMode,
|
|
AssetBundle assetBundle,
|
|
DevFSContent kernelContent,
|
|
String privateKeyPath = defaultPrivateKeyPath,
|
|
String assetDirPath,
|
|
String compilationTraceFilePath,
|
|
}) async {
|
|
assetDirPath ??= getAssetBuildDirectory();
|
|
printTrace('Building bundle');
|
|
|
|
final Map<String, DevFSContent> assetEntries = Map<String, DevFSContent>.from(assetBundle.entries);
|
|
if (kernelContent != null) {
|
|
if (compilationTraceFilePath != null) {
|
|
final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData);
|
|
final String isolateSnapshotData = fs.path.join(getBuildDirectory(), _kIsolateSnapshotData);
|
|
final String isolateSnapshotInstr = fs.path.join(getBuildDirectory(), _kIsolateSnapshotInstr);
|
|
assetEntries[_kVMSnapshotData] = DevFSFileContent(fs.file(vmSnapshotData));
|
|
assetEntries[_kIsolateSnapshotData] = DevFSFileContent(fs.file(isolateSnapshotData));
|
|
assetEntries[_kIsolateSnapshotInstr] = DevFSFileContent(fs.file(isolateSnapshotInstr));
|
|
} else {
|
|
final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData, null, buildMode);
|
|
final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData, null, buildMode);
|
|
assetEntries[_kKernelKey] = kernelContent;
|
|
assetEntries[_kVMSnapshotData] = DevFSFileContent(fs.file(vmSnapshotData));
|
|
assetEntries[_kIsolateSnapshotData] = DevFSFileContent(fs.file(isolateSnapshotData));
|
|
}
|
|
}
|
|
|
|
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<void>(
|
|
assetEntries.entries.map<Future<void>>((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());
|
|
}));
|
|
}
|