Skip to content

Commit

Permalink
[tool][android] Allow --target-platform work properly with --debug mo…
Browse files Browse the repository at this point in the history
…de (flutter#154476)

This PR addresses an issue where the `--target-platform` flag was not being respected when building APKs in debug mode. Previously, debug builds would always include `x86` and `x64` architectures, regardless of the specified target platform. This change ensures that the `--target-platform` flag is honored across all build modes, including debug.

To achieve this, `BuildApkCommand` has been slightly changed to become responsible for list of archs that should be built in the current run,rather than just parsing arguments. Previously, this responsibility was distributed to gradle, which could be frustrating (in my opinion)

Fixes flutter#153359
  • Loading branch information
Sameri11 authored Oct 1, 2024
1 parent 6bba08c commit 0975e61
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 47 deletions.
1 change: 0 additions & 1 deletion dev/devicelab/bin/tasks/build_aar_module_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,6 @@ Future<void> main() async {

checkFileContains(<String>[
'flutter_embedding_debug',
'x86_debug',
'x86_64_debug',
'armeabi_v7a_debug',
'arm64_v8a_debug',
Expand Down
7 changes: 0 additions & 7 deletions dev/devicelab/bin/tasks/gradle_plugin_light_apk_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ Future<void> main() async {
...debugAssets,
...baseApkFiles,
'lib/armeabi-v7a/libflutter.so',
// Debug mode intentionally includes `x86` and `x86_64`.
'lib/x86/libflutter.so',
'lib/x86_64/libflutter.so',
], apkFiles);

checkCollectionDoesNotContain<String>(<String>[
Expand Down Expand Up @@ -65,9 +62,7 @@ Future<void> main() async {
...flutterAssets,
...debugAssets,
...baseApkFiles,
// Debug mode intentionally includes `x86` and `x86_64`.
'lib/x86/libflutter.so',
'lib/x86_64/libflutter.so',
], apkFiles);

checkCollectionDoesNotContain<String>(<String>[
Expand Down Expand Up @@ -96,8 +91,6 @@ Future<void> main() async {
...flutterAssets,
...debugAssets,
...baseApkFiles,
// Debug mode intentionally includes `x86` and `x86_64`.
'lib/x86/libflutter.so',
'lib/x86_64/libflutter.so',
], apkFiles);

Expand Down
5 changes: 0 additions & 5 deletions packages/flutter_tools/gradle/src/main/groovy/flutter.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -637,11 +637,6 @@ class FlutterPlugin implements Plugin<Project> {
"io.flutter:flutter_embedding_$flutterBuildMode:$engineVersion")
}
List<String> platforms = getTargetPlatforms().collect()
// Debug mode includes x86 and x64, which are commonly used in emulators.
if (flutterBuildMode == "debug" && !useLocalEngine()) {
platforms.add("android-x86")
platforms.add("android-x64")
}
platforms.each { platform ->
String arch = PLATFORM_ARCH_MAP[platform].replace("-", "_")
// Add the `libflutter.so` dependency.
Expand Down
71 changes: 37 additions & 34 deletions packages/flutter_tools/lib/src/commands/build_apk.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,43 @@ class BuildApkCommand extends BuildSubCommand {
help: 'Generate build files used by flutter but '
'do not build any artifacts.')
..addMultiOption('target-platform',
defaultsTo: <String>['android-arm', 'android-arm64', 'android-x64'],
allowed: <String>['android-arm', 'android-arm64', 'android-x86', 'android-x64'],
// https://github.com/flutter/flutter/issues/153359 tracks debug build type support.
help:
'The target platform for which the app is compiled. Supports release but not debug build types.',
'The target platform for which the app is compiled.',
);
usesTrackWidgetCreation(verboseHelp: verboseHelp);
}

BuildMode get _buildMode {
if (boolArg('release')) {
return BuildMode.release;
} else if (boolArg('profile')) {
return BuildMode.profile;
} else if (boolArg('debug')) {
return BuildMode.debug;
} else if (boolArg('jit-release')) {
return BuildMode.jitRelease;
}
return BuildMode.release;
}
static const List<String> _kDefaultJitArchs = <String>[
'android-arm',
'android-arm64',
'android-x86',
'android-x64',
];
static const List<String> _kDefaultAotArchs = <String>[
'android-arm',
'android-arm64',
'android-x64',
];
List<String> get _targetArchs => stringsArg('target-platform').isEmpty
? switch (_buildMode) {
BuildMode.release || BuildMode.profile => _kDefaultAotArchs,
BuildMode.debug || BuildMode.jitRelease => _kDefaultJitArchs,
}
: stringsArg('target-platform');

@override
final String name = 'apk';

Expand All @@ -81,46 +109,20 @@ class BuildApkCommand extends BuildSubCommand {

@override
Future<CustomDimensions> get usageValues async {
String buildMode;

if (boolArg('release')) {
buildMode = 'release';
} else if (boolArg('debug')) {
buildMode = 'debug';
} else if (boolArg('profile')) {
buildMode = 'profile';
} else {
// The build defaults to release.
buildMode = 'release';
}

return CustomDimensions(
commandBuildApkTargetPlatform: stringsArg('target-platform').join(','),
commandBuildApkBuildMode: buildMode,
commandBuildApkTargetPlatform: _targetArchs.join(','),
commandBuildApkBuildMode: _buildMode.cliName,
commandBuildApkSplitPerAbi: boolArg('split-per-abi'),
);
}

@override
Future<Event> unifiedAnalyticsUsageValues(String commandPath) async {
final String buildMode;

if (boolArg('release')) {
buildMode = 'release';
} else if (boolArg('debug')) {
buildMode = 'debug';
} else if (boolArg('profile')) {
buildMode = 'profile';
} else {
// The build defaults to release.
buildMode = 'release';
}

return Event.commandUsageValues(
workflow: commandPath,
commandHasTerminal: hasTerminal,
buildApkTargetPlatform: stringsArg('target-platform').join(','),
buildApkBuildMode: buildMode,
buildApkTargetPlatform: _targetArchs.join(','),
buildApkBuildMode: _buildMode.cliName,
buildApkSplitPerAbi: boolArg('split-per-abi'),
);
}
Expand All @@ -131,10 +133,11 @@ class BuildApkCommand extends BuildSubCommand {
exitWithNoSdkMessage();
}
final BuildInfo buildInfo = await getBuildInfo();

final AndroidBuildInfo androidBuildInfo = AndroidBuildInfo(
buildInfo,
splitPerAbi: boolArg('split-per-abi'),
targetArchs: stringsArg('target-platform').map<AndroidArch>(getAndroidArchForName),
targetArchs: _targetArchs.map<AndroidArch>(getAndroidArchForName),
);
validateBuild(androidBuildInfo);
displayNullSafetyMode(androidBuildInfo.buildInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,172 @@ void main() {
testUsingContext('indicate the default target platforms', () async {
final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=app']);

// Without buildMode flag.
await runBuildApkCommand(projectPath);
expect(
fakeAnalytics.sentEvents,
contains(
Event.commandUsageValues(
workflow: 'apk',
commandHasTerminal: false,
buildApkTargetPlatform: 'android-arm,android-arm64,android-x64',
buildApkBuildMode: 'release',
buildApkSplitPerAbi: false,
),
),
);

await runBuildApkCommand(projectPath, arguments: <String>['--debug']);
expect(
fakeAnalytics.sentEvents,
contains(
Event.commandUsageValues(
workflow: 'apk',
commandHasTerminal: false,
buildApkTargetPlatform: 'android-arm,android-arm64,android-x86,android-x64',
buildApkBuildMode: 'debug',
buildApkSplitPerAbi: false,
),
),
);

await runBuildApkCommand(projectPath, arguments: <String>['--jit-release']);
expect(
fakeAnalytics.sentEvents,
contains(
Event.commandUsageValues(
workflow: 'apk',
commandHasTerminal: false,
buildApkTargetPlatform: 'android-arm,android-arm64,android-x86,android-x64',
buildApkBuildMode: 'jit_release',
buildApkSplitPerAbi: false,
),
),
);

await runBuildApkCommand(projectPath, arguments: <String>['--profile']);
expect(
fakeAnalytics.sentEvents,
contains(
Event.commandUsageValues(
workflow: 'apk',
commandHasTerminal: false,
buildApkTargetPlatform: 'android-arm,android-arm64,android-x64',
buildApkBuildMode: 'profile',
buildApkSplitPerAbi: false,
),
),
);

await runBuildApkCommand(projectPath, arguments: <String>['--release']);
expect(
fakeAnalytics.sentEvents,
contains(
Event.commandUsageValues(
workflow: 'apk',
commandHasTerminal: false,
buildApkTargetPlatform: 'android-arm,android-arm64,android-x64',
buildApkBuildMode: 'release',
buildApkSplitPerAbi: false,
),
),
);

}, overrides: <Type, Generator>{
AndroidBuilder: () => FakeAndroidBuilder(),
Analytics: () => fakeAnalytics,
});

testUsingContext('Each build mode respects --target-platform', () async {
final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=app']);

// Without buildMode flag.
await runBuildApkCommand(
projectPath,
arguments: <String>['--target-platform=android-arm'],
);
expect(
fakeAnalytics.sentEvents,
contains(
Event.commandUsageValues(
workflow: 'apk',
commandHasTerminal: false,
buildApkTargetPlatform: 'android-arm',
buildApkBuildMode: 'release',
buildApkSplitPerAbi: false,
),
),
);

await runBuildApkCommand(
projectPath,
arguments: <String>['--debug', '--target-platform=android-arm'],
);
expect(
fakeAnalytics.sentEvents,
contains(
Event.commandUsageValues(
workflow: 'apk',
commandHasTerminal: false,
buildApkTargetPlatform: 'android-arm',
buildApkBuildMode: 'debug',
buildApkSplitPerAbi: false,
),
),
);

await runBuildApkCommand(
projectPath,
arguments: <String>['--release', '--target-platform=android-arm'],
);
expect(
fakeAnalytics.sentEvents,
contains(
Event.commandUsageValues(
workflow: 'apk',
commandHasTerminal: false,
buildApkTargetPlatform: 'android-arm',
buildApkBuildMode: 'release',
buildApkSplitPerAbi: false,
),
),
);

await runBuildApkCommand(
projectPath,
arguments: <String>['--profile', '--target-platform=android-arm'],
);
expect(
fakeAnalytics.sentEvents,
contains(
Event.commandUsageValues(
workflow: 'apk',
commandHasTerminal: false,
buildApkTargetPlatform: 'android-arm',
buildApkBuildMode: 'profile',
buildApkSplitPerAbi: false,
),
),
);

await runBuildApkCommand(
projectPath,
arguments: <String>['--jit-release', '--target-platform=android-arm'],
);
expect(
fakeAnalytics.sentEvents,
contains(
Event.commandUsageValues(
workflow: 'apk',
commandHasTerminal: false,
buildApkTargetPlatform: 'android-arm',
buildApkBuildMode: 'jit_release',
buildApkSplitPerAbi: false,
),
),
);
}, overrides: <Type, Generator>{
AndroidBuilder: () => FakeAndroidBuilder(),
Analytics: () => fakeAnalytics,
Expand Down

0 comments on commit 0975e61

Please sign in to comment.