Unverified Commit 79bc6caf authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

implement build aot with assemble for Android target platforms (#43282)

parent bdd93924
......@@ -778,9 +778,6 @@ abstract class BaseFlutterTask extends DefaultTask {
args "--target", targetPath
args "--output-dir", "${intermediateDir}"
args "--target-platform", "${targetPlatform}"
if (trackWidgetCreation) {
args "--track-widget-creation"
}
if (extraFrontEndOptions != null) {
args "--extra-front-end-options", "${extraFrontEndOptions}"
}
......
......@@ -337,3 +337,52 @@ class AotElfRelease extends AotElfBase {
KernelSnapshot(),
];
}
/// Copies the prebuilt flutter aot bundle.
// This is a one-off rule for implementing build aot in terms of assemble.
abstract class CopyFlutterAotBundle extends Target {
const CopyFlutterAotBundle();
@override
List<Source> get inputs => const <Source>[
Source.pattern('{BUILD_DIR}/app.so'),
];
@override
List<Source> get outputs => const <Source>[
Source.pattern('{OUTPUT_DIR}/app.so'),
];
@override
Future<void> build(Environment environment) async {
final File outputFile = environment.outputDir.childFile('app.so');
if (!outputFile.parent.existsSync()) {
outputFile.parent.createSync(recursive: true);
}
environment.buildDir.childFile('app.so').copySync(outputFile.path);
}
}
class ProfileCopyFlutterAotBundle extends CopyFlutterAotBundle {
const ProfileCopyFlutterAotBundle();
@override
String get name => 'profile_copy_aot_flutter_bundle';
@override
List<Target> get dependencies => const <Target>[
AotElfProfile(),
];
}
class ReleaseCopyFlutterAotBundle extends CopyFlutterAotBundle {
const ReleaseCopyFlutterAotBundle();
@override
String get name => 'release_copy_aot_flutter_bundle';
@override
List<Target> get dependencies => const <Target>[
AotElfRelease(),
];
}
......@@ -14,10 +14,13 @@ import '../base/logger.dart';
import '../base/process.dart';
import '../base/version.dart';
import '../build_info.dart';
import '../build_system/build_system.dart';
import '../build_system/targets/dart.dart';
import '../dart/package_map.dart';
import '../globals.dart';
import '../ios/plist_parser.dart';
import '../macos/xcode.dart';
import '../project.dart';
import '../resident_runner.dart';
import '../runner/flutter_command.dart';
import 'build.dart';
......@@ -74,12 +77,22 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
Future<FlutterCommandResult> runCommand() async {
final String targetPlatform = argResults['target-platform'];
final TargetPlatform platform = getTargetPlatformForName(targetPlatform);
final String outputPath = argResults['output-dir'] ?? getAotBuildDirectory();
final BuildMode buildMode = getBuildMode();
if (platform == null) {
throwToolExit('Unknown platform: $targetPlatform');
}
if (_canUseAssemble(platform)) {
await _buildWithAssemble(
targetFile: findMainDartFile(targetFile),
outputDir: outputPath,
targetPlatform: platform,
buildMode: buildMode,
);
return null;
}
final bool bitcode = argResults['bitcode'];
final BuildMode buildMode = getBuildMode();
if (bitcode) {
if (platform != TargetPlatform.ios) {
......@@ -96,7 +109,6 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
timeout: timeoutConfiguration.slowOperation,
);
}
final String outputPath = argResults['output-dir'] ?? getAotBuildDirectory();
final bool reportTimings = argResults['report-timings'];
try {
String mainPath = findMainDartFile(targetFile);
......@@ -200,6 +212,78 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
}
return null;
}
bool _canUseAssemble(TargetPlatform targetPlatform) {
if (argResults.wasParsed(FlutterOptions.kExtraFrontEndOptions) ||
argResults.wasParsed(FlutterOptions.kExtraGenSnapshotOptions)) {
return false;
}
switch (targetPlatform) {
case TargetPlatform.android_arm:
case TargetPlatform.android_arm64:
case TargetPlatform.android_x86:
case TargetPlatform.darwin_x64:
return true;
case TargetPlatform.android_x64:
case TargetPlatform.ios:
case TargetPlatform.linux_x64:
case TargetPlatform.windows_x64:
case TargetPlatform.fuchsia_arm64:
case TargetPlatform.fuchsia_x64:
case TargetPlatform.tester:
case TargetPlatform.web_javascript:
default:
return false;
}
}
Future<void> _buildWithAssemble({
TargetPlatform targetPlatform,
BuildMode buildMode,
String targetFile,
String outputDir,
}) async {
Status status;
if (!argResults['quiet']) {
final String typeName = artifacts.getEngineType(targetPlatform, buildMode);
status = logger.startProgress(
'Building AOT snapshot in ${getFriendlyModeName(getBuildMode())} mode ($typeName)...',
timeout: timeoutConfiguration.slowOperation,
);
}
final FlutterProject flutterProject = FlutterProject.current();
// Currently this only supports android, per the check above.
final Target target = buildMode == BuildMode.profile
? const ProfileCopyFlutterAotBundle()
: const ReleaseCopyFlutterAotBundle();
final BuildResult result = await buildSystem.build(target, Environment(
projectDir: flutterProject.directory,
outputDir: fs.directory(outputDir),
buildDir: flutterProject.directory
.childDirectory('.dart_tool')
.childDirectory('flutter_build'),
defines: <String, String>{
kBuildMode: getNameForBuildMode(buildMode),
kTargetPlatform: getNameForTargetPlatform(targetPlatform),
kTargetFile: targetFile,
}
));
status?.stop();
if (!result.success) {
for (ExceptionMeasurement measurement in result.exceptions.values) {
printError(measurement.exception.toString());
printError(measurement.stackTrace.toString());
}
throwToolExit('Failed to build aot.');
}
final String builtMessage = 'Built to $outputDir${fs.path.separator}.';
if (argResults['quiet']) {
printTrace(builtMessage);
} else {
printStatus(builtMessage);
}
}
}
Future<void> validateBitcode(BuildMode buildMode, TargetPlatform targetPlatform) async {
......
// Copyright 2019 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 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/dart.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/build.dart';
import 'package:mockito/mockito.dart';
import '../../src/common.dart';
import '../../src/mocks.dart';
import '../../src/testbed.dart';
void main() {
Testbed testbed;
setUpAll(() {
Cache.disableLocking();
});
tearDownAll(() {
Cache.enableLocking();
});
setUp(() {
testbed = Testbed(overrides: <Type, Generator>{
BuildSystem: () => MockBuildSystem(),
});
});
test('invokes assemble for android aot build.', () => testbed.run(() async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
fs.file(fs.path.join('lib', 'main.dart')).createSync(recursive: true);
when(buildSystem.build(any, any)).thenAnswer((Invocation invocation) async {
return BuildResult(success: true);
});
final BuildCommand command = BuildCommand();
applyMocksToCommand(command);
await createTestCommandRunner(command).run(<String>[
'build',
'aot',
'--target-platform=android-arm',
'--no-pub',
]);
final Environment environment = verify(buildSystem.build(any, captureAny)).captured.single;
expect(environment.defines, <String, String>{
kTargetFile: fs.path.absolute(fs.path.join('lib', 'main.dart')),
kBuildMode: 'release',
kTargetPlatform: 'android-arm',
});
}));
}
class MockBuildSystem extends Mock implements BuildSystem {}
......@@ -363,6 +363,14 @@ example:fiz/lib/''');
fs.directory('fiz').createSync();
expect(listDartSources(androidEnvironment), <File>[]);
}));
test('Profile/ReleaseCopyFlutterAotBundle copies .so to correct output directory', () => testbed.run(() async {
androidEnvironment.buildDir.createSync(recursive: true);
androidEnvironment.buildDir.childFile('app.so').createSync();
await const ProfileCopyFlutterAotBundle().build(androidEnvironment);
expect(androidEnvironment.outputDir.childFile('app.so').existsSync(), true);
}));
}
class MockProcessManager extends Mock implements ProcessManager {}
......
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