Unverified Commit 90f38907 authored by Emmanuel Garcia's avatar Emmanuel Garcia Committed by GitHub

Support ARM 32 and 64 bits in app bundles

parent c2a93bd5
...@@ -63,6 +63,51 @@ Future<void> main() async { ...@@ -63,6 +63,51 @@ Future<void> main() async {
await runProjectTest((FlutterProject project) async { await runProjectTest((FlutterProject project) async {
section('gradlew assembleRelease'); section('gradlew assembleRelease');
await project.runGradleTask('assembleRelease'); await project.runGradleTask('assembleRelease');
// When the platform-target isn't specified, we generate the snapshots
// for arm and arm64.
final List<String> targetPlatforms = <String>[
'android-arm',
'android-arm64'
];
for (final String targetPlatform in targetPlatforms) {
final String androidArmSnapshotPath = path.join(
project.rootPath,
'build',
'app',
'intermediates',
'flutter',
'release',
targetPlatform);
final String isolateSnapshotData =
path.join(androidArmSnapshotPath, 'isolate_snapshot_data');
if (!File(isolateSnapshotData).existsSync()) {
throw TaskResult.failure(
'Snapshot doesn\'t exist: $isolateSnapshotData');
}
final String isolateSnapshotInstr =
path.join(androidArmSnapshotPath, 'isolate_snapshot_instr');
if (!File(isolateSnapshotInstr).existsSync()) {
throw TaskResult.failure(
'Snapshot doesn\'t exist: $isolateSnapshotInstr');
}
final String vmSnapshotData =
path.join(androidArmSnapshotPath, 'vm_snapshot_data');
if (!File(isolateSnapshotData).existsSync()) {
throw TaskResult.failure(
'Snapshot doesn\'t exist: $vmSnapshotData');
}
final String vmSnapshotInstr =
path.join(androidArmSnapshotPath, 'vm_snapshot_instr');
if (!File(isolateSnapshotData).existsSync()) {
throw TaskResult.failure(
'Snapshot doesn\'t exist: $vmSnapshotInstr');
}
}
}); });
await runProjectTest((FlutterProject project) async { await runProjectTest((FlutterProject project) async {
...@@ -311,7 +356,7 @@ class _Dependencies { ...@@ -311,7 +356,7 @@ class _Dependencies {
String _validateSnapshotDependency(FlutterProject project, String expectedTarget) { String _validateSnapshotDependency(FlutterProject project, String expectedTarget) {
final _Dependencies deps = _Dependencies( final _Dependencies deps = _Dependencies(
path.join(project.rootPath, 'build', 'app', 'intermediates', path.join(project.rootPath, 'build', 'app', 'intermediates',
'flutter', 'debug', 'snapshot_blob.bin.d')); 'flutter', 'debug', 'android-arm', 'snapshot_blob.bin.d'));
return deps.target == expectedTarget ? null : return deps.target == expectedTarget ? null :
'Dependency file should have $expectedTarget as target. Instead has ${deps.target}'; 'Dependency file should have $expectedTarget as target. Instead has ${deps.target}';
} }
...@@ -36,14 +36,13 @@ android { ...@@ -36,14 +36,13 @@ android {
apply plugin: FlutterPlugin apply plugin: FlutterPlugin
class FlutterPlugin implements Plugin<Project> { class FlutterPlugin implements Plugin<Project> {
private Path baseEnginePath
private File flutterRoot private File flutterRoot
private File flutterExecutable private File flutterExecutable
private String localEngine private String localEngine
private String localEngineSrcPath private String localEngineSrcPath
private Properties localProperties private Properties localProperties
private File flutterJar private File flutterJar
private File flutterX86Jar
private File debugFlutterJar private File debugFlutterJar
private File profileFlutterJar private File profileFlutterJar
private File releaseFlutterJar private File releaseFlutterJar
...@@ -57,6 +56,22 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -57,6 +56,22 @@ class FlutterPlugin implements Plugin<Project> {
// to match. // to match.
static final String flutterBuildPrefix = "flutterBuild" static final String flutterBuildPrefix = "flutterBuild"
// The platforms (or CPU architectures) for which native code is generated.
static final Map allTargetPlatforms = [
'android-arm': 'armeabi-v7a',
'android-arm64': 'arm64-v8a',
'android-x64': 'x86_64',
'android-x86': 'x86',
]
// Supports ARM 32 and 64 bits.
// When splits are enabled, multiple APKs are generated per each CPU architecture,
// which helps decrease the size of each APK.
static final Set allArmPlatforms = [
'android-arm',
'android-arm64'
]
private Properties readPropertiesIfExist(File propertiesFile) { private Properties readPropertiesIfExist(File propertiesFile) {
Properties result = new Properties() Properties result = new Properties()
if (propertiesFile.exists()) { if (propertiesFile.exists()) {
...@@ -65,6 +80,20 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -65,6 +80,20 @@ class FlutterPlugin implements Plugin<Project> {
return result return result
} }
private String getTargetPlatform(Project project) {
if (project.hasProperty('target-platform')) {
return project.property('target-platform')
}
return 'android-arm-all';
}
private Boolean getBuildShareLibrary(Project project) {
if (project.hasProperty('build-shared-library')) {
return project.property('build-shared-library').toBoolean()
}
return false;
}
private String resolveProperty(Project project, String name, String defaultValue) { private String resolveProperty(Project project, String name, String defaultValue) {
if (localProperties == null) { if (localProperties == null) {
localProperties = readPropertiesIfExist(new File(project.projectDir.parentFile, "local.properties")) localProperties = readPropertiesIfExist(new File(project.projectDir.parentFile, "local.properties"))
...@@ -84,6 +113,23 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -84,6 +113,23 @@ class FlutterPlugin implements Plugin<Project> {
@Override @Override
void apply(Project project) { void apply(Project project) {
project.extensions.create("flutter", FlutterExtension)
project.afterEvaluate this.&addFlutterTask
allTargetPlatforms.each { currentTargetPlatformValue, abi ->
project.android {
packagingOptions {
pickFirst "lib/${abi}/libflutter.so"
// Disable warning by *-android-strip: File format not recognized
doNotStrip "*/${abi}/lib_vm_snapshot_data.so"
doNotStrip "*/${abi}/lib_vm_snapshot_instr.so"
doNotStrip "*/${abi}/lib_isolate_snapshot_data.so"
doNotStrip "*/${abi}/lib_isolate_snapshot_instr.so"
}
}
}
// Add custom build types // Add custom build types
project.android.buildTypes { project.android.buildTypes {
profile { profile {
...@@ -124,33 +170,32 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -124,33 +170,32 @@ class FlutterPlugin implements Plugin<Project> {
if (!engineOut.isDirectory()) { if (!engineOut.isDirectory()) {
throw new GradleException('localEngineOut must point to a local engine build') throw new GradleException('localEngineOut must point to a local engine build')
} }
flutterJar = Paths.get(engineOut.absolutePath, "flutter.jar").toFile() baseEnginePath = Paths.get(engineOut.absolutePath)
flutterJar = baseEnginePath.resolve("flutter.jar").toFile()
if (!flutterJar.isFile()) { if (!flutterJar.isFile()) {
throw new GradleException('File not found: ' + flutterJar) throw new GradleException('File not found: ' + flutterJar)
} }
localEngine = engineOut.name localEngine = engineOut.name
localEngineSrcPath = engineOut.parentFile.parent localEngineSrcPath = engineOut.parentFile.parent
// The local engine is built for one of the build type.
project.dependencies { // However, we use the same engine for each of the build types.
if (project.getConfigurations().findByName("api")) { debugFlutterJar = flutterJar
api project.files(flutterJar) profileFlutterJar = flutterJar
releaseFlutterJar = flutterJar
dynamicProfileFlutterJar = flutterJar
dynamicReleaseFlutterJar = flutterJar
} else { } else {
compile project.files(flutterJar) String targetPlatform = getTargetPlatform(project)
} String targetArch = targetPlatform == 'android-arm64' ? 'arm64' : 'arm'
} baseEnginePath = Paths.get(flutterRoot.absolutePath, "bin", "cache", "artifacts", "engine")
} else {
Path baseEnginePath = Paths.get(flutterRoot.absolutePath, "bin", "cache", "artifacts", "engine")
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() debugFlutterJar = baseEnginePath.resolve("android-${targetArch}").resolve("flutter.jar").toFile()
profileFlutterJar = baseEnginePath.resolve("android-${targetArch}-profile").resolve("flutter.jar").toFile() profileFlutterJar = baseEnginePath.resolve("android-${targetArch}-profile").resolve("flutter.jar").toFile()
releaseFlutterJar = baseEnginePath.resolve("android-${targetArch}-release").resolve("flutter.jar").toFile() releaseFlutterJar = baseEnginePath.resolve("android-${targetArch}-release").resolve("flutter.jar").toFile()
dynamicProfileFlutterJar = baseEnginePath.resolve("android-${targetArch}-dynamic-profile").resolve("flutter.jar").toFile() dynamicProfileFlutterJar = baseEnginePath.resolve("android-${targetArch}-dynamic-profile").resolve("flutter.jar").toFile()
dynamicReleaseFlutterJar = baseEnginePath.resolve("android-${targetArch}-dynamic-release").resolve("flutter.jar").toFile() dynamicReleaseFlutterJar = baseEnginePath.resolve("android-${targetArch}-dynamic-release").resolve("flutter.jar").toFile()
}
if (!debugFlutterJar.isFile()) { if (!debugFlutterJar.isFile()) {
project.exec { project.exec {
executable flutterExecutable.absolutePath executable flutterExecutable.absolutePath
...@@ -163,25 +208,25 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -163,25 +208,25 @@ class FlutterPlugin implements Plugin<Project> {
} }
// Add x86/x86_64 native library. Debug mode only, for now. // Add x86/x86_64 native library. Debug mode only, for now.
flutterX86Jar = project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/flutter-x86.jar") File flutterX86Jar = project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/flutter-x86.jar")
Task flutterX86JarTask = project.tasks.create("${flutterBuildPrefix}X86Jar", Jar) { Task debugX86JarTask = project.tasks.create("${flutterBuildPrefix}X86Jar", Jar) {
destinationDir flutterX86Jar.parentFile destinationDir flutterX86Jar.parentFile
archiveName flutterX86Jar.name archiveName flutterX86Jar.name
from("${flutterRoot}/bin/cache/artifacts/engine/android-x86/libflutter.so") { from("${flutterRoot}/bin/cache/artifacts/engine/android-x86/libflutter.so") {
into "lib/x86" into 'lib/x86'
} }
from("${flutterRoot}/bin/cache/artifacts/engine/android-x64/libflutter.so") { from("${flutterRoot}/bin/cache/artifacts/engine/android-x64/libflutter.so") {
into "lib/x86_64" into 'lib/x86_64'
} }
} }
// Add flutter.jar dependencies to all <buildType>Api configurations, including custom ones // Add flutter.jar dependencies to all <buildType>Api configurations, including custom ones
// added after applying the Flutter plugin. // added after applying the Flutter plugin.
project.android.buildTypes.each { addFlutterJarApiDependency(project, it, flutterX86JarTask) } project.android.buildTypes.each {
project.android.buildTypes.whenObjectAdded { addFlutterJarApiDependency(project, it, flutterX86JarTask) } addFlutterJarApiDependency(project, it, debugX86JarTask)
}
project.android.buildTypes.whenObjectAdded {
addFlutterJarApiDependency(project, it, debugX86JarTask)
} }
project.extensions.create("flutter", FlutterExtension)
project.afterEvaluate this.&addFlutterTask
File pluginsFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins') File pluginsFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins')
Properties plugins = readPropertiesIfExist(pluginsFile) Properties plugins = readPropertiesIfExist(pluginsFile)
...@@ -240,7 +285,7 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -240,7 +285,7 @@ class FlutterPlugin implements Plugin<Project> {
* *
* Note: The BuildType DSL type is not public, and is therefore omitted from the signature. * Note: The BuildType DSL type is not public, and is therefore omitted from the signature.
*/ */
private void addFlutterJarApiDependency(Project project, buildType, Task flutterX86JarTask) { private void addFlutterJarApiDependency(Project project, buildType, Task debugX86JarTask) {
project.dependencies { project.dependencies {
String configuration; String configuration;
if (project.getConfigurations().findByName("api")) { if (project.getConfigurations().findByName("api")) {
...@@ -250,16 +295,24 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -250,16 +295,24 @@ class FlutterPlugin implements Plugin<Project> {
} }
add(configuration, project.files { add(configuration, project.files {
String buildMode = buildModeFor(buildType) String buildMode = buildModeFor(buildType)
if (buildMode == "debug") { switch (buildMode) {
[flutterX86JarTask, debugFlutterJar] case "debug":
} else if (buildMode == "profile") { [debugX86JarTask, debugFlutterJar]
break
case "profile":
profileFlutterJar profileFlutterJar
} else if (buildMode == "dynamicProfile") { break
case "dynamicProfile":
dynamicProfileFlutterJar dynamicProfileFlutterJar
} else if (buildMode == "dynamicRelease") { break
case "dynamicRelease":
dynamicReleaseFlutterJar dynamicReleaseFlutterJar
} else { break
case "release":
releaseFlutterJar releaseFlutterJar
break
default:
throw new GradleException("Invalid build mode: ${buildMode}")
} }
}) })
} }
...@@ -341,17 +394,13 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -341,17 +394,13 @@ class FlutterPlugin implements Plugin<Project> {
if (project.hasProperty('extra-gen-snapshot-options')) { if (project.hasProperty('extra-gen-snapshot-options')) {
extraGenSnapshotOptionsValue = project.property('extra-gen-snapshot-options') extraGenSnapshotOptionsValue = project.property('extra-gen-snapshot-options')
} }
Boolean buildSharedLibraryValue = false
if (project.hasProperty('build-shared-library')) { Boolean buildSharedLibraryValue = this.getBuildShareLibrary(project)
buildSharedLibraryValue = project.property('build-shared-library').toBoolean() String targetPlatformValue = this.getTargetPlatform(project)
}
String targetPlatformValue = null
if (project.hasProperty('target-platform')) {
targetPlatformValue = project.property('target-platform')
}
def addFlutterDeps = { variant -> def addFlutterDeps = { variant ->
String flutterBuildMode = buildModeFor(variant.buildType) String flutterBuildMode = buildModeFor(variant.buildType)
if (flutterBuildMode == 'debug' && project.tasks.findByName('${flutterBuildPrefix}X86Jar')) { if (flutterBuildMode == 'debug' && project.tasks.findByName('${flutterBuildPrefix}X86Jar')) {
Task task = project.tasks.findByName("compile${variant.name.capitalize()}JavaWithJavac") Task task = project.tasks.findByName("compile${variant.name.capitalize()}JavaWithJavac")
if (task) { if (task) {
...@@ -363,12 +412,29 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -363,12 +412,29 @@ class FlutterPlugin implements Plugin<Project> {
} }
} }
FlutterTask flutterTask = project.tasks.create(name: "${flutterBuildPrefix}${variant.name.capitalize()}", type: FlutterTask) { def flutterTasks = []
def targetPlatforms = []
if (targetPlatformValue == 'android-arm-all') {
if (flutterBuildMode == 'release') {
targetPlatforms.addAll(allArmPlatforms)
} else {
targetPlatforms.add('android-arm')
}
} else {
targetPlatforms.add(targetPlatformValue)
}
targetPlatforms.each { currentTargetPlatformValue ->
String abiValue = allTargetPlatforms[currentTargetPlatformValue]
FlutterTask compileTask = project.tasks.create(name: "${flutterBuildPrefix}${variant.name.capitalize()}${currentTargetPlatformValue}:compile",
type: FlutterTask) {
flutterRoot this.flutterRoot flutterRoot this.flutterRoot
flutterExecutable this.flutterExecutable flutterExecutable this.flutterExecutable
buildMode flutterBuildMode buildMode flutterBuildMode
localEngine this.localEngine localEngine this.localEngine
localEngineSrcPath this.localEngineSrcPath localEngineSrcPath this.localEngineSrcPath
abi abiValue
targetPath target targetPath target
verbose verboseValue verbose verboseValue
fileSystemRoots fileSystemRootsValue fileSystemRoots fileSystemRootsValue
...@@ -379,19 +445,61 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -379,19 +445,61 @@ class FlutterPlugin implements Plugin<Project> {
buildNumber buildNumberValue buildNumber buildNumberValue
baselineDir baselineDirValue baselineDir baselineDirValue
buildSharedLibrary buildSharedLibraryValue buildSharedLibrary buildSharedLibraryValue
targetPlatform targetPlatformValue targetPlatform currentTargetPlatformValue
sourceDir project.file(project.flutter.source) sourceDir project.file(project.flutter.source)
intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}") intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}/${currentTargetPlatformValue}")
extraFrontEndOptions extraFrontEndOptionsValue extraFrontEndOptions extraFrontEndOptionsValue
extraGenSnapshotOptions extraGenSnapshotOptionsValue extraGenSnapshotOptions extraGenSnapshotOptionsValue
} }
flutterTasks.add(compileTask)
}
def libJar = project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/libs.jar")
Task packFlutterSnapshotsAndLibsTask = project.tasks.create(name: ":flutter:package:packLibs${variant.name.capitalize()}", type: Jar) {
destinationDir libJar.parentFile
archiveName libJar.name
targetPlatforms.each { targetPlatform ->
// Include `libflutter.so` for each abi.
// TODO(blasten): The libs should be outside `flutter.jar` when the artifacts are downloaded.
from(project.zipTree("${flutterRoot}/bin/cache/artifacts/engine/${targetPlatform}-release/flutter.jar")) {
include 'lib/**'
}
}
dependsOn flutterTasks
// Add the snapshots and rename them as `lib/{abi}/*.so`.
flutterTasks.each { flutterTask ->
from(flutterTask.intermediateDir) {
include 'vm_snapshot_data'
include 'vm_snapshot_instr'
include 'isolate_snapshot_data'
include 'isolate_snapshot_instr'
rename { String filename ->
return "lib/${flutterTask.abi}/lib_${filename}.so"
}
}
}
}
// Include the snapshots and libflutter.so in `lib/`.
if (flutterBuildMode == 'release' && targetPlatformValue == 'android-arm-all') {
project.dependencies {
String configuration;
if (project.getConfigurations().findByName("api")) {
configuration = buildType.name + "Api";
} else {
configuration = buildType.name + "Compile";
}
add(configuration, project.files {
packFlutterSnapshotsAndLibsTask
})
}
}
// We know that the flutter app is a subproject in another Android app when these tasks exist. // We know that the flutter app is a subproject in another Android app when these tasks exist.
Task packageAssets = project.tasks.findByPath(":flutter:package${variant.name.capitalize()}Assets") Task packageAssets = project.tasks.findByPath(":flutter:package${variant.name.capitalize()}Assets")
Task cleanPackageAssets = project.tasks.findByPath(":flutter:cleanPackage${variant.name.capitalize()}Assets") Task cleanPackageAssets = project.tasks.findByPath(":flutter:cleanPackage${variant.name.capitalize()}Assets")
Task copyFlutterAssetsTask = project.tasks.create(name: "copyFlutterAssets${variant.name.capitalize()}", type: Copy) { Task copyFlutterAssetsTask = project.tasks.create(name: "copyFlutterAssets${variant.name.capitalize()}", type: Copy) {
dependsOn flutterTask dependsOn flutterTasks
if (packageAssets && cleanPackageAssets) { if (packageAssets && cleanPackageAssets) {
dependsOn packageAssets dependsOn packageAssets
dependsOn cleanPackageAssets dependsOn cleanPackageAssets
...@@ -401,9 +509,14 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -401,9 +509,14 @@ class FlutterPlugin implements Plugin<Project> {
dependsOn "clean${variant.mergeAssets.name.capitalize()}" dependsOn "clean${variant.mergeAssets.name.capitalize()}"
into variant.mergeAssets.outputDir into variant.mergeAssets.outputDir
} }
flutterTasks.each { flutterTask ->
with flutterTask.assets with flutterTask.assets
// Include the snapshots in the assets directory.
if (flutterBuildMode != 'release' || targetPlatformValue != 'android-arm-all') {
with flutterTask.snapshots
}
}
} }
if (packageAssets) { if (packageAssets) {
String mainModuleName = "app" String mainModuleName = "app"
try { try {
...@@ -419,9 +532,11 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -419,9 +532,11 @@ class FlutterPlugin implements Plugin<Project> {
mergeAssets.dependsOn(copyFlutterAssetsTask) mergeAssets.dependsOn(copyFlutterAssetsTask)
} }
} else { } else {
variant.outputs[0].processResources.dependsOn(copyFlutterAssetsTask) def processResources = variant.outputs.first().processResources
processResources.dependsOn(copyFlutterAssetsTask)
} }
} }
if (project.android.hasProperty("applicationVariants")) { if (project.android.hasProperty("applicationVariants")) {
project.android.applicationVariants.all addFlutterDeps project.android.applicationVariants.all addFlutterDeps
} else { } else {
...@@ -463,6 +578,8 @@ abstract class BaseFlutterTask extends DefaultTask { ...@@ -463,6 +578,8 @@ abstract class BaseFlutterTask extends DefaultTask {
Boolean buildSharedLibrary Boolean buildSharedLibrary
@Optional @Input @Optional @Input
String targetPlatform String targetPlatform
@Input
String abi
File sourceDir File sourceDir
File intermediateDir File intermediateDir
@Optional @Input @Optional @Input
...@@ -505,7 +622,6 @@ abstract class BaseFlutterTask extends DefaultTask { ...@@ -505,7 +622,6 @@ abstract class BaseFlutterTask extends DefaultTask {
args "--suppress-analytics" args "--suppress-analytics"
args "--quiet" args "--quiet"
args "--target", targetPath args "--target", targetPath
args "--target-platform", "android-arm"
args "--output-dir", "${intermediateDir}" args "--output-dir", "${intermediateDir}"
if (trackWidgetCreation) { if (trackWidgetCreation) {
args "--track-widget-creation" args "--track-widget-creation"
...@@ -519,7 +635,9 @@ abstract class BaseFlutterTask extends DefaultTask { ...@@ -519,7 +635,9 @@ abstract class BaseFlutterTask extends DefaultTask {
if (buildSharedLibrary) { if (buildSharedLibrary) {
args "--build-shared-library" args "--build-shared-library"
} }
if (targetPlatform != null) { if (targetPlatform == null) {
args "--target-platform", "android-arm"
} else {
args "--target-platform", "${targetPlatform}" args "--target-platform", "${targetPlatform}"
} }
args "--${buildMode}" args "--${buildMode}"
...@@ -603,8 +721,13 @@ class FlutterTask extends BaseFlutterTask { ...@@ -603,8 +721,13 @@ class FlutterTask extends BaseFlutterTask {
CopySpec getAssets() { CopySpec getAssets() {
return project.copySpec { return project.copySpec {
from "${intermediateDir}" from "${intermediateDir}"
include "flutter_assets/**" // the working dir and its files include "flutter_assets/**" // the working dir and its files
}
}
CopySpec getSnapshots() {
return project.copySpec {
from "${intermediateDir}"
if (buildMode == 'release' || buildMode == 'profile') { if (buildMode == 'release' || buildMode == 'profile') {
if (buildSharedLibrary) { if (buildSharedLibrary) {
......
...@@ -27,7 +27,9 @@ class BuildApkCommand extends BuildSubCommand { ...@@ -27,7 +27,9 @@ class BuildApkCommand extends BuildSubCommand {
) )
..addOption('target-platform', ..addOption('target-platform',
defaultsTo: 'android-arm', defaultsTo: 'android-arm',
allowed: <String>['android-arm', 'android-arm64', 'android-x86', 'android-x64']); allowed: <String>['android-arm', 'android-arm64', 'android-x86', 'android-x64'],
help: 'The target platform for which the app is compiled.',
);
} }
@override @override
......
...@@ -20,20 +20,27 @@ class BuildAppBundleCommand extends BuildSubCommand { ...@@ -20,20 +20,27 @@ class BuildAppBundleCommand extends BuildSubCommand {
argParser argParser
..addFlag('track-widget-creation', negatable: false, hide: !verboseHelp) ..addFlag('track-widget-creation', negatable: false, hide: !verboseHelp)
..addFlag('build-shared-library', ..addFlag(
'build-shared-library',
negatable: false, 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', ..addOption(
defaultsTo: 'android-arm', 'target-platform',
allowed: <String>['android-arm', 'android-arm64']); allowed: <String>['android-arm', 'android-arm64'],
help: 'The target platform for which the app is compiled.\n'
'By default, the bundle will include \'arm\' and \'arm64\', '
'which is the recommended configuration for app bundles.\n'
'For more, see https://developer.android.com/distribute/best-practices/develop/64-bit',
);
} }
@override @override
final String name = 'appbundle'; final String name = 'appbundle';
@override @override
final String description = 'Build an Android App Bundle file from your app.\n\n' final String description =
'Build an Android App Bundle file from your app.\n\n'
'This command can build debug and release versions of an app bundle for your application. \'debug\' builds support ' 'This command can build debug and release versions of an app bundle for your application. \'debug\' builds support '
'debugging and a quick development cycle. \'release\' builds don\'t support debugging and are ' 'debugging and a quick development cycle. \'release\' builds don\'t support debugging and are '
'suitable for deploying to app stores. \n app bundle improves your app size'; 'suitable for deploying to app stores. \n app bundle improves your app size';
......
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