Unverified Commit cdbb2385 authored by Chris Bracken's avatar Chris Bracken Committed by GitHub

Extract kernel compile from buildAotSnapshot (#17062)

Moves the kernel compile step to the beginning of the AOT build in a
separate method. This is pre-factoring for iOS universal builds where
the kernel build happens once, but we then snapshot twice: once for
armv7 and once for arm64.

This also writes dependencies to build/kernel_compile.d rather than
build/aot/snapshot.d, since that is immediately overwritten by
gen_snapshot.
parent 8860627b
......@@ -207,6 +207,52 @@ class Snapshotter {
return exitCode;
}
/// Compiles a Dart file to kernel.
///
/// Returns the output kernel file path, or null on failure.
Future<String> compileKernel({
@required TargetPlatform platform,
@required BuildMode buildMode,
@required String mainPath,
@required String outputPath,
List<String> extraFrontEndOptions: const <String>[],
}) async {
final Directory outputDir = fs.directory(outputPath);
outputDir.createSync(recursive: true);
printTrace('Compiling Dart to kernel: $mainPath');
final bool aot = !_isInterpreted(platform, buildMode);
final List<String> entryPointsJsonFiles = <String>[];
if (aot) {
entryPointsJsonFiles.addAll(<String>[
artifacts.getArtifactPath(Artifact.entryPointsJson, platform, buildMode),
artifacts.getArtifactPath(Artifact.entryPointsExtraJson, platform, buildMode),
]);
}
if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty)
printTrace('Extra front-end options: $extraFrontEndOptions');
final String depfilePath = fs.path.join(outputPath, 'kernel_compile.d');
final CompilerOutput compilerOutput = await kernelCompiler.compile(
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
mainPath: mainPath,
outputFilePath: fs.path.join(outputPath, 'app.dill'),
depFilePath: depfilePath,
extraFrontEndOptions: extraFrontEndOptions,
linkPlatformKernelIn: true,
aot: aot,
entryPointsJsonFiles: entryPointsJsonFiles,
trackWidgetCreation: false,
);
// Write path to frontend_server, since things need to be re-generated when that changes.
final String frontendPath = artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk);
await fs.directory(outputPath).childFile('frontend_server.d').writeAsString('frontend_server.d: $frontendPath\n');
return compilerOutput?.outputFilename;
}
/// Builds an architecture-specific ahead-of-time compiled snapshot of the specified script.
Future<int> buildAotSnapshot({
@required TargetPlatform platform,
......@@ -216,7 +262,6 @@ class Snapshotter {
@required String outputPath,
@required bool previewDart2,
@required bool preferSharedLibrary,
List<String> extraFrontEndOptions: const <String>[],
List<String> extraGenSnapshotOptions: const <String>[],
}) async {
if (!(platform == TargetPlatform.android_arm ||
......@@ -228,6 +273,7 @@ class Snapshotter {
final Directory outputDir = fs.directory(outputPath);
outputDir.createSync(recursive: true);
final String vmSnapshotData = fs.path.join(outputDir.path, 'vm_snapshot_data');
final String vmSnapshotInstructions = fs.path.join(outputDir.path, 'vm_snapshot_instr');
final String isolateSnapshotData = fs.path.join(outputDir.path, 'isolate_snapshot_data');
......@@ -250,15 +296,6 @@ class Snapshotter {
final String ioEntryPoints = artifacts.getArtifactPath(Artifact.dartIoEntriesTxt, platform, buildMode);
assert(ioEntryPoints != null);
final bool interpreter = platform == TargetPlatform.ios && buildMode == BuildMode.debug;
final List<String> entryPointsJsonFiles = <String>[];
if (previewDart2 && !interpreter) {
entryPointsJsonFiles.addAll(<String>[
artifacts.getArtifactPath(Artifact.entryPointsJson, platform, buildMode),
artifacts.getArtifactPath(Artifact.entryPointsExtraJson, platform, buildMode),
]);
}
final PackageMap packageMap = new PackageMap(packagesPath);
final String packageMapError = packageMap.checkValid();
if (packageMapError != null) {
......@@ -278,8 +315,6 @@ class Snapshotter {
mainPath,
];
inputPaths.addAll(entryPointsJsonFiles);
final Set<String> outputPaths = new Set<String>();
// These paths are used only on iOS.
......@@ -325,14 +360,12 @@ class Snapshotter {
'--dependencies=$depfilePath',
];
if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty)
printTrace('Extra front-end options: $extraFrontEndOptions');
if ((extraGenSnapshotOptions != null) && extraGenSnapshotOptions.isNotEmpty) {
printTrace('Extra gen-snapshot options: $extraGenSnapshotOptions');
genSnapshotArgs.addAll(extraGenSnapshotOptions);
}
final bool interpreter = _isInterpreted(platform, buildMode);
if (!interpreter) {
genSnapshotArgs.add('--embedder_entry_points_manifest=$vmEntryPoints');
genSnapshotArgs.add('--embedder_entry_points_manifest=$ioEntryPoints');
......@@ -347,7 +380,6 @@ class Snapshotter {
final String kIsolateSnapshotDataC = fs.path.join(outputDir.path, '$kIsolateSnapshotData.c');
final String kVmSnapshotDataO = fs.path.join(outputDir.path, '$kVmSnapshotData.o');
final String kIsolateSnapshotDataO = fs.path.join(outputDir.path, '$kIsolateSnapshotData.o');
final String kApplicationKernelPath = fs.path.join(getBuildDirectory(), 'app.dill');
switch (platform) {
case TargetPlatform.android_arm:
......@@ -408,36 +440,13 @@ class Snapshotter {
return 0;
}
String entrypointPath = mainPath;
if (previewDart2) {
final CompilerOutput compilerOutput = await kernelCompiler.compile(
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
mainPath: mainPath,
outputFilePath: kApplicationKernelPath,
depFilePath: depfilePath,
extraFrontEndOptions: extraFrontEndOptions,
linkPlatformKernelIn: true,
aot: !interpreter,
entryPointsJsonFiles: entryPointsJsonFiles,
trackWidgetCreation: false,
);
entrypointPath = compilerOutput?.outputFilename;
if (entrypointPath == null) {
printError('Compiler terminated unexpectedly.');
return -5;
}
// Write path to frontend_server, since things need to be re-generated when
// that changes.
await outputDir.childFile('frontend_server.d')
.writeAsString('frontend_server.d: ${artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk)}\n');
genSnapshotArgs.addAll(<String>[
'--reify-generic-functions',
'--strong',
]);
}
genSnapshotArgs.add(entrypointPath);
genSnapshotArgs.add(mainPath);
final int genSnapshotExitCode = await genSnapshot.run(
snapshotType: new SnapshotType(platform, buildMode),
......@@ -517,6 +526,11 @@ class Snapshotter {
return 0;
}
/// Returns true if the specified platform and build mode require running in interpreted mode.
bool _isInterpreted(TargetPlatform platform, BuildMode buildMode) {
return platform == TargetPlatform.ios && buildMode == BuildMode.debug;
}
String _getPackagePath(PackageMap packageMap, String package) {
return fs.path.dirname(fs.path.fromUri(packageMap.map[package]));
}
......
......@@ -54,29 +54,50 @@ class BuildAotCommand extends BuildSubCommand {
@override
Future<Null> runCommand() async {
await super.runCommand();
final String targetPlatform = argResults['target-platform'];
final TargetPlatform platform = getTargetPlatformForName(targetPlatform);
if (platform == null)
throwToolExit('Unknown platform: $targetPlatform');
final String typeName = artifacts.getEngineType(platform, getBuildMode());
final BuildMode buildMode = getBuildMode();
Status status;
if (!argResults['quiet']) {
final String typeName = artifacts.getEngineType(platform, buildMode);
status = logger.startProgress('Building AOT snapshot in ${getModeName(getBuildMode())} mode ($typeName)...',
expectSlowOperation: true);
}
final String outputPath = argResults['output-dir'] ?? getAotBuildDirectory();
try {
final bool previewDart2 = argResults['preview-dart-2'];
String mainPath = findMainDartFile(targetFile);
final Snapshotter snapshotter = new Snapshotter();
// Compile to kernel, if Dart 2.
if (previewDart2) {
mainPath = await snapshotter.compileKernel(
platform: platform,
buildMode: buildMode,
mainPath: mainPath,
outputPath: outputPath,
extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions],
);
if (mainPath == null) {
printError('Compiler terminated unexpectedly.');
return;
}
}
// Build AOT snapshot.
final int snapshotExitCode = await snapshotter.buildAotSnapshot(
platform: platform,
buildMode: getBuildMode(),
mainPath: findMainDartFile(targetFile),
buildMode: buildMode,
mainPath: mainPath,
packagesPath: PackageMap.globalPackagesPath,
outputPath: outputPath,
previewDart2: argResults['preview-dart-2'],
previewDart2: previewDart2,
preferSharedLibrary: argResults['prefer-shared-library'],
extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions],
extraGenSnapshotOptions: argResults[FlutterOptions.kExtraGenSnapshotOptions],
);
if (snapshotExitCode != 0) {
......
......@@ -9,7 +9,6 @@ import 'dart:convert' show json;
import 'package:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/compile.dart';
import 'package:flutter_tools/src/base/build.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
......@@ -70,29 +69,6 @@ class _FakeGenSnapshot implements GenSnapshot {
}
}
class _FakeKernelCompiler implements KernelCompiler {
CompilerOutput output;
@override
Future<CompilerOutput> compile({
String sdkRoot,
String mainPath,
String outputFilePath,
String depFilePath,
bool linkPlatformKernelIn: false,
bool aot: false,
List<String> entryPointsJsonFiles,
bool trackWidgetCreation: false,
List<String> extraFrontEndOptions,
String incrementalCompilerByteStorePath,
String packagesPath,
List<String> fileSystemRoots,
String fileSystemScheme,
}) async {
return output;
}
}
void main() {
group('SnapshotType', () {
test('throws, if build mode is null', () {
......@@ -606,7 +582,6 @@ void main() {
String skyEnginePath;
_FakeGenSnapshot genSnapshot;
_FakeKernelCompiler kernelCompiler;
MemoryFileSystem fs;
Snapshotter snapshotter;
MockArtifacts mockArtifacts;
......@@ -630,7 +605,6 @@ void main() {
fs.file(fs.path.join(skyEnginePath, 'sdk_ext', 'vmservice_io.dart')).createSync();
genSnapshot = new _FakeGenSnapshot();
kernelCompiler = new _FakeKernelCompiler();
snapshotter = new Snapshotter();
mockArtifacts = new MockArtifacts();
mockXcode = new MockXcode();
......@@ -648,18 +622,16 @@ void main() {
Artifacts: () => mockArtifacts,
FileSystem: () => fs,
GenSnapshot: () => genSnapshot,
KernelCompiler: () => kernelCompiler,
Xcode: () => mockXcode,
Xxd: () => mockXxd,
};
testUsingContext('builds iOS debug AOT snapshot', () async {
fs.file('main.dart').writeAsStringSync('void main() {}');
fs.file('main.dill').writeAsStringSync('binary magic');
final String outputPath = fs.path.join('build', 'foo');
fs.directory(outputPath).createSync(recursive: true);
kernelCompiler.output = const CompilerOutput('main.dill', 0);
genSnapshot.outputs = <String, String>{
fs.path.join(outputPath, 'vm_snapshot_data'): '',
fs.path.join(outputPath, 'vm_snapshot_instr'): '',
......@@ -672,7 +644,7 @@ void main() {
final int genSnapshotExitCode = await snapshotter.buildAotSnapshot(
platform: TargetPlatform.ios,
buildMode: BuildMode.debug,
mainPath: 'main.dart',
mainPath: 'main.dill',
packagesPath: '.packages',
outputPath: outputPath,
preferSharedLibrary: false,
......@@ -701,12 +673,11 @@ void main() {
}, overrides: contextOverrides);
testUsingContext('builds iOS profile AOT snapshot', () async {
fs.file('main.dart').writeAsStringSync('void main() {}');
fs.file('main.dill').writeAsStringSync('binary magic');
final String outputPath = fs.path.join('build', 'foo');
fs.directory(outputPath).createSync(recursive: true);
kernelCompiler.output = const CompilerOutput('main.dill', 0);
genSnapshot.outputs = <String, String>{
fs.path.join(outputPath, 'snapshot_assembly.S'): '',
fs.path.join(outputPath, 'snapshot.d'): '',
......@@ -715,7 +686,7 @@ void main() {
final int genSnapshotExitCode = await snapshotter.buildAotSnapshot(
platform: TargetPlatform.ios,
buildMode: BuildMode.profile,
mainPath: 'main.dart',
mainPath: 'main.dill',
packagesPath: '.packages',
outputPath: outputPath,
preferSharedLibrary: false,
......@@ -746,12 +717,11 @@ void main() {
}, overrides: contextOverrides);
testUsingContext('builds iOS release AOT snapshot', () async {
fs.file('main.dart').writeAsStringSync('void main() {}');
fs.file('main.dill').writeAsStringSync('binary magic');
final String outputPath = fs.path.join('build', 'foo');
fs.directory(outputPath).createSync(recursive: true);
kernelCompiler.output = const CompilerOutput('main.dill', 0);
genSnapshot.outputs = <String, String>{
fs.path.join(outputPath, 'snapshot_assembly.S'): '',
fs.path.join(outputPath, 'snapshot.d'): '',
......@@ -760,7 +730,7 @@ void main() {
final int genSnapshotExitCode = await snapshotter.buildAotSnapshot(
platform: TargetPlatform.ios,
buildMode: BuildMode.release,
mainPath: 'main.dart',
mainPath: 'main.dill',
packagesPath: '.packages',
outputPath: outputPath,
preferSharedLibrary: false,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment