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 { ...@@ -207,6 +207,52 @@ class Snapshotter {
return exitCode; 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. /// Builds an architecture-specific ahead-of-time compiled snapshot of the specified script.
Future<int> buildAotSnapshot({ Future<int> buildAotSnapshot({
@required TargetPlatform platform, @required TargetPlatform platform,
...@@ -216,7 +262,6 @@ class Snapshotter { ...@@ -216,7 +262,6 @@ class Snapshotter {
@required String outputPath, @required String outputPath,
@required bool previewDart2, @required bool previewDart2,
@required bool preferSharedLibrary, @required bool preferSharedLibrary,
List<String> extraFrontEndOptions: const <String>[],
List<String> extraGenSnapshotOptions: const <String>[], List<String> extraGenSnapshotOptions: const <String>[],
}) async { }) async {
if (!(platform == TargetPlatform.android_arm || if (!(platform == TargetPlatform.android_arm ||
...@@ -228,6 +273,7 @@ class Snapshotter { ...@@ -228,6 +273,7 @@ class Snapshotter {
final Directory outputDir = fs.directory(outputPath); final Directory outputDir = fs.directory(outputPath);
outputDir.createSync(recursive: true); outputDir.createSync(recursive: true);
final String vmSnapshotData = fs.path.join(outputDir.path, 'vm_snapshot_data'); final String vmSnapshotData = fs.path.join(outputDir.path, 'vm_snapshot_data');
final String vmSnapshotInstructions = fs.path.join(outputDir.path, 'vm_snapshot_instr'); final String vmSnapshotInstructions = fs.path.join(outputDir.path, 'vm_snapshot_instr');
final String isolateSnapshotData = fs.path.join(outputDir.path, 'isolate_snapshot_data'); final String isolateSnapshotData = fs.path.join(outputDir.path, 'isolate_snapshot_data');
...@@ -250,15 +296,6 @@ class Snapshotter { ...@@ -250,15 +296,6 @@ class Snapshotter {
final String ioEntryPoints = artifacts.getArtifactPath(Artifact.dartIoEntriesTxt, platform, buildMode); final String ioEntryPoints = artifacts.getArtifactPath(Artifact.dartIoEntriesTxt, platform, buildMode);
assert(ioEntryPoints != null); 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 PackageMap packageMap = new PackageMap(packagesPath);
final String packageMapError = packageMap.checkValid(); final String packageMapError = packageMap.checkValid();
if (packageMapError != null) { if (packageMapError != null) {
...@@ -278,8 +315,6 @@ class Snapshotter { ...@@ -278,8 +315,6 @@ class Snapshotter {
mainPath, mainPath,
]; ];
inputPaths.addAll(entryPointsJsonFiles);
final Set<String> outputPaths = new Set<String>(); final Set<String> outputPaths = new Set<String>();
// These paths are used only on iOS. // These paths are used only on iOS.
...@@ -325,14 +360,12 @@ class Snapshotter { ...@@ -325,14 +360,12 @@ class Snapshotter {
'--dependencies=$depfilePath', '--dependencies=$depfilePath',
]; ];
if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty)
printTrace('Extra front-end options: $extraFrontEndOptions');
if ((extraGenSnapshotOptions != null) && extraGenSnapshotOptions.isNotEmpty) { if ((extraGenSnapshotOptions != null) && extraGenSnapshotOptions.isNotEmpty) {
printTrace('Extra gen-snapshot options: $extraGenSnapshotOptions'); printTrace('Extra gen-snapshot options: $extraGenSnapshotOptions');
genSnapshotArgs.addAll(extraGenSnapshotOptions); genSnapshotArgs.addAll(extraGenSnapshotOptions);
} }
final bool interpreter = _isInterpreted(platform, buildMode);
if (!interpreter) { if (!interpreter) {
genSnapshotArgs.add('--embedder_entry_points_manifest=$vmEntryPoints'); genSnapshotArgs.add('--embedder_entry_points_manifest=$vmEntryPoints');
genSnapshotArgs.add('--embedder_entry_points_manifest=$ioEntryPoints'); genSnapshotArgs.add('--embedder_entry_points_manifest=$ioEntryPoints');
...@@ -347,7 +380,6 @@ class Snapshotter { ...@@ -347,7 +380,6 @@ class Snapshotter {
final String kIsolateSnapshotDataC = fs.path.join(outputDir.path, '$kIsolateSnapshotData.c'); final String kIsolateSnapshotDataC = fs.path.join(outputDir.path, '$kIsolateSnapshotData.c');
final String kVmSnapshotDataO = fs.path.join(outputDir.path, '$kVmSnapshotData.o'); final String kVmSnapshotDataO = fs.path.join(outputDir.path, '$kVmSnapshotData.o');
final String kIsolateSnapshotDataO = fs.path.join(outputDir.path, '$kIsolateSnapshotData.o'); final String kIsolateSnapshotDataO = fs.path.join(outputDir.path, '$kIsolateSnapshotData.o');
final String kApplicationKernelPath = fs.path.join(getBuildDirectory(), 'app.dill');
switch (platform) { switch (platform) {
case TargetPlatform.android_arm: case TargetPlatform.android_arm:
...@@ -408,36 +440,13 @@ class Snapshotter { ...@@ -408,36 +440,13 @@ class Snapshotter {
return 0; return 0;
} }
String entrypointPath = mainPath;
if (previewDart2) { 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>[ genSnapshotArgs.addAll(<String>[
'--reify-generic-functions', '--reify-generic-functions',
'--strong', '--strong',
]); ]);
} }
genSnapshotArgs.add(mainPath);
genSnapshotArgs.add(entrypointPath);
final int genSnapshotExitCode = await genSnapshot.run( final int genSnapshotExitCode = await genSnapshot.run(
snapshotType: new SnapshotType(platform, buildMode), snapshotType: new SnapshotType(platform, buildMode),
...@@ -517,6 +526,11 @@ class Snapshotter { ...@@ -517,6 +526,11 @@ class Snapshotter {
return 0; 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) { String _getPackagePath(PackageMap packageMap, String package) {
return fs.path.dirname(fs.path.fromUri(packageMap.map[package])); return fs.path.dirname(fs.path.fromUri(packageMap.map[package]));
} }
......
...@@ -54,29 +54,50 @@ class BuildAotCommand extends BuildSubCommand { ...@@ -54,29 +54,50 @@ class BuildAotCommand extends BuildSubCommand {
@override @override
Future<Null> runCommand() async { Future<Null> runCommand() async {
await super.runCommand(); await super.runCommand();
final String targetPlatform = argResults['target-platform']; final String targetPlatform = argResults['target-platform'];
final TargetPlatform platform = getTargetPlatformForName(targetPlatform); final TargetPlatform platform = getTargetPlatformForName(targetPlatform);
if (platform == null) if (platform == null)
throwToolExit('Unknown platform: $targetPlatform'); throwToolExit('Unknown platform: $targetPlatform');
final String typeName = artifacts.getEngineType(platform, getBuildMode()); final BuildMode buildMode = getBuildMode();
Status status; Status status;
if (!argResults['quiet']) { if (!argResults['quiet']) {
final String typeName = artifacts.getEngineType(platform, buildMode);
status = logger.startProgress('Building AOT snapshot in ${getModeName(getBuildMode())} mode ($typeName)...', status = logger.startProgress('Building AOT snapshot in ${getModeName(getBuildMode())} mode ($typeName)...',
expectSlowOperation: true); expectSlowOperation: true);
} }
final String outputPath = argResults['output-dir'] ?? getAotBuildDirectory(); final String outputPath = argResults['output-dir'] ?? getAotBuildDirectory();
try { try {
final bool previewDart2 = argResults['preview-dart-2'];
String mainPath = findMainDartFile(targetFile);
final Snapshotter snapshotter = new Snapshotter(); 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( final int snapshotExitCode = await snapshotter.buildAotSnapshot(
platform: platform, platform: platform,
buildMode: getBuildMode(), buildMode: buildMode,
mainPath: findMainDartFile(targetFile), mainPath: mainPath,
packagesPath: PackageMap.globalPackagesPath, packagesPath: PackageMap.globalPackagesPath,
outputPath: outputPath, outputPath: outputPath,
previewDart2: argResults['preview-dart-2'], previewDart2: previewDart2,
preferSharedLibrary: argResults['prefer-shared-library'], preferSharedLibrary: argResults['prefer-shared-library'],
extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions],
extraGenSnapshotOptions: argResults[FlutterOptions.kExtraGenSnapshotOptions], extraGenSnapshotOptions: argResults[FlutterOptions.kExtraGenSnapshotOptions],
); );
if (snapshotExitCode != 0) { if (snapshotExitCode != 0) {
......
...@@ -9,7 +9,6 @@ import 'dart:convert' show json; ...@@ -9,7 +9,6 @@ import 'dart:convert' show json;
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/build_info.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/build.dart';
import 'package:flutter_tools/src/base/context.dart'; import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
...@@ -70,29 +69,6 @@ class _FakeGenSnapshot implements GenSnapshot { ...@@ -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() { void main() {
group('SnapshotType', () { group('SnapshotType', () {
test('throws, if build mode is null', () { test('throws, if build mode is null', () {
...@@ -606,7 +582,6 @@ void main() { ...@@ -606,7 +582,6 @@ void main() {
String skyEnginePath; String skyEnginePath;
_FakeGenSnapshot genSnapshot; _FakeGenSnapshot genSnapshot;
_FakeKernelCompiler kernelCompiler;
MemoryFileSystem fs; MemoryFileSystem fs;
Snapshotter snapshotter; Snapshotter snapshotter;
MockArtifacts mockArtifacts; MockArtifacts mockArtifacts;
...@@ -630,7 +605,6 @@ void main() { ...@@ -630,7 +605,6 @@ void main() {
fs.file(fs.path.join(skyEnginePath, 'sdk_ext', 'vmservice_io.dart')).createSync(); fs.file(fs.path.join(skyEnginePath, 'sdk_ext', 'vmservice_io.dart')).createSync();
genSnapshot = new _FakeGenSnapshot(); genSnapshot = new _FakeGenSnapshot();
kernelCompiler = new _FakeKernelCompiler();
snapshotter = new Snapshotter(); snapshotter = new Snapshotter();
mockArtifacts = new MockArtifacts(); mockArtifacts = new MockArtifacts();
mockXcode = new MockXcode(); mockXcode = new MockXcode();
...@@ -648,18 +622,16 @@ void main() { ...@@ -648,18 +622,16 @@ void main() {
Artifacts: () => mockArtifacts, Artifacts: () => mockArtifacts,
FileSystem: () => fs, FileSystem: () => fs,
GenSnapshot: () => genSnapshot, GenSnapshot: () => genSnapshot,
KernelCompiler: () => kernelCompiler,
Xcode: () => mockXcode, Xcode: () => mockXcode,
Xxd: () => mockXxd, Xxd: () => mockXxd,
}; };
testUsingContext('builds iOS debug AOT snapshot', () async { 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'); final String outputPath = fs.path.join('build', 'foo');
fs.directory(outputPath).createSync(recursive: true); fs.directory(outputPath).createSync(recursive: true);
kernelCompiler.output = const CompilerOutput('main.dill', 0);
genSnapshot.outputs = <String, String>{ genSnapshot.outputs = <String, String>{
fs.path.join(outputPath, 'vm_snapshot_data'): '', fs.path.join(outputPath, 'vm_snapshot_data'): '',
fs.path.join(outputPath, 'vm_snapshot_instr'): '', fs.path.join(outputPath, 'vm_snapshot_instr'): '',
...@@ -672,7 +644,7 @@ void main() { ...@@ -672,7 +644,7 @@ void main() {
final int genSnapshotExitCode = await snapshotter.buildAotSnapshot( final int genSnapshotExitCode = await snapshotter.buildAotSnapshot(
platform: TargetPlatform.ios, platform: TargetPlatform.ios,
buildMode: BuildMode.debug, buildMode: BuildMode.debug,
mainPath: 'main.dart', mainPath: 'main.dill',
packagesPath: '.packages', packagesPath: '.packages',
outputPath: outputPath, outputPath: outputPath,
preferSharedLibrary: false, preferSharedLibrary: false,
...@@ -701,12 +673,11 @@ void main() { ...@@ -701,12 +673,11 @@ void main() {
}, overrides: contextOverrides); }, overrides: contextOverrides);
testUsingContext('builds iOS profile AOT snapshot', () async { 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'); final String outputPath = fs.path.join('build', 'foo');
fs.directory(outputPath).createSync(recursive: true); fs.directory(outputPath).createSync(recursive: true);
kernelCompiler.output = const CompilerOutput('main.dill', 0);
genSnapshot.outputs = <String, String>{ genSnapshot.outputs = <String, String>{
fs.path.join(outputPath, 'snapshot_assembly.S'): '', fs.path.join(outputPath, 'snapshot_assembly.S'): '',
fs.path.join(outputPath, 'snapshot.d'): '', fs.path.join(outputPath, 'snapshot.d'): '',
...@@ -715,7 +686,7 @@ void main() { ...@@ -715,7 +686,7 @@ void main() {
final int genSnapshotExitCode = await snapshotter.buildAotSnapshot( final int genSnapshotExitCode = await snapshotter.buildAotSnapshot(
platform: TargetPlatform.ios, platform: TargetPlatform.ios,
buildMode: BuildMode.profile, buildMode: BuildMode.profile,
mainPath: 'main.dart', mainPath: 'main.dill',
packagesPath: '.packages', packagesPath: '.packages',
outputPath: outputPath, outputPath: outputPath,
preferSharedLibrary: false, preferSharedLibrary: false,
...@@ -746,12 +717,11 @@ void main() { ...@@ -746,12 +717,11 @@ void main() {
}, overrides: contextOverrides); }, overrides: contextOverrides);
testUsingContext('builds iOS release AOT snapshot', () async { 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'); final String outputPath = fs.path.join('build', 'foo');
fs.directory(outputPath).createSync(recursive: true); fs.directory(outputPath).createSync(recursive: true);
kernelCompiler.output = const CompilerOutput('main.dill', 0);
genSnapshot.outputs = <String, String>{ genSnapshot.outputs = <String, String>{
fs.path.join(outputPath, 'snapshot_assembly.S'): '', fs.path.join(outputPath, 'snapshot_assembly.S'): '',
fs.path.join(outputPath, 'snapshot.d'): '', fs.path.join(outputPath, 'snapshot.d'): '',
...@@ -760,7 +730,7 @@ void main() { ...@@ -760,7 +730,7 @@ void main() {
final int genSnapshotExitCode = await snapshotter.buildAotSnapshot( final int genSnapshotExitCode = await snapshotter.buildAotSnapshot(
platform: TargetPlatform.ios, platform: TargetPlatform.ios,
buildMode: BuildMode.release, buildMode: BuildMode.release,
mainPath: 'main.dart', mainPath: 'main.dill',
packagesPath: '.packages', packagesPath: '.packages',
outputPath: outputPath, outputPath: outputPath,
preferSharedLibrary: false, 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