Toolchain support for Android ARM64 targets (#14394)
diff --git a/packages/flutter_tools/gradle/flutter.gradle b/packages/flutter_tools/gradle/flutter.gradle index 55c0380..5c655f8 100644 --- a/packages/flutter_tools/gradle/flutter.gradle +++ b/packages/flutter_tools/gradle/flutter.gradle
@@ -115,9 +115,14 @@ } } else { Path baseEnginePath = Paths.get(flutterRoot.absolutePath, "bin", "cache", "artifacts", "engine") - debugFlutterJar = baseEnginePath.resolve("android-arm").resolve("flutter.jar").toFile() - profileFlutterJar = baseEnginePath.resolve("android-arm-profile").resolve("flutter.jar").toFile() - releaseFlutterJar = baseEnginePath.resolve("android-arm-release").resolve("flutter.jar").toFile() + String targetArch = 'arm' + if (project.hasProperty('target-platform') && + project.property('target-platform') == 'android-arm64') { + targetArch = 'arm64' + } + debugFlutterJar = baseEnginePath.resolve("android-${targetArch}").resolve("flutter.jar").toFile() + profileFlutterJar = baseEnginePath.resolve("android-${targetArch}-profile").resolve("flutter.jar").toFile() + releaseFlutterJar = baseEnginePath.resolve("android-${targetArch}-release").resolve("flutter.jar").toFile() if (!debugFlutterJar.isFile()) { project.exec { executable flutterExecutable.absolutePath @@ -273,6 +278,10 @@ if (project.hasProperty('prefer-shared-library')) { preferSharedLibraryValue = project.property('prefer-shared-library') } + String targetPlatformValue = null + if (project.hasProperty('target-platform')) { + targetPlatformValue = project.property('target-platform') + } project.android.applicationVariants.all { variant -> String flutterBuildMode = buildModeFor(variant.buildType) @@ -297,6 +306,7 @@ previewDart2 previewDart2Value strongMode strongModeValue preferSharedLibrary preferSharedLibraryValue + targetPlatform targetPlatformValue sourceDir project.file(project.flutter.source) intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}") } @@ -312,6 +322,7 @@ previewDart2 previewDart2Value strongMode strongModeValue preferSharedLibrary preferSharedLibraryValue + targetPlatform targetPlatformValue sourceDir project.file(project.flutter.source) intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}") extraFrontEndOptions extraFrontEndOptionsValue @@ -349,6 +360,8 @@ Boolean strongMode @Optional @Input Boolean preferSharedLibrary + @Optional @Input + String targetPlatform File sourceDir File intermediateDir @Optional @Input @@ -400,6 +413,9 @@ if (preferSharedLibrary) { args "--prefer-shared-library" } + if (targetPlatform != null) { + args "--target-platform", "${targetPlatform}" + } args "--${buildMode}" } }
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart index 9c9cac6..aef36790 100644 --- a/packages/flutter_tools/lib/src/android/android_device.dart +++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -126,6 +126,9 @@ if (_platform == null) { // http://developer.android.com/ndk/guides/abis.html (x86, armeabi-v7a, ...) switch (await _getProperty('ro.product.cpu.abi')) { + case 'arm64-v8a': + _platform = TargetPlatform.android_arm64; + break; case 'x86_64': _platform = TargetPlatform.android_x64; break; @@ -355,16 +358,23 @@ if (!await _checkForSupportedAdbVersion() || !await _checkForSupportedAndroidVersion()) return new LaunchResult.failed(); - if (await targetPlatform != TargetPlatform.android_arm && !debuggingOptions.buildInfo.isDebug) { + final TargetPlatform devicePlatform = await targetPlatform; + if (!(devicePlatform == TargetPlatform.android_arm || + devicePlatform == TargetPlatform.android_arm64) && + !debuggingOptions.buildInfo.isDebug) { printError('Profile and release builds are only supported on ARM targets.'); return new LaunchResult.failed(); } + BuildInfo buildInfo = debuggingOptions.buildInfo; + if (devicePlatform == TargetPlatform.android_arm64) + buildInfo = buildInfo.withTargetPlatform(TargetPlatform.android_arm64); + if (!prebuiltApplication) { printTrace('Building APK'); await buildApk( target: mainPath, - buildInfo: debuggingOptions.buildInfo, + buildInfo: buildInfo, ); // Package has been built, so we can get the updated application ID and // activity name from the .apk.
diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart index 8d8957a..e22bc8b 100644 --- a/packages/flutter_tools/lib/src/android/gradle.dart +++ b/packages/flutter_tools/lib/src/android/gradle.dart
@@ -301,6 +301,8 @@ if (buildInfo.preferSharedLibrary && androidSdk.ndkCompiler != null) { command.add('-Pprefer-shared-library=true'); } + if (buildInfo.targetPlatform == TargetPlatform.android_arm64) + command.add('-Ptarget-platform=android-arm64'); command.add(assembleTask); final int exitCode = await runCommandAndStreamOutput(
diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart index 14c0310..f734d7a 100644 --- a/packages/flutter_tools/lib/src/application_package.dart +++ b/packages/flutter_tools/lib/src/application_package.dart
@@ -259,6 +259,7 @@ }) async { switch (platform) { case TargetPlatform.android_arm: + case TargetPlatform.android_arm64: case TargetPlatform.android_x64: case TargetPlatform.android_x86: return applicationBinary == null @@ -287,6 +288,7 @@ Future<ApplicationPackage> getPackageForPlatform(TargetPlatform platform) async { switch (platform) { case TargetPlatform.android_arm: + case TargetPlatform.android_arm64: case TargetPlatform.android_x64: case TargetPlatform.android_x86: android ??= await AndroidApk.fromCurrentDirectory();
diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart index 3c4bfa3..bfe8963 100644 --- a/packages/flutter_tools/lib/src/artifacts.dart +++ b/packages/flutter_tools/lib/src/artifacts.dart
@@ -97,6 +97,7 @@ platform ??= _currentHostPlatform; switch (platform) { case TargetPlatform.android_arm: + case TargetPlatform.android_arm64: case TargetPlatform.android_x64: case TargetPlatform.android_x86: return _getAndroidArtifactPath(artifact, platform, mode); @@ -195,6 +196,7 @@ return fs.path.join(engineDir, platformName); case TargetPlatform.ios: case TargetPlatform.android_arm: + case TargetPlatform.android_arm64: case TargetPlatform.android_x64: case TargetPlatform.android_x86: assert(mode != null, 'Need to specify a build mode for platform $platform.');
diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart index 63bf145..8ed2b77 100644 --- a/packages/flutter_tools/lib/src/build_info.dart +++ b/packages/flutter_tools/lib/src/build_info.dart
@@ -15,7 +15,8 @@ this.strongMode, this.extraFrontEndOptions, this.extraGenSnapshotOptions, - this.preferSharedLibrary}); + this.preferSharedLibrary, + this.targetPlatform}); final BuildMode mode; /// Represents a custom Android product flavor or an Xcode scheme, null for @@ -41,6 +42,9 @@ // Whether to prefer AOT compiling to a *so file. final bool preferSharedLibrary; + /// Target platform for the build (e.g. android_arm versus android_arm64). + final TargetPlatform targetPlatform; + static const BuildInfo debug = const BuildInfo(BuildMode.debug, null); static const BuildInfo profile = const BuildInfo(BuildMode.profile, null); static const BuildInfo release = const BuildInfo(BuildMode.release, null); @@ -64,6 +68,15 @@ bool get supportsEmulator => isEmulatorBuildMode(mode); bool get supportsSimulator => isEmulatorBuildMode(mode); String get modeName => getModeName(mode); + + BuildInfo withTargetPlatform(TargetPlatform targetPlatform) => + new BuildInfo(mode, flavor, + previewDart2: previewDart2, + strongMode: strongMode, + extraFrontEndOptions: extraFrontEndOptions, + extraGenSnapshotOptions: extraGenSnapshotOptions, + preferSharedLibrary: preferSharedLibrary, + targetPlatform: targetPlatform); } /// The type of build - `debug`, `profile`, or `release`. @@ -114,6 +127,7 @@ enum TargetPlatform { android_arm, + android_arm64, android_x64, android_x86, ios, @@ -127,6 +141,8 @@ switch (platform) { case TargetPlatform.android_arm: return 'android-arm'; + case TargetPlatform.android_arm64: + return 'android-arm64'; case TargetPlatform.android_x64: return 'android-x64'; case TargetPlatform.android_x86: @@ -150,6 +166,8 @@ switch (platform) { case 'android-arm': return TargetPlatform.android_arm; + case 'android-arm64': + return TargetPlatform.android_arm64; case 'android-x64': return TargetPlatform.android_x64; case 'android-x86':
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart index ba657bf..62083ac 100644 --- a/packages/flutter_tools/lib/src/cache.dart +++ b/packages/flutter_tools/lib/src/cache.dart
@@ -394,6 +394,8 @@ <String>['linux-x64', 'dart-sdk-linux-x64.zip'], <String>['android-arm-profile/linux-x64', 'android-arm-profile/linux-x64.zip'], <String>['android-arm-release/linux-x64', 'android-arm-release/linux-x64.zip'], + <String>['android-arm64-profile/linux-x64', 'android-arm64-profile/linux-x64.zip'], + <String>['android-arm64-release/linux-x64', 'android-arm64-release/linux-x64.zip'], ]; List<List<String>> get _windowsBinaryDirs => <List<String>>[ @@ -409,6 +411,9 @@ <String>['android-arm', 'android-arm/artifacts.zip'], <String>['android-arm-profile', 'android-arm-profile/artifacts.zip'], <String>['android-arm-release', 'android-arm-release/artifacts.zip'], + <String>['android-arm64', 'android-arm64/artifacts.zip'], + <String>['android-arm64-profile', 'android-arm64-profile/artifacts.zip'], + <String>['android-arm64-release', 'android-arm64-release/artifacts.zip'], ]; List<List<String>> get _iosBinaryDirs => <List<String>>[
diff --git a/packages/flutter_tools/lib/src/commands/build_aot.dart b/packages/flutter_tools/lib/src/commands/build_aot.dart index 9233bbf..dd60d4d 100644 --- a/packages/flutter_tools/lib/src/commands/build_aot.dart +++ b/packages/flutter_tools/lib/src/commands/build_aot.dart
@@ -35,7 +35,7 @@ ..addOption('output-dir', defaultsTo: getAotBuildDirectory()) ..addOption('target-platform', defaultsTo: 'android-arm', - allowed: <String>['android-arm', 'ios'] + allowed: <String>['android-arm', 'android-arm64', 'ios'] ) ..addFlag('interpreter') ..addFlag('quiet', defaultsTo: false) @@ -159,7 +159,9 @@ return null; } - if (platform != TargetPlatform.android_arm && platform != TargetPlatform.ios) { + if (!(platform == TargetPlatform.android_arm || + platform == TargetPlatform.android_arm64 || + platform == TargetPlatform.ios)) { printError('${getNameForTargetPlatform(platform)} does not support AOT compilation.'); return null; } @@ -217,6 +219,7 @@ switch (platform) { case TargetPlatform.android_arm: + case TargetPlatform.android_arm64: case TargetPlatform.android_x64: case TargetPlatform.android_x86: if (compileToSharedLibrary) { @@ -287,6 +290,7 @@ switch (platform) { case TargetPlatform.android_arm: + case TargetPlatform.android_arm64: case TargetPlatform.android_x64: case TargetPlatform.android_x86: if (compileToSharedLibrary) { @@ -300,10 +304,12 @@ '--isolate_snapshot_instructions=$isolateSnapshotInstructions', ]); } - genSnapshotCmd.addAll(<String>[ - '--no-sim-use-hardfp', // Android uses the softfloat ABI. - '--no-use-integer-division', // Not supported by the Pixel in 32-bit mode. - ]); + if (platform == TargetPlatform.android_arm) { + genSnapshotCmd.addAll(<String>[ + '--no-sim-use-hardfp', // Android uses the softfloat ABI. + '--no-use-integer-division', // Not supported by the Pixel in 32-bit mode. + ]); + } break; case TargetPlatform.ios: if (interpreter) {
diff --git a/packages/flutter_tools/lib/src/commands/build_apk.dart b/packages/flutter_tools/lib/src/commands/build_apk.dart index 4636e48..67d8a18 100644 --- a/packages/flutter_tools/lib/src/commands/build_apk.dart +++ b/packages/flutter_tools/lib/src/commands/build_apk.dart
@@ -18,7 +18,10 @@ ..addFlag('preview-dart-2', negatable: false, hide: !verboseHelp) ..addFlag('strong', negatable: false, hide: !verboseHelp) ..addFlag('prefer-shared-library', negatable: false, - help: 'Whether to prefer compiling to a *.so file (android only).'); + help: 'Whether to prefer compiling to a *.so file (android only).') + ..addOption('target-platform', + defaultsTo: 'android-arm', + allowed: <String>['android-arm', 'android-arm64']); } @override
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index a7c520a..db64ccd 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -886,6 +886,7 @@ String getMissingPackageHintForPlatform(TargetPlatform platform) { switch (platform) { case TargetPlatform.android_arm: + case TargetPlatform.android_arm64: case TargetPlatform.android_x64: case TargetPlatform.android_x86: String manifest = 'android/AndroidManifest.xml';
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index f8962b3..3907599 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -185,7 +185,10 @@ : null, preferSharedLibrary: argParser.options.containsKey('prefer-shared-library') ? argResults['prefer-shared-library'] - : false); + : false, + targetPlatform: argParser.options.containsKey('target-platform') + ? getTargetPlatformForName(argResults['target-platform']) + : null); } void setupApplicationPackages() {