Skip to content

Commit 888e2c2

Browse files
authored
Rollup merge of rust-lang#34567 - alexcrichton:rustbuild-android, r=brson
rustbuild: Implement testing for Android This commit enhances the rustbuild support for testing Android to the same level of parity as the makefiles. This involved: * A new step to copy the standard library and other shared objects to the emulator. This is injected as a dependency of all test suites for Android. * Appropriate arguments are now passed through to compiletest to ensure that it can run tests. * When testing the standard library the test executables are probed for and shipped to the emulator to run for each test. * Fixing compilation of compiler-rt a bit All support added here is modeled after what's found in the makefiles, just translating one strategy to another. As an added bonus this commit adds support for the "check" step to automatically run tests for all targets, and the "check-target" step now runs all tests for a particular target, automatically filtering the tests if the target is detected as a cross-compile. Note that we don't (and probably won't) have a bot which is actually going to exercise any of this just yet, but all tests have passed locally for me at least.
2 parents 533ce9a + 39a5d3f commit 888e2c2

File tree

8 files changed

+227
-52
lines changed

8 files changed

+227
-52
lines changed

src/bootstrap/build/cc.rs

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ fn set_compiler(cfg: &mut gcc::Config,
9090
// compiler already takes into account the triple in question.
9191
t if t.contains("android") => {
9292
if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) {
93+
let target = target.replace("armv7", "arm");
9394
let compiler = format!("{}-{}", target, gnu_compiler);
9495
cfg.compiler(ndk.join("bin").join(compiler));
9596
}

src/bootstrap/build/check.rs

+117-11
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ use build_helper::output;
2323
use bootstrap::{dylib_path, dylib_path_var};
2424

2525
use build::{Build, Compiler, Mode};
26+
use build::util;
27+
28+
const ADB_TEST_DIR: &'static str = "/data/tmp";
2629

2730
/// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
2831
///
@@ -88,6 +91,7 @@ pub fn compiletest(build: &Build,
8891
target: &str,
8992
mode: &str,
9093
suite: &str) {
94+
println!("Check compiletest {} ({} -> {})", suite, compiler.host, target);
9195
let mut cmd = build.tool_cmd(compiler, "compiletest");
9296

9397
// compiletest currently has... a lot of arguments, so let's just pass all
@@ -105,21 +109,23 @@ pub fn compiletest(build: &Build,
105109
cmd.arg("--host").arg(compiler.host);
106110
cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build));
107111

108-
let mut flags = format!("-Crpath");
112+
let mut flags = vec!["-Crpath".to_string()];
109113
if build.config.rust_optimize_tests {
110-
flags.push_str(" -O");
114+
flags.push("-O".to_string());
111115
}
112116
if build.config.rust_debuginfo_tests {
113-
flags.push_str(" -g");
117+
flags.push("-g".to_string());
114118
}
115119

116-
cmd.arg("--host-rustcflags").arg(&flags);
117-
118-
let linkflag = format!("-Lnative={}", build.test_helpers_out(target).display());
119-
cmd.arg("--target-rustcflags").arg(format!("{} {}", flags, linkflag));
120+
let mut hostflags = build.rustc_flags(&compiler.host);
121+
hostflags.extend(flags.clone());
122+
cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
120123

121-
// FIXME: needs android support
122-
cmd.arg("--android-cross-path").arg("");
124+
let mut targetflags = build.rustc_flags(&target);
125+
targetflags.extend(flags);
126+
targetflags.push(format!("-Lnative={}",
127+
build.test_helpers_out(target).display()));
128+
cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
123129

124130
// FIXME: CFG_PYTHON should probably be detected more robustly elsewhere
125131
let python_default = "python";
@@ -180,6 +186,16 @@ pub fn compiletest(build: &Build,
180186
}
181187
build.add_bootstrap_key(compiler, &mut cmd);
182188

189+
cmd.arg("--adb-path").arg("adb");
190+
cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
191+
if target.contains("android") {
192+
// Assume that cc for this target comes from the android sysroot
193+
cmd.arg("--android-cross-path")
194+
.arg(build.cc(target).parent().unwrap().parent().unwrap());
195+
} else {
196+
cmd.arg("--android-cross-path").arg("");
197+
}
198+
183199
build.run(&mut cmd);
184200
}
185201

@@ -302,7 +318,97 @@ pub fn krate(build: &Build,
302318
let mut dylib_path = dylib_path();
303319
dylib_path.insert(0, build.sysroot_libdir(compiler, target));
304320
cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
305-
cargo.args(&build.flags.args);
306321

307-
build.run(&mut cargo);
322+
if target.contains("android") {
323+
build.run(cargo.arg("--no-run"));
324+
krate_android(build, compiler, target, mode);
325+
} else {
326+
cargo.args(&build.flags.args);
327+
build.run(&mut cargo);
328+
}
329+
}
330+
331+
fn krate_android(build: &Build,
332+
compiler: &Compiler,
333+
target: &str,
334+
mode: Mode) {
335+
let mut tests = Vec::new();
336+
let out_dir = build.cargo_out(compiler, mode, target);
337+
find_tests(&out_dir, target, &mut tests);
338+
find_tests(&out_dir.join("deps"), target, &mut tests);
339+
340+
for test in tests {
341+
build.run(Command::new("adb").arg("push").arg(&test).arg(ADB_TEST_DIR));
342+
343+
let test_file_name = test.file_name().unwrap().to_string_lossy();
344+
let log = format!("{}/check-stage{}-T-{}-H-{}-{}.log",
345+
ADB_TEST_DIR,
346+
compiler.stage,
347+
target,
348+
compiler.host,
349+
test_file_name);
350+
let program = format!("(cd {dir}; \
351+
LD_LIBRARY_PATH=./{target} ./{test} \
352+
--logfile {log} \
353+
{args})",
354+
dir = ADB_TEST_DIR,
355+
target = target,
356+
test = test_file_name,
357+
log = log,
358+
args = build.flags.args.join(" "));
359+
360+
let output = output(Command::new("adb").arg("shell").arg(&program));
361+
println!("{}", output);
362+
build.run(Command::new("adb")
363+
.arg("pull")
364+
.arg(&log)
365+
.arg(build.out.join("tmp")));
366+
build.run(Command::new("adb").arg("shell").arg("rm").arg(&log));
367+
if !output.contains("result: ok") {
368+
panic!("some tests failed");
369+
}
370+
}
371+
}
372+
373+
fn find_tests(dir: &Path,
374+
target: &str,
375+
dst: &mut Vec<PathBuf>) {
376+
for e in t!(dir.read_dir()).map(|e| t!(e)) {
377+
let file_type = t!(e.file_type());
378+
if !file_type.is_file() {
379+
continue
380+
}
381+
let filename = e.file_name().into_string().unwrap();
382+
if (target.contains("windows") && filename.ends_with(".exe")) ||
383+
(!target.contains("windows") && !filename.contains(".")) {
384+
dst.push(e.path());
385+
}
386+
}
387+
}
388+
389+
pub fn android_copy_libs(build: &Build,
390+
compiler: &Compiler,
391+
target: &str) {
392+
println!("Android copy libs to emulator ({})", target);
393+
build.run(Command::new("adb").arg("remount"));
394+
build.run(Command::new("adb").args(&["shell", "rm", "-r", ADB_TEST_DIR]));
395+
build.run(Command::new("adb").args(&["shell", "mkdir", ADB_TEST_DIR]));
396+
build.run(Command::new("adb")
397+
.arg("push")
398+
.arg(build.src.join("src/etc/adb_run_wrapper.sh"))
399+
.arg(ADB_TEST_DIR));
400+
401+
let target_dir = format!("{}/{}", ADB_TEST_DIR, target);
402+
build.run(Command::new("adb").args(&["shell", "mkdir", &target_dir[..]]));
403+
404+
for f in t!(build.sysroot_libdir(compiler, target).read_dir()) {
405+
let f = t!(f);
406+
let name = f.file_name().into_string().unwrap();
407+
if util::is_dylib(&name) {
408+
build.run(Command::new("adb")
409+
.arg("push")
410+
.arg(f.path())
411+
.arg(&target_dir));
412+
}
413+
}
308414
}

src/bootstrap/build/config.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -368,13 +368,13 @@ impl Config {
368368
target.ndk = Some(PathBuf::from(value));
369369
}
370370
"CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => {
371-
let target = "i686-linux-androideabi".to_string();
371+
let target = "i686-linux-android".to_string();
372372
let target = self.target_config.entry(target)
373373
.or_insert(Target::default());
374374
target.ndk = Some(PathBuf::from(value));
375375
}
376376
"CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => {
377-
let target = "aarch64-linux-androideabi".to_string();
377+
let target = "aarch64-linux-android".to_string();
378378
let target = self.target_config.entry(target)
379379
.or_insert(Target::default());
380380
target.ndk = Some(PathBuf::from(value));

src/bootstrap/build/dist.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ pub fn rustc(build: &Build, stage: u32, host: &str) {
135135

136136
// Prepare the overlay which is part of the tarball but won't actually be
137137
// installed
138-
t!(fs::create_dir_all(&overlay));
139138
let cp = |file: &str| {
140139
install(&build.src.join(file), &overlay, 0o644);
141140
};
@@ -199,7 +198,6 @@ pub fn rustc(build: &Build, stage: u32, host: &str) {
199198

200199
// Copy runtime DLLs needed by the compiler
201200
if libdir != "bin" {
202-
t!(fs::create_dir_all(image.join(libdir)));
203201
for entry in t!(src.join(libdir).read_dir()).map(|e| t!(e)) {
204202
let name = entry.file_name();
205203
if let Some(s) = name.to_str() {
@@ -221,7 +219,6 @@ pub fn rustc(build: &Build, stage: u32, host: &str) {
221219
let cp = |file: &str| {
222220
install(&build.src.join(file), &image.join("share/doc/rust"), 0o644);
223221
};
224-
t!(fs::create_dir_all(&image.join("share/doc/rust")));
225222
cp("COPYRIGHT");
226223
cp("LICENSE-APACHE");
227224
cp("LICENSE-MIT");
@@ -289,6 +286,7 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) {
289286

290287
fn install(src: &Path, dstdir: &Path, perms: u32) {
291288
let dst = dstdir.join(src.file_name().unwrap());
289+
t!(fs::create_dir_all(dstdir));
292290
t!(fs::copy(src, &dst));
293291
chmod(&dst, perms);
294292
}

src/bootstrap/build/mod.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ pub struct Build {
128128
///
129129
/// These entries currently correspond to the various output directories of the
130130
/// build system, with each mod generating output in a different directory.
131+
#[derive(Clone, Copy)]
131132
pub enum Mode {
132133
/// This cargo is going to build the standard library, placing output in the
133134
/// "stageN-std" directory.
@@ -383,8 +384,7 @@ impl Build {
383384
"ui", "ui");
384385
}
385386
CheckDebuginfo { compiler } => {
386-
if target.target.contains("msvc") ||
387-
target.target.contains("android") {
387+
if target.target.contains("msvc") {
388388
// nothing to do
389389
} else if target.target.contains("apple") {
390390
check::compiletest(self, &compiler, target.target,
@@ -434,8 +434,14 @@ impl Build {
434434
target.target);
435435
}
436436

437+
AndroidCopyLibs { compiler } => {
438+
check::android_copy_libs(self, &compiler, target.target);
439+
}
440+
441+
// pseudo-steps
437442
Dist { .. } |
438-
Doc { .. } | // pseudo-steps
443+
Doc { .. } |
444+
CheckTarget { .. } |
439445
Check { .. } => {}
440446
}
441447
}

src/bootstrap/build/native.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ pub fn llvm(build: &Build, target: &str) {
4949
return
5050
}
5151

52+
println!("Building LLVM for {}", target);
53+
5254
let _ = fs::remove_dir_all(&dst.join("build"));
5355
t!(fs::create_dir_all(&dst.join("build")));
5456
let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
@@ -167,8 +169,10 @@ pub fn compiler_rt(build: &Build, target: &str) {
167169
"arm" if target.contains("eabihf") => "armhf",
168170
_ => arch,
169171
};
170-
let target = format!("clang_rt.builtins-{}{}", builtins_arch, os_extra);
171-
("linux".to_string(), target.clone(), target)
172+
let target = format!("clang_rt.builtins-{}", builtins_arch);
173+
("linux".to_string(),
174+
target.clone(),
175+
format!("{}{}", target, os_extra))
172176
} else if target.contains("apple-darwin") {
173177
let builtins_arch = match arch {
174178
"i686" => "i386",

src/bootstrap/build/sanity.rs

+4
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
139139
");
140140
}
141141
}
142+
143+
if target.contains("arm-linux-android") {
144+
need_cmd("adb".as_ref());
145+
}
142146
}
143147

144148
for host in build.flags.host.iter() {

0 commit comments

Comments
 (0)