Skip to content

Commit f19e8b0

Browse files
committed
Improve android-ndk property interface
PR rust-lang#102332 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 6f04af4 commit f19e8b0

File tree

6 files changed

+62
-74
lines changed

6 files changed

+62
-74
lines changed

config.toml.example

+3-6
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,9 @@ changelog-seen = 2
341341
# this is not intended to be used during local development.
342342
#metrics = false
343343

344+
# Specify the location of the Android NDK. Used when targeting Android.
345+
#android-ndk = "/path/to/android-ndk-r25b"
346+
344347
# =============================================================================
345348
# General install configuration options
346349
# =============================================================================
@@ -708,12 +711,6 @@ changelog-seen = 2
708711
# it must link to `libgcc_eh.a` to get a working output, and this option have no effect.
709712
#llvm-libunwind = 'no' if Linux, 'in-tree' if Fuchsia
710713

711-
# If this target is for Android, this option will be required to specify where
712-
# the NDK for the target lives. This is used to find the C compiler to link and
713-
# build native code.
714-
# See `src/bootstrap/cc_detect.rs` for details.
715-
#android-ndk = <none> (path)
716-
717714
# Build the sanitizer runtimes for this target.
718715
# This option will override the same option under [build] section.
719716
#sanitizers = build.sanitizers (bool)

src/bootstrap/cc_detect.rs

+44-30
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

199198
"mips-unknown-linux-musl" => {
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
}
204205
"mipsel-unknown-linux-musl" => {
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

210213
t if t.contains("musl") => {
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,7 +240,18 @@ 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.

src/bootstrap/config.rs

+12-17
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use std::str::FromStr;
1515

1616
use crate::builder::TaskPath;
1717
use crate::cache::{Interned, INTERNER};
18-
use crate::cc_detect::{ndk_compiler, Language};
1918
use crate::channel::{self, GitInfo};
2019
pub use crate::flags::Subcommand;
2120
use crate::flags::{Color, Flags};
@@ -84,6 +83,7 @@ pub struct Config {
8483
pub color: Color,
8584
pub patch_binaries_for_nix: bool,
8685
pub stage0_metadata: Stage0Metadata,
86+
pub android_ndk: Option<PathBuf>,
8787

8888
pub on_fail: Option<String>,
8989
pub stage: u32,
@@ -436,7 +436,6 @@ pub struct Target {
436436
pub ranlib: Option<PathBuf>,
437437
pub default_linker: Option<PathBuf>,
438438
pub linker: Option<PathBuf>,
439-
pub ndk: Option<PathBuf>,
440439
pub sanitizers: Option<bool>,
441440
pub profiler: Option<bool>,
442441
pub crt_static: Option<bool>,
@@ -636,6 +635,7 @@ define_config! {
636635
bench_stage: Option<u32> = "bench-stage",
637636
patch_binaries_for_nix: Option<bool> = "patch-binaries-for-nix",
638637
metrics: Option<bool> = "metrics",
638+
android_ndk: Option<PathBuf> = "android-ndk",
639639
}
640640
}
641641

@@ -777,7 +777,6 @@ define_config! {
777777
llvm_has_rust_patches: Option<bool> = "llvm-has-rust-patches",
778778
llvm_filecheck: Option<String> = "llvm-filecheck",
779779
llvm_libunwind: Option<String> = "llvm-libunwind",
780-
android_ndk: Option<String> = "android-ndk",
781780
sanitizers: Option<bool> = "sanitizers",
782781
profiler: Option<bool> = "profiler",
783782
crt_static: Option<bool> = "crt-static",
@@ -863,11 +862,13 @@ impl Config {
863862
// We still support running outside the repository if we find we aren't in a git directory.
864863
cmd.arg("rev-parse").arg("--show-toplevel");
865864
// Discard stderr because we expect this to fail when building from a tarball.
866-
let output = cmd
867-
.stderr(std::process::Stdio::null())
868-
.output()
869-
.ok()
870-
.and_then(|output| if output.status.success() { Some(output) } else { None });
865+
let output = cmd.stderr(std::process::Stdio::null()).output().ok().and_then(|output| {
866+
if output.status.success() {
867+
Some(output)
868+
} else {
869+
None
870+
}
871+
});
871872
if let Some(output) = output {
872873
let git_root = String::from_utf8(output.stdout).unwrap();
873874
// We need to canonicalize this path to make sure it uses backslashes instead of forward slashes.
@@ -1008,6 +1009,7 @@ impl Config {
10081009
config.python = build.python.map(PathBuf::from);
10091010
config.reuse = build.reuse.map(PathBuf::from);
10101011
config.submodules = build.submodules;
1012+
config.android_ndk = build.android_ndk;
10111013
set(&mut config.low_priority, build.low_priority);
10121014
set(&mut config.compiler_docs, build.compiler_docs);
10131015
set(&mut config.docs_minification, build.docs_minification);
@@ -1235,18 +1237,11 @@ impl Config {
12351237
.llvm_libunwind
12361238
.as_ref()
12371239
.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
1238-
if let Some(ref s) = cfg.android_ndk {
1239-
target.ndk = Some(config.src.join(s));
1240-
}
12411240
if let Some(s) = cfg.no_std {
12421241
target.no_std = s;
12431242
}
1244-
target.cc = cfg.cc.map(PathBuf::from).or_else(|| {
1245-
target.ndk.as_ref().map(|ndk| ndk_compiler(Language::C, &triple, ndk))
1246-
});
1247-
target.cxx = cfg.cxx.map(PathBuf::from).or_else(|| {
1248-
target.ndk.as_ref().map(|ndk| ndk_compiler(Language::CPlusPlus, &triple, ndk))
1249-
});
1243+
target.cc = cfg.cc.map(PathBuf::from);
1244+
target.cxx = cfg.cxx.map(PathBuf::from);
12501245
target.ar = cfg.ar.map(PathBuf::from);
12511246
target.ranlib = cfg.ranlib.map(PathBuf::from);
12521247
target.linker = cfg.linker.map(PathBuf::from);

src/bootstrap/configure.py

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