[hooks] Don't require NDK for Android targets (#180594)

When targeting Android, don't fail in Flutter tools if the NDK is not
installed. Instead, pass a `null` c compiler config to the hooks. The
hooks can then decide to fail if they need the NDK. If no hook happened
to require the NDK, Flutter for Android apps can be built without the
NDK installed.

Bug: https://github.com/flutter/flutter/issues/180163

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
This commit is contained in:
Daco Harkes 2026-01-06 20:02:11 +01:00 committed by GitHub
parent a404f7c499
commit a0a27839c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 8 additions and 11 deletions

View File

@ -92,12 +92,11 @@ KernelAsset _targetLocationAndroid(FlutterCodeAsset asset) {
/// Looks the NDK clang compiler tools.
///
/// Tool-exits if the NDK cannot be found.
/// Returns `null` if the NDK cannot be found.
///
/// Should only be invoked if a native assets build is performed. If the native
/// assets feature is disabled, or none of the packages have native assets, a
/// missing NDK is okay.
Future<CCompilerConfig> cCompilerConfigAndroid() async {
/// Typically the Flutter Gradle Plugin will install an NDK. This method will
/// return the newest NDK if multiple NDKs are found on the system.
Future<CCompilerConfig?> cCompilerConfigAndroid() async {
final AndroidSdk? androidSdk = AndroidSdk.locateAndroidSdk();
if (androidSdk == null) {
throwToolExit('Android SDK could not be found.');
@ -106,7 +105,7 @@ Future<CCompilerConfig> cCompilerConfigAndroid() async {
final Uri? archiver = _toOptionalFileUri(androidSdk.getNdkArPath());
final Uri? linker = _toOptionalFileUri(androidSdk.getNdkLdPath());
if (compiler == null || archiver == null || linker == null) {
throwToolExit('Android NDK Clang could not be found.');
return null;
}
final result = CCompilerConfig(compiler: compiler, archiver: archiver, linker: linker);
return result;

View File

@ -8,7 +8,6 @@ import 'package:file/memory.dart';
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/android/gradle_utils.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/common.dart' show throwToolExit;
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
@ -149,7 +148,7 @@ void main() {
await packageConfig.parent.create();
await packageConfig.create();
expect(
() => runFlutterSpecificHooks(
await runFlutterSpecificHooks(
environmentDefines: <String, String>{
kBuildMode: BuildMode.debug.cliName,
kMinSdkVersion: minSdkVersion,
@ -159,7 +158,7 @@ void main() {
fileSystem: fileSystem,
buildRunner: _BuildRunnerWithoutNdk(packagesWithNativeAssetsResult: <String>['bar']),
),
throwsToolExit(message: 'Android NDK Clang could not be found.'),
isA<DartHooksResult>(),
);
},
);
@ -169,6 +168,5 @@ class _BuildRunnerWithoutNdk extends FakeFlutterNativeAssetsBuildRunner {
_BuildRunnerWithoutNdk({super.packagesWithNativeAssetsResult = const <String>[]});
@override
CCompilerConfig? get ndkCCompilerConfigResult =>
throwToolExit('Android NDK Clang could not be found.');
CCompilerConfig? get ndkCCompilerConfigResult => null;
}