From 59a94155e26c32a0f72acf1b7669f56c3b06bfda Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 5 Oct 2022 19:05:51 -0700 Subject: [PATCH] Update Android target to use new build system integration Currently the Android build support relies on standalone toolchains which are obsolete as of NDK r19. This change adds support for the new build system integration described here: https://developer.android.com/ndk/guides/other_build_systems This avoids developers needing to create a standalone toolchain for each target as well as needing to specify the NDK path on each target, as the NDK path is now specified via [build]. The target-specific android-ndk option is still available for users of standalone toolchains. --- config.toml.example | 16 ++++++++++++++++ src/bootstrap/cc_detect.rs | 16 ++++++++++++++-- src/bootstrap/config.rs | 6 ++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/config.toml.example b/config.toml.example index 1f5747456e957..90805847e850d 100644 --- a/config.toml.example +++ b/config.toml.example @@ -334,6 +334,18 @@ changelog-seen = 2 # this is not intended to be used during local development. #metrics = false +# When targeting Android, specify the location of the Android NDK. This variable +# needs to be set to the location of the LLVM toolchain subdirectory within +# the NDK, found under "toolchains/llvm/prebuilt/-". +# +# This option is only compatible with Android NDK r19 or newer. If you are using +# an older NDK, you will need to create a standalone toolchain and specify the +# path via the target-specific android-ndk option. +#android-ndk = (path) + +# When targeting Android, specify the minimum API level to target. +#android-api-level = 21 + # ============================================================================= # General install configuration options # ============================================================================= @@ -700,6 +712,10 @@ changelog-seen = 2 # the NDK for the target lives. This is used to find the C compiler to link and # build native code. # See `src/bootstrap/cc_detect.rs` for details. +# +# This option is deprecated as it requires building a standalone toolchain, +# which is unnecessary with NDK r19 and newer. Instead, prefer to use the same +# option under the [build] section. #android-ndk = (path) # Build the sanitizer runtimes for this target. diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index 759a99c330c27..e01b412d96dee 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -34,7 +34,7 @@ use crate::{Build, CLang, GitRepo}; // so use some simplified logic here. First we respect the environment variable `AR`, then // try to infer the archiver path from the C compiler path. // In the future this logic should be replaced by calling into the `cc` crate. -fn cc2ar(cc: &Path, target: TargetSelection) -> Option { +fn cc2ar(cc: &Path, target: TargetSelection, build: &Build) -> Option { if let Some(ar) = env::var_os(format!("AR_{}", target.triple.replace("-", "_"))) { Some(PathBuf::from(ar)) } else if let Some(ar) = env::var_os("AR") { @@ -47,6 +47,8 @@ fn cc2ar(cc: &Path, target: TargetSelection) -> Option { Some(PathBuf::from("ar")) } else if target.contains("vxworks") { Some(PathBuf::from("wr-ar")) + } else if target.contains("android") && build.config.android_ndk.is_some() { + Some(build.config.android_ndk.as_ref().unwrap().join("bin").join("llvm-ar")) } else { let parent = cc.parent().unwrap(); let file = cc.file_name().unwrap().to_str().unwrap(); @@ -108,7 +110,7 @@ pub fn find(build: &mut Build) { let ar = if let ar @ Some(..) = config.and_then(|c| c.ar.clone()) { ar } else { - cc2ar(compiler.path(), target) + cc2ar(compiler.path(), target, build) }; build.cc.insert(target, compiler.clone()); @@ -174,6 +176,16 @@ fn set_compiler( .replace("thumbv7", "arm"); let compiler = format!("{}-{}", target, compiler.clang()); cfg.compiler(ndk.join("bin").join(compiler)); + } else if let Some(ndk) = build.config.android_ndk.as_ref() { + let target = target + .triple + .replace("armv7neon", "armv7a") + .replace("armv7", "armv7a") + .replace("thumbv7neon", "armv7a") + .replace("thumbv7", "armv7a"); + let api_level = build.config.android_api_level.unwrap_or(21); + let compiler = format!("{}{}-{}", target, api_level, compiler.clang()); + cfg.compiler(ndk.join("bin").join(compiler)); } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 8c501f637d97e..1e6a7186db3fe 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -75,6 +75,8 @@ pub struct Config { pub stage0_metadata: Stage0Metadata, /// Whether to use the `c` feature of the `compiler_builtins` crate. pub optimized_compiler_builtins: bool, + pub android_ndk: Option, + pub android_api_level: Option, pub on_fail: Option, pub stage: u32, @@ -600,6 +602,8 @@ define_config! { patch_binaries_for_nix: Option = "patch-binaries-for-nix", metrics: Option = "metrics", optimized_compiler_builtins: Option = "optimized-compiler-builtins", + android_ndk: Option = "android-ndk", + android_api_level: Option = "android-api-level", } } @@ -951,6 +955,8 @@ impl Config { config.gdb = build.gdb.map(PathBuf::from); config.python = build.python.map(PathBuf::from); config.submodules = build.submodules; + config.android_ndk = build.android_ndk; + config.android_api_level = build.android_api_level; set(&mut config.low_priority, build.low_priority); set(&mut config.compiler_docs, build.compiler_docs); set(&mut config.docs_minification, build.docs_minification);