blob: 1ee33c1f4657c29c2d4a4f4169bcf7b14ce087b7 [file] [log] [blame]
Alex Crichtondefd1b32016-03-08 07:15:551// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
Alex Crichton0e272de2016-11-16 20:31:1911//! Implementation of the test-related targets of the build system.
Alex Crichtonf72bfe62016-05-02 22:16:1512//!
13//! This file implements the various regression test suites that we execute on
14//! our CI.
15
Alex Crichtona270b802016-10-21 20:18:0916use std::collections::HashSet;
Alex Crichtonbb9062a2016-04-29 21:23:1517use std::env;
Mark Simulacrum5b44cbc2017-06-26 16:23:5018use std::iter;
Ulrik Sverdrupb1566ba2016-11-25 21:13:5919use std::fmt;
Mark Simulacrumdd1d75e2017-06-04 23:55:5020use std::fs::{self, File};
Alex Crichtonede89442016-04-15 01:00:3521use std::path::{PathBuf, Path};
22use std::process::Command;
Mark Simulacrumdd1d75e2017-06-04 23:55:5023use std::io::Read;
Alex Crichton73c2d2a2016-04-14 21:27:5124
Mark Simulacrum5b44cbc2017-06-26 16:23:5025use build_helper::{self, output};
Alex Crichton126e09e2016-04-14 22:51:0326
Alex Crichton48a07bf2016-07-06 04:58:2027use {Build, Compiler, Mode};
Alex Crichtond38db822016-12-09 01:13:5528use dist;
Alex Crichton1747ce22017-01-28 21:38:0629use util::{self, dylib_path, dylib_path_var, exe};
Alex Crichton39a5d3f2016-06-28 20:31:3030
Mark Simulacrum5b44cbc2017-06-26 16:23:5031const ADB_TEST_DIR: &str = "/data/tmp/work";
Alex Crichtondefd1b32016-03-08 07:15:5532
Ulrik Sverdrupb1566ba2016-11-25 21:13:5933/// The two modes of the test runner; tests or benchmarks.
34#[derive(Copy, Clone)]
35pub enum TestKind {
36 /// Run `cargo test`
37 Test,
38 /// Run `cargo bench`
39 Bench,
40}
41
42impl TestKind {
43 // Return the cargo subcommand for this test kind
44 fn subcommand(self) -> &'static str {
45 match self {
46 TestKind::Test => "test",
47 TestKind::Bench => "bench",
48 }
49 }
50}
51
52impl fmt::Display for TestKind {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 f.write_str(match *self {
55 TestKind::Test => "Testing",
56 TestKind::Bench => "Benchmarking",
57 })
58 }
59}
60
Josh Stone617aea42017-06-02 16:27:4461fn try_run(build: &Build, cmd: &mut Command) {
Mark Simulacrum4dc8fe92017-06-27 19:37:2462 if !build.fail_fast {
Josh Stone617aea42017-06-02 16:27:4463 if !build.try_run(cmd) {
64 let failures = build.delayed_failures.get();
65 build.delayed_failures.set(failures + 1);
66 }
67 } else {
68 build.run(cmd);
69 }
70}
71
72fn try_run_quiet(build: &Build, cmd: &mut Command) {
Mark Simulacrum4dc8fe92017-06-27 19:37:2473 if !build.fail_fast {
Josh Stone617aea42017-06-02 16:27:4474 if !build.try_run_quiet(cmd) {
75 let failures = build.delayed_failures.get();
76 build.delayed_failures.set(failures + 1);
77 }
78 } else {
79 build.run_quiet(cmd);
80 }
81}
82
Alex Crichtonf72bfe62016-05-02 22:16:1583/// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
84///
85/// This tool in `src/tools` will verify the validity of all our links in the
86/// documentation to ensure we don't have a bunch of dead ones.
Alex Crichton254876e2016-12-28 23:01:2187pub fn linkcheck(build: &Build, host: &str) {
88 println!("Linkcheck ({})", host);
89 let compiler = Compiler::new(0, host);
Alex Crichton0e272de2016-11-16 20:31:1990
91 let _time = util::timeit();
Josh Stone617aea42017-06-02 16:27:4492 try_run(build, build.tool_cmd(&compiler, "linkchecker")
93 .arg(build.out.join(host).join("doc")));
Alex Crichtondefd1b32016-03-08 07:15:5594}
Brian Anderson3a790ac2016-03-18 20:54:3195
Alex Crichtonf72bfe62016-05-02 22:16:1596/// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler.
97///
98/// This tool in `src/tools` will check out a few Rust projects and run `cargo
99/// test` to ensure that we don't regress the test suites there.
Brian Anderson3a790ac2016-03-18 20:54:31100pub fn cargotest(build: &Build, stage: u32, host: &str) {
Mark Simulacrum5b44cbc2017-06-26 16:23:50101 let compiler = Compiler::new(stage, host);
Brian Anderson80199222016-04-06 18:03:42102
Alex Crichton73c2d2a2016-04-14 21:27:51103 // Note that this is a short, cryptic, and not scoped directory name. This
104 // is currently to minimize the length of path on Windows where we otherwise
105 // quickly run into path name limit constraints.
106 let out_dir = build.out.join("ct");
107 t!(fs::create_dir_all(&out_dir));
108
Alex Crichton0e272de2016-11-16 20:31:19109 let _time = util::timeit();
Alex Crichton254876e2016-12-28 23:01:21110 let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest"));
Mark Simulacrum5b44cbc2017-06-26 16:23:50111 build.prepare_tool_cmd(&compiler, &mut cmd);
Mark Simulacrum2cc5b082017-06-27 19:32:04112 try_run(build, cmd.arg(&build.initial_cargo)
Josh Stone617aea42017-06-02 16:27:44113 .arg(&out_dir)
Mark Simulacrum5b44cbc2017-06-26 16:23:50114 .env("RUSTC", build.compiler_path(&compiler))
115 .env("RUSTDOC", build.rustdoc(&compiler)));
Alex Crichton009f45f2017-04-18 00:24:05116}
117
118/// Runs `cargo test` for `cargo` packaged with Rust.
119pub fn cargo(build: &Build, stage: u32, host: &str) {
120 let ref compiler = Compiler::new(stage, host);
121
122 // Configure PATH to find the right rustc. NB. we have to use PATH
123 // and not RUSTC because the Cargo test suite has tests that will
124 // fail if rustc is not spelled `rustc`.
125 let path = build.sysroot(compiler).join("bin");
Mark Simulacrum5b44cbc2017-06-26 16:23:50126 let old_path = env::var_os("PATH").unwrap_or_default();
127 let newpath = env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("");
Alex Crichton009f45f2017-04-18 00:24:05128
129 let mut cargo = build.cargo(compiler, Mode::Tool, host, "test");
Alex Crichton5daf5572017-04-20 21:32:54130 cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml"));
Mark Simulacrum4dc8fe92017-06-27 19:37:24131 if !build.fail_fast {
Josh Stone617aea42017-06-02 16:27:44132 cargo.arg("--no-fail-fast");
133 }
Alex Crichton009f45f2017-04-18 00:24:05134
135 // Don't build tests dynamically, just a pain to work with
136 cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
137
138 // Don't run cross-compile tests, we may not have cross-compiled libstd libs
139 // available.
140 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
141
Josh Stone617aea42017-06-02 16:27:44142 try_run(build, cargo.env("PATH", newpath));
Brian Anderson3a790ac2016-03-18 20:54:31143}
Alex Crichton9dd3c542016-03-29 20:14:52144
Alex Crichtonf72bfe62016-05-02 22:16:15145/// Runs the `tidy` tool as compiled in `stage` by the `host` compiler.
146///
147/// This tool in `src/tools` checks up on various bits and pieces of style and
148/// otherwise just implements a few lint-like checks that are specific to the
149/// compiler itself.
Alex Crichton254876e2016-12-28 23:01:21150pub fn tidy(build: &Build, host: &str) {
kennytme6e5dc02017-05-17 16:33:20151 let _folder = build.fold_output(|| "tidy");
Alex Crichton254876e2016-12-28 23:01:21152 println!("tidy check ({})", host);
153 let compiler = Compiler::new(0, host);
Eduard-Mihai Burtescud29f0bc2017-02-10 20:59:40154 let mut cmd = build.tool_cmd(&compiler, "tidy");
155 cmd.arg(build.src.join("src"));
156 if !build.config.vendor {
157 cmd.arg("--no-vendor");
158 }
kennytm6ac07872017-05-21 20:27:47159 if build.config.quiet_tests {
160 cmd.arg("--quiet");
161 }
Josh Stone617aea42017-06-02 16:27:44162 try_run(build, &mut cmd);
Alex Crichton9dd3c542016-03-29 20:14:52163}
Alex Crichtonb325baf2016-04-05 18:34:23164
165fn testdir(build: &Build, host: &str) -> PathBuf {
166 build.out.join(host).join("test")
167}
168
Alex Crichtonf72bfe62016-05-02 22:16:15169/// Executes the `compiletest` tool to run a suite of tests.
170///
171/// Compiles all tests with `compiler` for `target` with the specified
172/// compiletest `mode` and `suite` arguments. For example `mode` can be
173/// "run-pass" or `suite` can be something like `debuginfo`.
Alex Crichtonb325baf2016-04-05 18:34:23174pub fn compiletest(build: &Build,
175 compiler: &Compiler,
176 target: &str,
177 mode: &str,
178 suite: &str) {
kennytme6e5dc02017-05-17 16:33:20179 let _folder = build.fold_output(|| format!("test_{}", suite));
Alex Crichton0e272de2016-11-16 20:31:19180 println!("Check compiletest suite={} mode={} ({} -> {})",
181 suite, mode, compiler.host, target);
Alex Crichton254876e2016-12-28 23:01:21182 let mut cmd = Command::new(build.tool(&Compiler::new(0, compiler.host),
183 "compiletest"));
184 build.prepare_tool_cmd(compiler, &mut cmd);
Alex Crichtonb325baf2016-04-05 18:34:23185
Alex Crichtonf72bfe62016-05-02 22:16:15186 // compiletest currently has... a lot of arguments, so let's just pass all
187 // of them!
188
Alex Crichtonb325baf2016-04-05 18:34:23189 cmd.arg("--compile-lib-path").arg(build.rustc_libdir(compiler));
190 cmd.arg("--run-lib-path").arg(build.sysroot_libdir(compiler, target));
191 cmd.arg("--rustc-path").arg(build.compiler_path(compiler));
192 cmd.arg("--rustdoc-path").arg(build.rustdoc(compiler));
193 cmd.arg("--src-base").arg(build.src.join("src/test").join(suite));
Alex Crichtonb325baf2016-04-05 18:34:23194 cmd.arg("--build-base").arg(testdir(build, compiler.host).join(suite));
195 cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
196 cmd.arg("--mode").arg(mode);
197 cmd.arg("--target").arg(target);
198 cmd.arg("--host").arg(compiler.host);
199 cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build));
200
Mark Simulacrum5b44cbc2017-06-26 16:23:50201 if let Some(ref nodejs) = build.config.nodejs {
Brian Anderson8401e372016-09-15 19:42:26202 cmd.arg("--nodejs").arg(nodejs);
203 }
204
Alex Crichton39a5d3f2016-06-28 20:31:30205 let mut flags = vec!["-Crpath".to_string()];
Alex Crichtonf4e4ec72016-05-13 22:26:41206 if build.config.rust_optimize_tests {
Alex Crichton39a5d3f2016-06-28 20:31:30207 flags.push("-O".to_string());
Alex Crichtonf4e4ec72016-05-13 22:26:41208 }
209 if build.config.rust_debuginfo_tests {
Alex Crichton39a5d3f2016-06-28 20:31:30210 flags.push("-g".to_string());
Alex Crichtonf4e4ec72016-05-13 22:26:41211 }
212
Alex Crichton39a5d3f2016-06-28 20:31:30213 let mut hostflags = build.rustc_flags(&compiler.host);
214 hostflags.extend(flags.clone());
215 cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
Alex Crichtonf4e4ec72016-05-13 22:26:41216
Alex Crichton39a5d3f2016-06-28 20:31:30217 let mut targetflags = build.rustc_flags(&target);
218 targetflags.extend(flags);
219 targetflags.push(format!("-Lnative={}",
220 build.test_helpers_out(target).display()));
221 cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
Alex Crichtoncbe62922016-04-19 16:44:19222
Alex Crichton5f6261382016-11-14 16:04:39223 cmd.arg("--docck-python").arg(build.python());
Alex Crichtoncbe62922016-04-19 16:44:19224
225 if build.config.build.ends_with("apple-darwin") {
Corey Farwell97a1b6a2017-03-12 18:13:35226 // Force /usr/bin/python on macOS for LLDB tests because we're loading the
Alex Crichtoncbe62922016-04-19 16:44:19227 // LLDB plugin's compiled module which only works with the system python
228 // (namely not Homebrew-installed python)
229 cmd.arg("--lldb-python").arg("/usr/bin/python");
230 } else {
Alex Crichton5f6261382016-11-14 16:04:39231 cmd.arg("--lldb-python").arg(build.python());
Alex Crichtoncbe62922016-04-19 16:44:19232 }
Alex Crichtonb325baf2016-04-05 18:34:23233
Tim Neumanndce46002016-10-29 18:11:53234 if let Some(ref gdb) = build.config.gdb {
235 cmd.arg("--gdb").arg(gdb);
Alex Crichtonb325baf2016-04-05 18:34:23236 }
237 if let Some(ref vers) = build.lldb_version {
238 cmd.arg("--lldb-version").arg(vers);
239 }
240 if let Some(ref dir) = build.lldb_python_dir {
241 cmd.arg("--lldb-python-dir").arg(dir);
242 }
Alex Crichton96283fc2016-09-01 17:52:44243 let llvm_config = build.llvm_config(target);
244 let llvm_version = output(Command::new(&llvm_config).arg("--version"));
245 cmd.arg("--llvm-version").arg(llvm_version);
Simonas Kazlauskas406eddf2017-06-08 14:18:05246 if !build.is_rust_llvm(target) {
247 cmd.arg("--system-llvm");
248 }
Alex Crichtonb325baf2016-04-05 18:34:23249
Alex Crichtona270b802016-10-21 20:18:09250 cmd.args(&build.flags.cmd.test_args());
Alex Crichtonb325baf2016-04-05 18:34:23251
Niko Matsakis83453bc2016-11-16 23:02:56252 if build.config.verbose() || build.flags.verbose() {
Alex Crichtonb325baf2016-04-05 18:34:23253 cmd.arg("--verbose");
254 }
255
Corey Farwellc8c6d2c2016-10-30 01:58:52256 if build.config.quiet_tests {
257 cmd.arg("--quiet");
258 }
259
Alex Crichtonf72bfe62016-05-02 22:16:15260 // Only pass correct values for these flags for the `run-make` suite as it
261 // requires that a C++ compiler was configured which isn't always the case.
Alex Crichton126e09e2016-04-14 22:51:03262 if suite == "run-make" {
Alex Crichton126e09e2016-04-14 22:51:03263 let llvm_components = output(Command::new(&llvm_config).arg("--components"));
264 let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
265 cmd.arg("--cc").arg(build.cc(target))
Ian Douglas Scottf98ffb52017-06-22 18:51:32266 .arg("--cxx").arg(build.cxx(target).unwrap())
Alex Crichton126e09e2016-04-14 22:51:03267 .arg("--cflags").arg(build.cflags(target).join(" "))
268 .arg("--llvm-components").arg(llvm_components.trim())
269 .arg("--llvm-cxxflags").arg(llvm_cxxflags.trim());
270 } else {
271 cmd.arg("--cc").arg("")
272 .arg("--cxx").arg("")
273 .arg("--cflags").arg("")
274 .arg("--llvm-components").arg("")
275 .arg("--llvm-cxxflags").arg("");
276 }
277
Alex Crichton7bc2cbf2017-04-26 15:52:19278 if build.remote_tested(target) {
279 cmd.arg("--remote-test-client")
Alex Crichton1747ce22017-01-28 21:38:06280 .arg(build.tool(&Compiler::new(0, &build.config.build),
Alex Crichton7bc2cbf2017-04-26 15:52:19281 "remote-test-client"));
Alex Crichton1747ce22017-01-28 21:38:06282 }
283
Alex Crichton126e09e2016-04-14 22:51:03284 // Running a C compiler on MSVC requires a few env vars to be set, to be
285 // sure to set them here.
Alex Crichton0e272de2016-11-16 20:31:19286 //
287 // Note that if we encounter `PATH` we make sure to append to our own `PATH`
288 // rather than stomp over it.
Alex Crichton126e09e2016-04-14 22:51:03289 if target.contains("msvc") {
290 for &(ref k, ref v) in build.cc[target].0.env() {
291 if k != "PATH" {
292 cmd.env(k, v);
293 }
294 }
295 }
Alex Crichton21866602016-11-16 17:19:02296 cmd.env("RUSTC_BOOTSTRAP", "1");
Alex Crichton0e272de2016-11-16 20:31:19297 build.add_rust_test_threads(&mut cmd);
Alex Crichton126e09e2016-04-14 22:51:03298
Jorge Aparicio775a9362017-02-03 23:58:47299 if build.config.sanitizers {
300 cmd.env("SANITIZER_SUPPORT", "1");
301 }
302
whitequark42754ce2017-02-13 09:57:50303 if build.config.profiler {
304 cmd.env("PROFILER_SUPPORT", "1");
305 }
306
Alex Crichton39a5d3f2016-06-28 20:31:30307 cmd.arg("--adb-path").arg("adb");
308 cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
309 if target.contains("android") {
310 // Assume that cc for this target comes from the android sysroot
311 cmd.arg("--android-cross-path")
312 .arg(build.cc(target).parent().unwrap().parent().unwrap());
313 } else {
314 cmd.arg("--android-cross-path").arg("");
315 }
316
kennytme6e5dc02017-05-17 16:33:20317 build.ci_env.force_coloring_in_ci(&mut cmd);
318
Alex Crichton0e272de2016-11-16 20:31:19319 let _time = util::timeit();
Josh Stone617aea42017-06-02 16:27:44320 try_run(build, &mut cmd);
Alex Crichtonb325baf2016-04-05 18:34:23321}
Alex Crichtonede89442016-04-15 01:00:35322
Alex Crichtonf72bfe62016-05-02 22:16:15323/// Run `rustdoc --test` for all documentation in `src/doc`.
324///
325/// This will run all tests in our markdown documentation (e.g. the book)
326/// located in `src/doc`. The `rustdoc` that's run is the one that sits next to
327/// `compiler`.
Alex Crichtonede89442016-04-15 01:00:35328pub fn docs(build: &Build, compiler: &Compiler) {
Alex Crichtonf72bfe62016-05-02 22:16:15329 // Do a breadth-first traversal of the `src/doc` directory and just run
330 // tests for all files that end in `*.md`
Alex Crichtonede89442016-04-15 01:00:35331 let mut stack = vec![build.src.join("src/doc")];
Alex Crichton0e272de2016-11-16 20:31:19332 let _time = util::timeit();
kennytme6e5dc02017-05-17 16:33:20333 let _folder = build.fold_output(|| "test_docs");
Alex Crichtonede89442016-04-15 01:00:35334
335 while let Some(p) = stack.pop() {
336 if p.is_dir() {
Mark Simulacrumdd1d75e2017-06-04 23:55:50337 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()).filter(|p| {
338 p.extension().and_then(|s| s.to_str()) == Some("md") &&
339 // The nostarch directory in the book is for no starch, and so isn't guaranteed to
340 // build. We don't care if it doesn't build, so skip it.
341 p.to_str().map_or(true, |p| !p.contains("nostarch"))
342 }));
Alex Crichtonede89442016-04-15 01:00:35343 continue
344 }
345
Alex Crichtonede89442016-04-15 01:00:35346 markdown_test(build, compiler, &p);
347 }
348}
349
Alex Crichtonf72bfe62016-05-02 22:16:15350/// Run the error index generator tool to execute the tests located in the error
351/// index.
352///
353/// The `error_index_generator` tool lives in `src/tools` and is used to
354/// generate a markdown file from the error indexes of the code base which is
355/// then passed to `rustdoc --test`.
Alex Crichtonede89442016-04-15 01:00:35356pub fn error_index(build: &Build, compiler: &Compiler) {
kennytme6e5dc02017-05-17 16:33:20357 let _folder = build.fold_output(|| "test_error_index");
Alex Crichtonede89442016-04-15 01:00:35358 println!("Testing error-index stage{}", compiler.stage);
359
Alex Crichton860c6ab2016-11-08 17:59:46360 let dir = testdir(build, compiler.host);
361 t!(fs::create_dir_all(&dir));
362 let output = dir.join("error-index.md");
Alex Crichton0e272de2016-11-16 20:31:19363
364 let _time = util::timeit();
Alex Crichton254876e2016-12-28 23:01:21365 build.run(build.tool_cmd(&Compiler::new(0, compiler.host),
366 "error_index_generator")
Alex Crichtonede89442016-04-15 01:00:35367 .arg("markdown")
368 .arg(&output)
369 .env("CFG_BUILD", &build.config.build));
370
371 markdown_test(build, compiler, &output);
372}
373
374fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) {
Mark Simulacrumdd1d75e2017-06-04 23:55:50375 let mut file = t!(File::open(markdown));
376 let mut contents = String::new();
377 t!(file.read_to_string(&mut contents));
378 if !contents.contains("```") {
379 return;
380 }
381
Mark Simulacrumbc8fabb2017-06-06 18:00:22382 println!("doc tests for: {}", markdown.display());
Alex Crichtonede89442016-04-15 01:00:35383 let mut cmd = Command::new(build.rustdoc(compiler));
384 build.add_rustc_lib_path(compiler, &mut cmd);
Alex Crichton0e272de2016-11-16 20:31:19385 build.add_rust_test_threads(&mut cmd);
Alex Crichtonede89442016-04-15 01:00:35386 cmd.arg("--test");
387 cmd.arg(markdown);
Alex Crichton6f62fae2016-12-12 17:03:35388 cmd.env("RUSTC_BOOTSTRAP", "1");
Corey Farwellc8c6d2c2016-10-30 01:58:52389
kennytm6ac07872017-05-21 20:27:47390 let test_args = build.flags.cmd.test_args().join(" ");
Corey Farwellc8c6d2c2016-10-30 01:58:52391 cmd.arg("--test-args").arg(test_args);
392
kennytm6ac07872017-05-21 20:27:47393 if build.config.quiet_tests {
Josh Stone617aea42017-06-02 16:27:44394 try_run_quiet(build, &mut cmd);
kennytm6ac07872017-05-21 20:27:47395 } else {
Josh Stone617aea42017-06-02 16:27:44396 try_run(build, &mut cmd);
kennytm6ac07872017-05-21 20:27:47397 }
Alex Crichtonede89442016-04-15 01:00:35398}
Alex Crichtonbb9062a2016-04-29 21:23:15399
400/// Run all unit tests plus documentation tests for an entire crate DAG defined
401/// by a `Cargo.toml`
402///
403/// This is what runs tests for crates like the standard library, compiler, etc.
404/// It essentially is the driver for running `cargo test`.
405///
406/// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
Alex Crichton147e2da2016-10-07 06:30:38407/// arguments, and those arguments are discovered from `cargo metadata`.
Alex Crichtonbb9062a2016-04-29 21:23:15408pub fn krate(build: &Build,
409 compiler: &Compiler,
410 target: &str,
Alex Crichtona270b802016-10-21 20:18:09411 mode: Mode,
Ulrik Sverdrupb1566ba2016-11-25 21:13:59412 test_kind: TestKind,
Alex Crichtona270b802016-10-21 20:18:09413 krate: Option<&str>) {
Alex Crichton147e2da2016-10-07 06:30:38414 let (name, path, features, root) = match mode {
Ahmed Charles9ca382f2016-09-02 08:55:29415 Mode::Libstd => {
Alex Crichton40aaa652017-02-15 16:53:18416 ("libstd", "src/libstd", build.std_features(), "std")
Ahmed Charles9ca382f2016-09-02 08:55:29417 }
418 Mode::Libtest => {
Alex Crichton40aaa652017-02-15 16:53:18419 ("libtest", "src/libtest", String::new(), "test")
Ahmed Charles9ca382f2016-09-02 08:55:29420 }
421 Mode::Librustc => {
Alex Crichton147e2da2016-10-07 06:30:38422 ("librustc", "src/rustc", build.rustc_features(), "rustc-main")
Ahmed Charles9ca382f2016-09-02 08:55:29423 }
Alex Crichtonbb9062a2016-04-29 21:23:15424 _ => panic!("can only test libraries"),
425 };
kennytme6e5dc02017-05-17 16:33:20426 let _folder = build.fold_output(|| {
427 format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, name)
428 });
Ulrik Sverdrupb1566ba2016-11-25 21:13:59429 println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage,
Alex Crichtonbb9062a2016-04-29 21:23:15430 compiler.host, target);
431
Alex Crichton7046fea2016-12-25 23:20:33432 // If we're not doing a full bootstrap but we're testing a stage2 version of
433 // libstd, then what we're actually testing is the libstd produced in
434 // stage1. Reflect that here by updating the compiler that we're working
435 // with automatically.
436 let compiler = if build.force_use_stage1(compiler, target) {
437 Compiler::new(1, compiler.host)
438 } else {
439 compiler.clone()
440 };
441
Alex Crichtonbb9062a2016-04-29 21:23:15442 // Build up the base `cargo test` command.
Alex Crichton147e2da2016-10-07 06:30:38443 //
444 // Pass in some standard flags then iterate over the graph we've discovered
445 // in `cargo metadata` with the maps above and figure out what `-p`
446 // arguments need to get passed.
Alex Crichton7046fea2016-12-25 23:20:33447 let mut cargo = build.cargo(&compiler, mode, target, test_kind.subcommand());
Alex Crichtonbb9062a2016-04-29 21:23:15448 cargo.arg("--manifest-path")
449 .arg(build.src.join(path).join("Cargo.toml"))
450 .arg("--features").arg(features);
Mark Simulacrum4dc8fe92017-06-27 19:37:24451 if test_kind.subcommand() == "test" && !build.fail_fast {
Josh Stone617aea42017-06-02 16:27:44452 cargo.arg("--no-fail-fast");
453 }
Alex Crichtonbb9062a2016-04-29 21:23:15454
Alex Crichtona270b802016-10-21 20:18:09455 match krate {
456 Some(krate) => {
457 cargo.arg("-p").arg(krate);
Alex Crichtonbb9062a2016-04-29 21:23:15458 }
Alex Crichtona270b802016-10-21 20:18:09459 None => {
460 let mut visited = HashSet::new();
461 let mut next = vec![root];
462 while let Some(name) = next.pop() {
Alex Crichton36a926a2017-01-13 23:11:34463 // Right now jemalloc is our only target-specific crate in the
464 // sense that it's not present on all platforms. Custom skip it
465 // here for now, but if we add more this probably wants to get
466 // more generalized.
467 //
468 // Also skip `build_helper` as it's not compiled normally for
469 // target during the bootstrap and it's just meant to be a
470 // helper crate, not tested. If it leaks through then it ends up
471 // messing with various mtime calculations and such.
472 if !name.contains("jemalloc") && name != "build_helper" {
Vadim Petrochenkovb4abb722017-02-02 20:55:42473 cargo.arg("-p").arg(&format!("{}:0.0.0", name));
Alex Crichtona270b802016-10-21 20:18:09474 }
475 for dep in build.crates[name].deps.iter() {
476 if visited.insert(dep) {
477 next.push(dep);
478 }
479 }
Alex Crichtonbb9062a2016-04-29 21:23:15480 }
481 }
Alex Crichtonbb9062a2016-04-29 21:23:15482 }
483
484 // The tests are going to run with the *target* libraries, so we need to
485 // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
486 //
487 // Note that to run the compiler we need to run with the *host* libraries,
488 // but our wrapper scripts arrange for that to be the case anyway.
489 let mut dylib_path = dylib_path();
Alex Crichton7046fea2016-12-25 23:20:33490 dylib_path.insert(0, build.sysroot_libdir(&compiler, target));
Alex Crichtonbb9062a2016-04-29 21:23:15491 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
Alex Crichtonbb9062a2016-04-29 21:23:15492
Alex Crichton7bc2cbf2017-04-26 15:52:19493 if target.contains("emscripten") || build.remote_tested(target) {
Alex Crichton0e272de2016-11-16 20:31:19494 cargo.arg("--no-run");
495 }
496
497 cargo.arg("--");
498
Corey Farwellc8c6d2c2016-10-30 01:58:52499 if build.config.quiet_tests {
Corey Farwellc8c6d2c2016-10-30 01:58:52500 cargo.arg("--quiet");
501 }
502
Alex Crichton0e272de2016-11-16 20:31:19503 let _time = util::timeit();
504
Alex Crichton7bc2cbf2017-04-26 15:52:19505 if target.contains("emscripten") {
Alex Crichton0e272de2016-11-16 20:31:19506 build.run(&mut cargo);
Alex Crichton7046fea2016-12-25 23:20:33507 krate_emscripten(build, &compiler, target, mode);
Alex Crichton7bc2cbf2017-04-26 15:52:19508 } else if build.remote_tested(target) {
Alex Crichton1747ce22017-01-28 21:38:06509 build.run(&mut cargo);
Alex Crichton7bc2cbf2017-04-26 15:52:19510 krate_remote(build, &compiler, target, mode);
Alex Crichton39a5d3f2016-06-28 20:31:30511 } else {
Alex Crichtona270b802016-10-21 20:18:09512 cargo.args(&build.flags.cmd.test_args());
Josh Stone617aea42017-06-02 16:27:44513 try_run(build, &mut cargo);
Alex Crichton39a5d3f2016-06-28 20:31:30514 }
515}
516
Brian Andersonb8b50f02016-09-06 00:41:50517fn krate_emscripten(build: &Build,
518 compiler: &Compiler,
519 target: &str,
520 mode: Mode) {
Alex Crichton1747ce22017-01-28 21:38:06521 let out_dir = build.cargo_out(compiler, mode, target);
Mark Simulacrum5b44cbc2017-06-26 16:23:50522 let tests = find_tests(&out_dir.join("deps"), target);
Ross Schulmanad9184c2016-09-05 23:56:48523
Mark Simulacrum5b44cbc2017-06-26 16:23:50524 let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
Alex Crichton1747ce22017-01-28 21:38:06525 for test in tests {
Mark Simulacrum5b44cbc2017-06-26 16:23:50526 println!("running {}", test.display());
Alex Crichton1747ce22017-01-28 21:38:06527 let mut cmd = Command::new(nodejs);
Mark Simulacrum5b44cbc2017-06-26 16:23:50528 cmd.arg(&test);
Alex Crichton1747ce22017-01-28 21:38:06529 if build.config.quiet_tests {
530 cmd.arg("--quiet");
531 }
Josh Stone617aea42017-06-02 16:27:44532 try_run(build, &mut cmd);
Alex Crichton1747ce22017-01-28 21:38:06533 }
534}
535
Alex Crichton7bc2cbf2017-04-26 15:52:19536fn krate_remote(build: &Build,
537 compiler: &Compiler,
538 target: &str,
539 mode: Mode) {
Alex Crichton1747ce22017-01-28 21:38:06540 let out_dir = build.cargo_out(compiler, mode, target);
Mark Simulacrum5b44cbc2017-06-26 16:23:50541 let tests = find_tests(&out_dir.join("deps"), target);
Alex Crichton1747ce22017-01-28 21:38:06542
543 let tool = build.tool(&Compiler::new(0, &build.config.build),
Alex Crichton7bc2cbf2017-04-26 15:52:19544 "remote-test-client");
Alex Crichton1747ce22017-01-28 21:38:06545 for test in tests {
546 let mut cmd = Command::new(&tool);
547 cmd.arg("run")
548 .arg(&test);
549 if build.config.quiet_tests {
550 cmd.arg("--quiet");
551 }
552 cmd.args(&build.flags.cmd.test_args());
Josh Stone617aea42017-06-02 16:27:44553 try_run(build, &mut cmd);
Alex Crichton1747ce22017-01-28 21:38:06554 }
555}
Ross Schulmanad9184c2016-09-05 23:56:48556
Mark Simulacrum5b44cbc2017-06-26 16:23:50557fn find_tests(dir: &Path, target: &str) -> Vec<PathBuf> {
558 let mut dst = Vec::new();
Alex Crichton39a5d3f2016-06-28 20:31:30559 for e in t!(dir.read_dir()).map(|e| t!(e)) {
560 let file_type = t!(e.file_type());
561 if !file_type.is_file() {
562 continue
563 }
564 let filename = e.file_name().into_string().unwrap();
565 if (target.contains("windows") && filename.ends_with(".exe")) ||
Ross Schulmanad9184c2016-09-05 23:56:48566 (!target.contains("windows") && !filename.contains(".")) ||
Marco A L Barbosa554f21b2017-06-13 12:32:49567 (target.contains("emscripten") &&
568 filename.ends_with(".js") &&
569 !filename.ends_with(".asm.js")) {
Alex Crichton39a5d3f2016-06-28 20:31:30570 dst.push(e.path());
571 }
572 }
Mark Simulacrum5b44cbc2017-06-26 16:23:50573 dst
Alex Crichton39a5d3f2016-06-28 20:31:30574}
575
Mátyás Mustohab194def2017-04-11 10:10:05576pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
Alex Crichton7bc2cbf2017-04-26 15:52:19577 if !build.remote_tested(target) {
578 return
Alex Crichtoncf8fde12016-12-31 02:54:05579 }
580
Alex Crichton7bc2cbf2017-04-26 15:52:19581 println!("REMOTE copy libs to emulator ({})", target);
Alex Crichton1747ce22017-01-28 21:38:06582 t!(fs::create_dir_all(build.out.join("tmp")));
583
Alex Crichton1747ce22017-01-28 21:38:06584 let server = build.cargo_out(compiler, Mode::Tool, target)
Alex Crichton7bc2cbf2017-04-26 15:52:19585 .join(exe("remote-test-server", target));
Alex Crichton1747ce22017-01-28 21:38:06586
587 // Spawn the emulator and wait for it to come online
588 let tool = build.tool(&Compiler::new(0, &build.config.build),
Alex Crichton7bc2cbf2017-04-26 15:52:19589 "remote-test-client");
590 let mut cmd = Command::new(&tool);
591 cmd.arg("spawn-emulator")
592 .arg(target)
593 .arg(&server)
594 .arg(build.out.join("tmp"));
595 if let Some(rootfs) = build.qemu_rootfs(target) {
596 cmd.arg(rootfs);
597 }
598 build.run(&mut cmd);
Alex Crichton1747ce22017-01-28 21:38:06599
600 // Push all our dylibs to the emulator
601 for f in t!(build.sysroot_libdir(compiler, target).read_dir()) {
602 let f = t!(f);
603 let name = f.file_name().into_string().unwrap();
604 if util::is_dylib(&name) {
605 build.run(Command::new(&tool)
606 .arg("push")
607 .arg(f.path()));
608 }
609 }
610}
611
Alex Crichtond38db822016-12-09 01:13:55612/// Run "distcheck", a 'make check' from a tarball
613pub fn distcheck(build: &Build) {
614 if build.config.build != "x86_64-unknown-linux-gnu" {
615 return
616 }
617 if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") {
618 return
619 }
620 if !build.config.target.iter().any(|s| s == "x86_64-unknown-linux-gnu") {
621 return
622 }
623
Josh Stonec5cd4cb2017-04-26 19:37:12624 println!("Distcheck");
Alex Crichtond38db822016-12-09 01:13:55625 let dir = build.out.join("tmp").join("distcheck");
626 let _ = fs::remove_dir_all(&dir);
627 t!(fs::create_dir_all(&dir));
628
629 let mut cmd = Command::new("tar");
630 cmd.arg("-xzf")
631 .arg(dist::rust_src_location(build))
632 .arg("--strip-components=1")
633 .current_dir(&dir);
634 build.run(&mut cmd);
635 build.run(Command::new("./configure")
Alex Crichton4781eb32016-12-30 17:26:25636 .args(&build.config.configure_args)
Eduard-Mihai Burtescud29f0bc2017-02-10 20:59:40637 .arg("--enable-vendor")
Alex Crichtond38db822016-12-09 01:13:55638 .current_dir(&dir));
Sébastien Mariea7d90252016-12-17 19:09:23639 build.run(Command::new(build_helper::make(&build.config.build))
Alex Crichtond38db822016-12-09 01:13:55640 .arg("check")
641 .current_dir(&dir));
Josh Stonec5cd4cb2017-04-26 19:37:12642
643 // Now make sure that rust-src has all of libstd's dependencies
644 println!("Distcheck rust-src");
645 let dir = build.out.join("tmp").join("distcheck-src");
646 let _ = fs::remove_dir_all(&dir);
647 t!(fs::create_dir_all(&dir));
648
649 let mut cmd = Command::new("tar");
650 cmd.arg("-xzf")
651 .arg(dist::rust_src_installer(build))
652 .arg("--strip-components=1")
653 .current_dir(&dir);
654 build.run(&mut cmd);
655
656 let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml");
Mark Simulacrum2cc5b082017-06-27 19:32:04657 build.run(Command::new(&build.initial_cargo)
Josh Stonec5cd4cb2017-04-26 19:37:12658 .arg("generate-lockfile")
659 .arg("--manifest-path")
660 .arg(&toml)
661 .current_dir(&dir));
Alex Crichtond38db822016-12-09 01:13:55662}
Alex Crichton1a040b32016-12-31 03:50:57663
664/// Test the build system itself
665pub fn bootstrap(build: &Build) {
Mark Simulacrum2cc5b082017-06-27 19:32:04666 let mut cmd = Command::new(&build.initial_cargo);
Alex Crichton1a040b32016-12-31 03:50:57667 cmd.arg("test")
668 .current_dir(build.src.join("src/bootstrap"))
669 .env("CARGO_TARGET_DIR", build.out.join("bootstrap"))
Alex Crichtonbe7ebdd2017-06-07 02:32:43670 .env("RUSTC_BOOTSTRAP", "1")
Mark Simulacrum2cc5b082017-06-27 19:32:04671 .env("RUSTC", &build.initial_rustc);
Mark Simulacrum4dc8fe92017-06-27 19:37:24672 if !build.fail_fast {
Josh Stone617aea42017-06-02 16:27:44673 cmd.arg("--no-fail-fast");
674 }
Alex Crichton1a040b32016-12-31 03:50:57675 cmd.arg("--").args(&build.flags.cmd.test_args());
Josh Stone617aea42017-06-02 16:27:44676 try_run(build, &mut cmd);
Alex Crichton1a040b32016-12-31 03:50:57677}