Skip to content

Commit b962b34

Browse files
committed
Improve android-ndk property interface
PR #105716 added support for NDK r25b, and removed support for r15. Since the switch to r25b would have broken existing r15 users anyway, let's take the opportunity to make the interface more user friendly. Firstly move the android-ndk property to [build] instead of the targets. This is possible now that the NDK has obsoleted the concept of target-specific toolchains. Also make the property take the NDK root directory instead of the "toolchains/llvm/prebuilt/<host tag>" subdirectory.
1 parent fa4cc63 commit b962b34

File tree

6 files changed

+59
-72
lines changed

6 files changed

+59
-72
lines changed

config.example.toml

+3-6
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,9 @@ changelog-seen = 2
361361
# this is not intended to be used during local development.
362362
#metrics = false
363363

364+
# Specify the location of the Android NDK. Used when targeting Android.
365+
#android-ndk = "/path/to/android-ndk-r25b"
366+
364367
# =============================================================================
365368
# General install configuration options
366369
# =============================================================================
@@ -735,12 +738,6 @@ changelog-seen = 2
735738
# it must link to `libgcc_eh.a` to get a working output, and this option have no effect.
736739
#llvm-libunwind = 'no' if Linux, 'in-tree' if Fuchsia
737740

738-
# If this target is for Android, this option will be required to specify where
739-
# the NDK for the target lives. This is used to find the C compiler to link and
740-
# build native code.
741-
# See `src/bootstrap/cc_detect.rs` for details.
742-
#android-ndk = <none> (path)
743-
744741
# Build the sanitizer runtimes for this target.
745742
# This option will override the same option under [build] section.
746743
#sanitizers = build.sanitizers (bool)

src/bootstrap/cc_detect.rs

+48-33
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use std::path::{Path, PathBuf};
2626
use std::process::Command;
2727
use std::{env, iter};
2828

29-
use crate::config::{Target, TargetSelection};
29+
use crate::config::TargetSelection;
3030
use crate::util::output;
3131
use crate::{Build, CLang, GitRepo};
3232

@@ -100,10 +100,11 @@ pub fn find(build: &mut Build) {
100100
for target in targets.into_iter() {
101101
let mut cfg = new_cc_build(build, target);
102102
let config = build.config.target_config.get(&target);
103-
if let Some(cc) = config.and_then(|c| c.cc.as_ref()) {
103+
if let Some(cc) = config
104+
.and_then(|c| c.cc.clone())
105+
.or_else(|| default_compiler(&mut cfg, Language::C, target, build))
106+
{
104107
cfg.compiler(cc);
105-
} else {
106-
set_compiler(&mut cfg, Language::C, target, config, build);
107108
}
108109

109110
let compiler = cfg.get_compiler();
@@ -120,12 +121,12 @@ pub fn find(build: &mut Build) {
120121
// We'll need one anyways if the target triple is also a host triple
121122
let mut cfg = new_cc_build(build, target);
122123
cfg.cpp(true);
123-
let cxx_configured = if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
124+
let cxx_configured = if let Some(cxx) = config
125+
.and_then(|c| c.cxx.clone())
126+
.or_else(|| default_compiler(&mut cfg, Language::CPlusPlus, target, build))
127+
{
124128
cfg.compiler(cxx);
125129
true
126-
} else if build.hosts.contains(&target) || build.build == target {
127-
set_compiler(&mut cfg, Language::CPlusPlus, target, config, build);
128-
true
129130
} else {
130131
// Use an auto-detected compiler (or one configured via `CXX_target_triple` env vars).
131132
cfg.try_get_compiler().is_ok()
@@ -155,68 +156,70 @@ pub fn find(build: &mut Build) {
155156
}
156157
}
157158

158-
fn set_compiler(
159+
fn default_compiler(
159160
cfg: &mut cc::Build,
160161
compiler: Language,
161162
target: TargetSelection,
162-
config: Option<&Target>,
163163
build: &Build,
164-
) {
164+
) -> Option<PathBuf> {
165165
match &*target.triple {
166166
// When compiling for android we may have the NDK configured in the
167167
// config.toml in which case we look there. Otherwise the default
168168
// compiler already takes into account the triple in question.
169-
t if t.contains("android") => {
170-
if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) {
171-
cfg.compiler(ndk_compiler(compiler, &*target.triple, ndk));
172-
}
173-
}
169+
t if t.contains("android") => build
170+
.config
171+
.android_ndk
172+
.as_ref()
173+
.map(|ndk| ndk_compiler(compiler, &*target.triple, ndk)),
174174

175175
// The default gcc version from OpenBSD may be too old, try using egcc,
176176
// which is a gcc version from ports, if this is the case.
177177
t if t.contains("openbsd") => {
178178
let c = cfg.get_compiler();
179179
let gnu_compiler = compiler.gcc();
180180
if !c.path().ends_with(gnu_compiler) {
181-
return;
181+
return None;
182182
}
183183

184184
let output = output(c.to_command().arg("--version"));
185-
let i = match output.find(" 4.") {
186-
Some(i) => i,
187-
None => return,
188-
};
185+
let i = output.find(" 4.")?;
189186
match output[i + 3..].chars().next().unwrap() {
190187
'0'..='6' => {}
191-
_ => return,
188+
_ => return None,
192189
}
193190
let alternative = format!("e{}", gnu_compiler);
194191
if Command::new(&alternative).output().is_ok() {
195-
cfg.compiler(alternative);
192+
Some(PathBuf::from(alternative))
193+
} else {
194+
None
196195
}
197196
}
198197

199-
"mips-unknown-linux-musl" => {
198+
"mips-unknown-linux-musl" if compiler == Language::C => {
200199
if cfg.get_compiler().path().to_str() == Some("gcc") {
201-
cfg.compiler("mips-linux-musl-gcc");
200+
Some(PathBuf::from("mips-linux-musl-gcc"))
201+
} else {
202+
None
202203
}
203204
}
204-
"mipsel-unknown-linux-musl" => {
205+
"mipsel-unknown-linux-musl" if compiler == Language::C => {
205206
if cfg.get_compiler().path().to_str() == Some("gcc") {
206-
cfg.compiler("mipsel-linux-musl-gcc");
207+
Some(PathBuf::from("mipsel-linux-musl-gcc"))
208+
} else {
209+
None
207210
}
208211
}
209212

210-
t if t.contains("musl") => {
213+
t if t.contains("musl") && compiler == Language::C => {
211214
if let Some(root) = build.musl_root(target) {
212215
let guess = root.join("bin/musl-gcc");
213-
if guess.exists() {
214-
cfg.compiler(guess);
215-
}
216+
if guess.exists() { Some(guess) } else { None }
217+
} else {
218+
None
216219
}
217220
}
218221

219-
_ => {}
222+
_ => None,
220223
}
221224
}
222225

@@ -237,10 +240,22 @@ pub(crate) fn ndk_compiler(compiler: Language, triple: &str, ndk: &Path) -> Path
237240
let api_level =
238241
if triple.contains("aarch64") || triple.contains("x86_64") { "21" } else { "19" };
239242
let compiler = format!("{}{}-{}", triple_translated, api_level, compiler.clang());
240-
ndk.join("bin").join(compiler)
243+
let host_tag = if cfg!(target_os = "macos") {
244+
// The NDK uses universal binaries, so this is correct even on ARM.
245+
"darwin-x86_64"
246+
} else if cfg!(target_os = "windows") {
247+
"windows-x86_64"
248+
} else {
249+
// NDK r25b only has official releases for macOS, Windows and Linux.
250+
// Try the Linux directory everywhere else, on the assumption that the OS has an
251+
// emulation layer that can cope (e.g. BSDs).
252+
"linux-x86_64"
253+
};
254+
ndk.join("toolchains").join("llvm").join("prebuilt").join(host_tag).join("bin").join(compiler)
241255
}
242256

243257
/// The target programming language for a native compiler.
258+
#[derive(PartialEq)]
244259
pub(crate) enum Language {
245260
/// The compiler is targeting C.
246261
C,

src/bootstrap/config.rs

+5-12
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use std::str::FromStr;
1818

1919
use crate::builder::TaskPath;
2020
use crate::cache::{Interned, INTERNER};
21-
use crate::cc_detect::{ndk_compiler, Language};
2221
use crate::channel::{self, GitInfo};
2322
pub use crate::flags::Subcommand;
2423
use crate::flags::{Color, Flags};
@@ -85,6 +84,7 @@ pub struct Config {
8584
pub color: Color,
8685
pub patch_binaries_for_nix: bool,
8786
pub stage0_metadata: Stage0Metadata,
87+
pub android_ndk: Option<PathBuf>,
8888

8989
pub stdout_is_tty: bool,
9090
pub stderr_is_tty: bool,
@@ -452,7 +452,6 @@ pub struct Target {
452452
pub ranlib: Option<PathBuf>,
453453
pub default_linker: Option<PathBuf>,
454454
pub linker: Option<PathBuf>,
455-
pub ndk: Option<PathBuf>,
456455
pub sanitizers: Option<bool>,
457456
pub profiler: Option<bool>,
458457
pub crt_static: Option<bool>,
@@ -654,6 +653,7 @@ define_config! {
654653
patch_binaries_for_nix: Option<bool> = "patch-binaries-for-nix",
655654
// NOTE: only parsed by bootstrap.py, `--feature build-metrics` enables metrics unconditionally
656655
metrics: Option<bool> = "metrics",
656+
android_ndk: Option<PathBuf> = "android-ndk",
657657
}
658658
}
659659

@@ -797,7 +797,6 @@ define_config! {
797797
llvm_has_rust_patches: Option<bool> = "llvm-has-rust-patches",
798798
llvm_filecheck: Option<String> = "llvm-filecheck",
799799
llvm_libunwind: Option<String> = "llvm-libunwind",
800-
android_ndk: Option<String> = "android-ndk",
801800
sanitizers: Option<bool> = "sanitizers",
802801
profiler: Option<bool> = "profiler",
803802
crt_static: Option<bool> = "crt-static",
@@ -1044,6 +1043,7 @@ impl Config {
10441043
config.python = build.python.map(PathBuf::from);
10451044
config.reuse = build.reuse.map(PathBuf::from);
10461045
config.submodules = build.submodules;
1046+
config.android_ndk = build.android_ndk;
10471047
set(&mut config.low_priority, build.low_priority);
10481048
set(&mut config.compiler_docs, build.compiler_docs);
10491049
set(&mut config.library_docs_private_items, build.library_docs_private_items);
@@ -1279,18 +1279,11 @@ impl Config {
12791279
.llvm_libunwind
12801280
.as_ref()
12811281
.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
1282-
if let Some(ref s) = cfg.android_ndk {
1283-
target.ndk = Some(config.src.join(s));
1284-
}
12851282
if let Some(s) = cfg.no_std {
12861283
target.no_std = s;
12871284
}
1288-
target.cc = cfg.cc.map(PathBuf::from).or_else(|| {
1289-
target.ndk.as_ref().map(|ndk| ndk_compiler(Language::C, &triple, ndk))
1290-
});
1291-
target.cxx = cfg.cxx.map(PathBuf::from).or_else(|| {
1292-
target.ndk.as_ref().map(|ndk| ndk_compiler(Language::CPlusPlus, &triple, ndk))
1293-
});
1285+
target.cc = cfg.cc.map(PathBuf::from);
1286+
target.cxx = cfg.cxx.map(PathBuf::from);
12941287
target.ar = cfg.ar.map(PathBuf::from);
12951288
target.ranlib = cfg.ranlib.map(PathBuf::from);
12961289
target.linker = cfg.linker.map(PathBuf::from);

src/bootstrap/configure.py

+1-14
Original file line numberDiff line numberDiff line change
@@ -97,20 +97,7 @@ def v(*args):
9797
v("llvm-config", None, "set path to llvm-config")
9898
v("llvm-filecheck", None, "set path to LLVM's FileCheck utility")
9999
v("python", "build.python", "set path to python")
100-
v("android-cross-path", "target.arm-linux-androideabi.android-ndk",
101-
"Android NDK standalone path (deprecated)")
102-
v("i686-linux-android-ndk", "target.i686-linux-android.android-ndk",
103-
"i686-linux-android NDK standalone path")
104-
v("arm-linux-androideabi-ndk", "target.arm-linux-androideabi.android-ndk",
105-
"arm-linux-androideabi NDK standalone path")
106-
v("armv7-linux-androideabi-ndk", "target.armv7-linux-androideabi.android-ndk",
107-
"armv7-linux-androideabi NDK standalone path")
108-
v("thumbv7neon-linux-androideabi-ndk", "target.thumbv7neon-linux-androideabi.android-ndk",
109-
"thumbv7neon-linux-androideabi NDK standalone path")
110-
v("aarch64-linux-android-ndk", "target.aarch64-linux-android.android-ndk",
111-
"aarch64-linux-android NDK standalone path")
112-
v("x86_64-linux-android-ndk", "target.x86_64-linux-android.android-ndk",
113-
"x86_64-linux-android NDK standalone path")
100+
v("android-ndk", "build.android-ndk", "set path to Android NDK")
114101
v("musl-root", "target.x86_64-unknown-linux-musl.musl-root",
115102
"MUSL root installation directory (deprecated)")
116103
v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root",

src/ci/docker/host-x86_64/arm-android/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ ENV PATH=$PATH:/android/sdk/platform-tools
3030

3131
ENV TARGETS=arm-linux-androideabi
3232

33-
ENV RUST_CONFIGURE_ARGS --arm-linux-androideabi-ndk=/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/
33+
ENV RUST_CONFIGURE_ARGS --android-ndk=/android/ndk/
3434

3535
ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target $TARGETS
3636

src/ci/docker/host-x86_64/dist-android/Dockerfile

+1-6
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,7 @@ ENV TARGETS=$TARGETS,x86_64-linux-android
1919
ENV RUST_CONFIGURE_ARGS \
2020
--enable-extended \
2121
--enable-profiler \
22-
--arm-linux-androideabi-ndk=/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/ \
23-
--armv7-linux-androideabi-ndk=/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/ \
24-
--thumbv7neon-linux-androideabi-ndk=/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/ \
25-
--i686-linux-android-ndk=/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/ \
26-
--aarch64-linux-android-ndk=/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/ \
27-
--x86_64-linux-android-ndk=/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/ \
22+
--android-ndk=/android/ndk/ \
2823
--disable-docs
2924

3025
ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS

0 commit comments

Comments
 (0)