diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 384ae3f45f60c..20239e974788b 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -39,7 +39,6 @@ use util::logv; use self::header::EarlyProps; -pub mod procsrv; pub mod util; mod json; pub mod header; diff --git a/src/tools/compiletest/src/procsrv.rs b/src/tools/compiletest/src/procsrv.rs deleted file mode 100644 index ffcc60e785292..0000000000000 --- a/src/tools/compiletest/src/procsrv.rs +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::env; -use std::ffi::OsString; -use std::io::prelude::*; -use std::io; -use std::path::PathBuf; -use std::process::{Child, Command, ExitStatus, Output, Stdio}; - -/// Get the name of the environment variable that holds dynamic library -/// locations -pub fn dylib_env_var() -> &'static str { - if cfg!(windows) { - "PATH" - } else if cfg!(target_os = "macos") { - "DYLD_LIBRARY_PATH" - } else if cfg!(target_os = "haiku") { - "LIBRARY_PATH" - } else { - "LD_LIBRARY_PATH" - } -} - -/// Add `lib_path` and `aux_path` (if it is `Some`) to the dynamic library -/// env var -fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) { - // Need to be sure to put both the lib_path and the aux path in the dylib - // search path for the child. - let var = dylib_env_var(); - let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new())) - .collect::>(); - if let Some(p) = aux_path { - path.insert(0, PathBuf::from(p)) - } - path.insert(0, PathBuf::from(lib_path)); - - // Add the new dylib search path var - let newpath = env::join_paths(&path).unwrap(); - cmd.env(var, newpath); -} - -/// Represents exit status, stdout and stderr of a completed process -pub struct Result { - pub status: ExitStatus, - pub out: String, - pub err: String, -} - -/// Runs a test program -/// -/// # Params -/// - `lib_path` Path to search for required library -/// - `prog` command to run -/// - `aux_path` Optional extra path to search for required -/// auxiliary libraries -/// - `args` List of arguments to pass to `prog` -/// - `env` List of environment variables to set, `.0` is variable name, -/// `.1` is value -/// - `input` String to be fed as stdin -/// - `current_dir` Optional working dir to run command in -/// -pub fn run(lib_path: &str, - prog: &str, - aux_path: Option<&str>, - args: &[String], - env: Vec<(String, String)>, - input: Option, - current_dir: Option) - -> io::Result { - - let mut cmd = Command::new(prog); - cmd.args(args) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .stdin(Stdio::piped()); - - add_target_env(&mut cmd, lib_path, aux_path); - for (key, val) in env { - cmd.env(&key, &val); - } - if let Some(cwd) = current_dir { - cmd.current_dir(cwd); - } - - let mut process = cmd.spawn()?; - if let Some(input) = input { - process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); - } - let Output { status, stdout, stderr } = process.wait_with_output().unwrap(); - - Ok(Result { - status, - out: String::from_utf8(stdout).unwrap(), - err: String::from_utf8(stderr).unwrap(), - }) -} - -/// Same as `run`, but return process rather than waiting on completion -pub fn run_background(lib_path: &str, - prog: &str, - aux_path: Option<&str>, - args: &[String], - env: Vec<(String, String)>, - input: Option, - current_dir: Option) - -> io::Result { - - let mut cmd = Command::new(prog); - cmd.args(args) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()); - add_target_env(&mut cmd, lib_path, aux_path); - for (key, val) in env { - cmd.env(&key, &val); - } - if let Some(cwd) = current_dir { - cmd.current_dir(cwd); - } - - let mut process = cmd.spawn()?; - if let Some(input) = input { - process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); - } - - Ok(process) -} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 02511ac6d98bc..d2a0c776b33e6 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -17,22 +17,35 @@ use errors::{self, ErrorKind, Error}; use filetime::FileTime; use json; use header::TestProps; -use procsrv; use test::TestPaths; use util::logv; +use std::collections::HashMap; use std::collections::HashSet; use std::env; +use std::ffi::OsString; use std::fs::{self, File, create_dir_all}; use std::io::prelude::*; use std::io::{self, BufReader}; use std::path::{Path, PathBuf}; -use std::process::{Command, Output, ExitStatus}; +use std::process::{Command, Output, ExitStatus, Stdio}; use std::str; -use std::collections::HashMap; use extract_gdb_version; +/// The name of the environment variable that holds dynamic library locations. +pub fn dylib_env_var() -> &'static str { + if cfg!(windows) { + "PATH" + } else if cfg!(target_os = "macos") { + "DYLD_LIBRARY_PATH" + } else if cfg!(target_os = "haiku") { + "LIBRARY_PATH" + } else { + "LD_LIBRARY_PATH" + } +} + pub fn run(config: Config, testpaths: &TestPaths) { match &*config.target { @@ -325,37 +338,23 @@ impl<'test> TestCx<'test> { } } - fn print_source(&self, - src: String, - pretty_type: &str) - -> ProcRes { + fn print_source(&self, src: String, pretty_type: &str) -> ProcRes { let aux_dir = self.aux_output_dir_name(); - self.compose_and_run(self.make_pp_args(pretty_type.to_owned()), - self.props.exec_env.clone(), + + let mut rustc = Command::new(&self.config.rustc_path); + rustc.arg("-") + .arg("-Zunstable-options") + .args(&["--unpretty", &pretty_type]) + .args(&["--target", &self.config.target]) + .arg("-L").arg(&aux_dir) + .args(self.split_maybe_args(&self.config.target_rustcflags)) + .args(&self.props.compile_flags) + .envs(self.props.exec_env.clone()); + + self.compose_and_run(rustc, self.config.compile_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), - Some(src), - None) - } - - fn make_pp_args(&self, - pretty_type: String) - -> ProcArgs { - let aux_dir = self.aux_output_dir_name(); - // FIXME (#9639): This needs to handle non-utf8 paths - let mut args = vec!["-".to_owned(), - "-Zunstable-options".to_owned(), - "--unpretty".to_owned(), - pretty_type, - format!("--target={}", self.config.target), - "-L".to_owned(), - aux_dir.to_str().unwrap().to_owned()]; - args.extend(self.split_maybe_args(&self.config.target_rustcflags)); - args.extend(self.props.compile_flags.iter().cloned()); - ProcArgs { - prog: self.config.rustc_path.to_str().unwrap().to_owned(), - args, - } + Some(src)) } fn compare_source(&self, @@ -379,45 +378,35 @@ actual:\n\ } fn typecheck_source(&self, src: String) -> ProcRes { - let args = self.make_typecheck_args(); - self.compose_and_run_compiler(args, Some(src)) - } + let mut rustc = Command::new(&self.config.rustc_path); + + let out_dir = self.output_base_name().with_extension("pretty-out"); + let _ = fs::remove_dir_all(&out_dir); + create_dir_all(&out_dir).unwrap(); - fn make_typecheck_args(&self) -> ProcArgs { - let aux_dir = self.aux_output_dir_name(); let target = if self.props.force_host { &*self.config.host } else { &*self.config.target }; - let out_dir = self.output_base_name().with_extension("pretty-out"); - let _ = fs::remove_dir_all(&out_dir); - create_dir_all(&out_dir).unwrap(); + let aux_dir = self.aux_output_dir_name(); + + rustc.arg("-") + .arg("-Zno-trans") + .arg("--out-dir").arg(&out_dir) + .arg(&format!("--target={}", target)) + .arg("-L").arg(&self.config.build_base) + .arg("-L").arg(aux_dir); - // FIXME (#9639): This needs to handle non-utf8 paths - let mut args = vec!["-".to_owned(), - "-Zno-trans".to_owned(), - "--out-dir".to_owned(), - out_dir.to_str().unwrap().to_owned(), - format!("--target={}", target), - "-L".to_owned(), - self.config.build_base.to_str().unwrap().to_owned(), - "-L".to_owned(), - aux_dir.to_str().unwrap().to_owned()]; if let Some(revision) = self.revision { - args.extend(vec![ - "--cfg".to_string(), - revision.to_string(), - ]); - } - args.extend(self.split_maybe_args(&self.config.target_rustcflags)); - args.extend(self.props.compile_flags.iter().cloned()); - // FIXME (#9639): This needs to handle non-utf8 paths - ProcArgs { - prog: self.config.rustc_path.to_str().unwrap().to_owned(), - args, + rustc.args(&["--cfg", revision]); } + + rustc.args(self.split_maybe_args(&self.config.target_rustcflags)); + rustc.args(&self.props.compile_flags); + + self.compose_and_run_compiler(rustc, Some(src)) } fn run_debuginfo_gdb_test(&self) { @@ -500,32 +489,19 @@ actual:\n\ debug!("script_str = {}", script_str); self.dump_output_file(&script_str, "debugger.script"); + let adb_path = &self.config.adb_path; - procsrv::run("", - &self.config.adb_path, - None, - &[ - "push".to_owned(), - exe_file.to_str().unwrap().to_owned(), - self.config.adb_test_dir.clone() - ], - Vec::new(), - None, - None) - .expect(&format!("failed to exec `{:?}`", self.config.adb_path)); - - procsrv::run("", - &self.config.adb_path, - None, - &[ - "forward".to_owned(), - "tcp:5039".to_owned(), - "tcp:5039".to_owned() - ], - Vec::new(), - None, - None) - .expect(&format!("failed to exec `{:?}`", self.config.adb_path)); + Command::new(adb_path) + .arg("push") + .arg(&exe_file) + .arg(&self.config.adb_test_dir) + .status() + .expect(&format!("failed to exec `{:?}`", adb_path)); + + Command::new(adb_path) + .args(&["forward", "tcp:5039", "tcp:5039"]) + .status() + .expect(&format!("failed to exec `{:?}`", adb_path)); let adb_arg = format!("export LD_LIBRARY_PATH={}; \ gdbserver{} :5039 {}/{}", @@ -537,23 +513,17 @@ actual:\n\ .unwrap()); debug!("adb arg: {}", adb_arg); - let mut process = procsrv::run_background("", - &self.config.adb_path - , - None, - &[ - "shell".to_owned(), - adb_arg.clone() - ], - Vec::new(), - None, - None) - .expect(&format!("failed to exec `{:?}`", self.config.adb_path)); + let mut adb = Command::new(adb_path) + .args(&["shell", &adb_arg]) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .spawn() + .expect(&format!("failed to exec `{:?}`", adb_path)); // Wait for the gdbserver to print out "Listening on port ..." // at which point we know that it's started and then we can // execute the debugger below. - let mut stdout = BufReader::new(process.stdout.take().unwrap()); + let mut stdout = BufReader::new(adb.stdout.take().unwrap()); let mut line = String::new(); loop { line.truncate(0); @@ -574,33 +544,29 @@ actual:\n\ let mut gdb_path = tool_path; gdb_path.push_str("/bin/gdb"); - let procsrv::Result { - out, - err, - status - } = procsrv::run("", - &gdb_path, - None, - &debugger_opts, - Vec::new(), - None, - None) + let Output { + status, + stdout, + stderr + } = Command::new(&gdb_path) + .args(&debugger_opts) + .output() .expect(&format!("failed to exec `{:?}`", gdb_path)); let cmdline = { - let cmdline = self.make_cmdline("", - &format!("{}-gdb", self.config.target), - &debugger_opts); + let mut gdb = Command::new(&format!("{}-gdb", self.config.target)); + gdb.args(&debugger_opts); + let cmdline = self.make_cmdline(&gdb, ""); logv(self.config, format!("executing {}", cmdline)); cmdline }; debugger_run_result = ProcRes { status, - stdout: out, - stderr: err, + stdout: String::from_utf8(stdout).unwrap(), + stderr: String::from_utf8(stderr).unwrap(), cmdline, }; - if process.kill().is_err() { + if adb.kill().is_err() { println!("Adb process is already finished."); } } @@ -679,19 +645,14 @@ actual:\n\ "-nx".to_owned(), format!("-command={}", debugger_script.to_str().unwrap())]; - let proc_args = ProcArgs { - prog: self.config.gdb.as_ref().unwrap().to_owned(), - args: debugger_opts, - }; - - let environment = vec![("PYTHONPATH".to_owned(), rust_pp_module_abs_path)]; + let mut gdb = Command::new(self.config.gdb.as_ref().unwrap()); + gdb.args(&debugger_opts) + .env("PYTHONPATH", rust_pp_module_abs_path); debugger_run_result = - self.compose_and_run(proc_args, - environment, + self.compose_and_run(gdb, self.config.run_lib_path.to_str().unwrap(), None, - None, None); } } @@ -1154,10 +1115,11 @@ actual:\n\ } fn compile_test(&self) -> ProcRes { - let aux_dir = self.aux_output_dir_name(); - // FIXME (#9639): This needs to handle non-utf8 paths - let mut extra_args = vec!["-L".to_owned(), - aux_dir.to_str().unwrap().to_owned()]; + let mut rustc = self.make_compile_args( + &self.testpaths.file, TargetLocation::ThisFile(self.make_exe_name())); + + rustc.arg("-L").arg(&self.aux_output_dir_name()); + match self.config.mode { CompileFail | Ui => { // compile-fail and ui tests tend to have tons of unused code as @@ -1165,15 +1127,12 @@ actual:\n\ // want to actually assert warnings about all this code. Instead // let's just ignore unused code warnings by defaults and tests // can turn it back on if needed. - extra_args.push("-A".to_owned()); - extra_args.push("unused".to_owned()); + rustc.args(&["-A", "unused"]); } _ => {} } - let args = self.make_compile_args(extra_args, - &self.testpaths.file, - TargetLocation::ThisFile(self.make_exe_name())); - self.compose_and_run_compiler(args, None) + + self.compose_and_run_compiler(rustc, None) } fn document(&self, out_dir: &Path) -> ProcRes { @@ -1197,22 +1156,20 @@ actual:\n\ } let aux_dir = self.aux_output_dir_name(); - let mut args = vec!["-L".to_owned(), - aux_dir.to_str().unwrap().to_owned(), - "-o".to_owned(), - out_dir.to_str().unwrap().to_owned(), - self.testpaths.file.to_str().unwrap().to_owned()]; - args.extend(self.props.compile_flags.iter().cloned()); - let args = ProcArgs { - prog: self.config.rustdoc_path - .as_ref().expect("--rustdoc-path passed").to_str().unwrap().to_owned(), - args, - }; - self.compose_and_run_compiler(args, None) + + let rustdoc_path = self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed"); + let mut rustdoc = Command::new(rustdoc_path); + + rustdoc.arg("-L").arg(aux_dir) + .arg("-o").arg(out_dir) + .arg(&self.testpaths.file) + .args(&self.props.compile_flags); + + self.compose_and_run_compiler(rustdoc, None) } fn exec_compiled_test(&self) -> ProcRes { - let env = self.props.exec_env.clone(); + let env = &self.props.exec_env; match &*self.config.target { // This is pretty similar to below, we're transforming: @@ -1230,41 +1187,39 @@ actual:\n\ // the process) and then report back the same result. _ if self.config.remote_test_client.is_some() => { let aux_dir = self.aux_output_dir_name(); - let mut args = self.make_run_args(); - let mut program = args.prog.clone(); + let ProcArgs { mut prog, args } = self.make_run_args(); if let Ok(entries) = aux_dir.read_dir() { for entry in entries { let entry = entry.unwrap(); if !entry.path().is_file() { continue } - program.push_str(":"); - program.push_str(entry.path().to_str().unwrap()); + prog.push_str(":"); + prog.push_str(entry.path().to_str().unwrap()); } } - args.args.insert(0, program); - args.args.insert(0, "run".to_string()); - args.prog = self.config.remote_test_client.clone().unwrap() - .into_os_string().into_string().unwrap(); - self.compose_and_run(args, - env, + let mut test_client = Command::new( + self.config.remote_test_client.as_ref().unwrap()); + test_client + .args(&["run", &prog]) + .args(args) + .envs(env.clone()); + self.compose_and_run(test_client, self.config.run_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), - None, None) } _ => { let aux_dir = self.aux_output_dir_name(); - let working_dir = - Some(self.output_base_name() - .parent().unwrap() - .to_str().unwrap().to_owned()); - self.compose_and_run(self.make_run_args(), - env, + let ProcArgs { prog, args } = self.make_run_args(); + let mut program = Command::new(&prog); + program.args(args) + .current_dir(&self.output_base_name().parent().unwrap()) + .envs(env.clone()); + self.compose_and_run(program, self.config.run_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), - None, - working_dir) + None) } } } @@ -1293,23 +1248,33 @@ actual:\n\ } } - fn compose_and_run_compiler(&self, args: ProcArgs, input: Option) -> ProcRes { + fn compose_and_run_compiler(&self, mut rustc: Command, input: Option) -> ProcRes { if !self.props.aux_builds.is_empty() { create_dir_all(&self.aux_output_dir_name()).unwrap(); } let aux_dir = self.aux_output_dir_name(); - // FIXME (#9639): This needs to handle non-utf8 paths - let extra_link_args = vec!["-L".to_owned(), - aux_dir.to_str().unwrap().to_owned()]; for rel_ab in &self.props.aux_builds { let aux_testpaths = self.compute_aux_test_paths(rel_ab); let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); - let mut crate_type = if aux_props.no_prefer_dynamic { - Vec::new() + let aux_output = { + let f = self.make_lib_name(&self.testpaths.file); + let parent = f.parent().unwrap(); + TargetLocation::ThisDirectory(parent.to_path_buf()) + }; + let aux_cx = TestCx { + config: self.config, + props: &aux_props, + testpaths: &aux_testpaths, + revision: self.revision + }; + let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output); + + let crate_type = if aux_props.no_prefer_dynamic { + None } else if (self.config.target.contains("musl") && !aux_props.force_host) || self.config.target.contains("emscripten") { // We primarily compile all auxiliary libraries as dynamic libraries @@ -1321,28 +1286,20 @@ actual:\n\ // dynamic libraries so we just go back to building a normal library. Note, // however, that for MUSL if the library is built with `force_host` then // it's ok to be a dylib as the host should always support dylibs. - vec!["--crate-type=lib".to_owned()] + Some("lib") } else { - vec!["--crate-type=dylib".to_owned()] - }; - crate_type.extend(extra_link_args.clone()); - let aux_output = { - let f = self.make_lib_name(&self.testpaths.file); - let parent = f.parent().unwrap(); - TargetLocation::ThisDirectory(parent.to_path_buf()) + Some("dylib") }; - let aux_cx = TestCx { - config: self.config, - props: &aux_props, - testpaths: &aux_testpaths, - revision: self.revision - }; - let aux_args = aux_cx.make_compile_args(crate_type, &aux_testpaths.file, aux_output); - let auxres = aux_cx.compose_and_run(aux_args, - Vec::new(), + + if let Some(crate_type) = crate_type { + aux_rustc.args(&["--crate-type", crate_type]); + } + + aux_rustc.arg("-L").arg(&aux_dir); + + let auxres = aux_cx.compose_and_run(aux_rustc, aux_cx.config.compile_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), - None, None); if !auxres.status.success() { self.fatal_proc_rec( @@ -1352,40 +1309,65 @@ actual:\n\ } } - self.compose_and_run(args, - self.props.rustc_env.clone(), + rustc.envs(self.props.rustc_env.clone()); + self.compose_and_run(rustc, self.config.compile_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), - input, - None) + input) } fn compose_and_run(&self, - ProcArgs{ args, prog }: ProcArgs, - procenv: Vec<(String, String)> , + mut command: Command, lib_path: &str, aux_path: Option<&str>, - input: Option, - working_dir: Option) -> ProcRes { - self.program_output(lib_path, prog, aux_path, args, procenv, input, working_dir) - } + input: Option) -> ProcRes { + let cmdline = + { + let cmdline = self.make_cmdline(&command, lib_path); + logv(self.config, format!("executing {}", cmdline)); + cmdline + }; - fn make_compile_args(&self, - extras: Vec , - input_file: &Path, - output_file: TargetLocation) - -> ProcArgs - { - let target = if self.props.force_host { - &*self.config.host - } else { - &*self.config.target + command + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .stdin(Stdio::piped()); + + // Need to be sure to put both the lib_path and the aux path in the dylib + // search path for the child. + let mut path = env::split_paths(&env::var_os(dylib_env_var()).unwrap_or(OsString::new())) + .collect::>(); + if let Some(p) = aux_path { + path.insert(0, PathBuf::from(p)) + } + path.insert(0, PathBuf::from(lib_path)); + + // Add the new dylib search path var + let newpath = env::join_paths(&path).unwrap(); + command.env(dylib_env_var(), newpath); + + let mut child = command.spawn().expect(&format!("failed to exec `{:?}`", &command)); + if let Some(input) = input { + child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); + } + let Output { status, stdout, stderr } = child.wait_with_output().unwrap(); + + let result = ProcRes { + status, + stdout: String::from_utf8(stdout).unwrap(), + stderr: String::from_utf8(stderr).unwrap(), + cmdline, }; - // FIXME (#9639): This needs to handle non-utf8 paths - let mut args = vec![input_file.to_str().unwrap().to_owned(), - "-L".to_owned(), - self.config.build_base.to_str().unwrap().to_owned()]; + self.dump_output(&result.stdout, &result.stderr); + + result + } + + fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command { + let mut rustc = Command::new(&self.config.rustc_path); + rustc.arg(input_file) + .arg("-L").arg(&self.config.build_base); // Optionally prevent default --target if specified in test compile-flags. let custom_target = self.props.compile_flags @@ -1393,26 +1375,23 @@ actual:\n\ .fold(false, |acc, x| acc || x.starts_with("--target")); if !custom_target { - args.extend(vec![ - format!("--target={}", target), - ]); + let target = if self.props.force_host { + &*self.config.host + } else { + &*self.config.target + }; + + rustc.arg(&format!("--target={}", target)); } if let Some(revision) = self.revision { - args.extend(vec![ - "--cfg".to_string(), - revision.to_string(), - ]); + rustc.args(&["--cfg", revision]); } if let Some(ref incremental_dir) = self.props.incremental_dir { - args.extend(vec![ - "-Z".to_string(), - format!("incremental={}", incremental_dir.display()), - ]); + rustc.args(&["-Z", &format!("incremental={}", incremental_dir.display())]); } - match self.config.mode { CompileFail | ParseFail | @@ -1421,19 +1400,14 @@ actual:\n\ // fashion, then you want JSON mode. Old-skool error // patterns still match the raw compiler output. if self.props.error_patterns.is_empty() { - args.extend(["--error-format", - "json"] - .iter() - .map(|s| s.to_string())); + rustc.args(&["--error-format", "json"]); } } MirOpt => { - args.extend(["-Zdump-mir=all", - "-Zmir-opt-level=3", - "-Zdump-mir-exclude-pass-number"] - .iter() - .map(|s| s.to_string())); - + rustc.args(&[ + "-Zdump-mir=all", + "-Zmir-opt-level=3", + "-Zdump-mir-exclude-pass-number"]); let mir_dump_dir = self.get_mir_dump_dir(); create_dir_all(mir_dump_dir.as_path()).unwrap(); @@ -1441,7 +1415,7 @@ actual:\n\ dir_opt.push_str(mir_dump_dir.to_str().unwrap()); debug!("dir_opt: {:?}", dir_opt); - args.push(dir_opt); + rustc.arg(dir_opt); } RunPass | RunFail | @@ -1458,32 +1432,28 @@ actual:\n\ } } - args.extend_from_slice(&extras); if !self.props.no_prefer_dynamic { - args.push("-C".to_owned()); - args.push("prefer-dynamic".to_owned()); + rustc.args(&["-C", "prefer-dynamic"]); } - let path = match output_file { + + match output_file { TargetLocation::ThisFile(path) => { - args.push("-o".to_owned()); - path + rustc.arg("-o").arg(path); } TargetLocation::ThisDirectory(path) => { - args.push("--out-dir".to_owned()); - path + rustc.arg("--out-dir").arg(path); } - }; - args.push(path.to_str().unwrap().to_owned()); + } + if self.props.force_host { - args.extend(self.split_maybe_args(&self.config.host_rustcflags)); + rustc.args(self.split_maybe_args(&self.config.host_rustcflags)); } else { - args.extend(self.split_maybe_args(&self.config.target_rustcflags)); - } - args.extend(self.props.compile_flags.iter().cloned()); - ProcArgs { - prog: self.config.rustc_path.to_str().unwrap().to_owned(), - args, + rustc.args(self.split_maybe_args(&self.config.target_rustcflags)); } + + rustc.args(&self.props.compile_flags); + + rustc } fn make_lib_name(&self, auxfile: &Path) -> PathBuf { @@ -1554,50 +1524,12 @@ actual:\n\ } } - fn program_output(&self, - lib_path: &str, - prog: String, - aux_path: Option<&str>, - args: Vec, - env: Vec<(String, String)>, - input: Option, - working_dir: Option) - -> ProcRes { - let cmdline = - { - let cmdline = self.make_cmdline(lib_path, - &prog, - &args); - logv(self.config, format!("executing {}", cmdline)); - cmdline - }; - - let procsrv::Result { - out, - err, - status - } = procsrv::run(lib_path, - &prog, - aux_path, - &args, - env, - input, - working_dir).expect(&format!("failed to exec `{}`", prog)); - self.dump_output(&out, &err); - ProcRes { - status, - stdout: out, - stderr: err, - cmdline, - } - } - - fn make_cmdline(&self, libpath: &str, prog: &str, args: &[String]) -> String { + fn make_cmdline(&self, command: &Command, libpath: &str) -> String { use util; // Linux and mac don't require adjusting the library search path if cfg!(unix) { - format!("{} {}", prog, args.join(" ")) + format!("{:?}", command) } else { // Build the LD_LIBRARY_PATH variable as it would be seen on the command line // for diagnostic purposes @@ -1605,7 +1537,7 @@ actual:\n\ format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path)) } - format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.join(" ")) + format!("{} {:?}", lib_path_cmd_prefix(libpath), command) } } @@ -1723,30 +1655,22 @@ actual:\n\ fn compile_test_and_save_ir(&self) -> ProcRes { let aux_dir = self.aux_output_dir_name(); - // FIXME (#9639): This needs to handle non-utf8 paths - let mut link_args = vec!["-L".to_owned(), - aux_dir.to_str().unwrap().to_owned()]; - let llvm_args = vec!["--emit=llvm-ir".to_owned(),]; - link_args.extend(llvm_args); - let args = self.make_compile_args(link_args, - &self.testpaths.file, - TargetLocation::ThisDirectory( - self.output_base_name().parent() - .unwrap() - .to_path_buf())); - self.compose_and_run_compiler(args, None) + + let output_file = TargetLocation::ThisDirectory( + self.output_base_name().parent().unwrap().to_path_buf()); + let mut rustc = self.make_compile_args(&self.testpaths.file, output_file); + rustc.arg("-L").arg(aux_dir) + .arg("--emit=llvm-ir"); + + self.compose_and_run_compiler(rustc, None) } fn check_ir_with_filecheck(&self) -> ProcRes { let irfile = self.output_base_name().with_extension("ll"); - let prog = self.config.llvm_filecheck.as_ref().unwrap(); - let proc_args = ProcArgs { - // FIXME (#9639): This needs to handle non-utf8 paths - prog: prog.to_str().unwrap().to_owned(), - args: vec![format!("-input-file={}", irfile.to_str().unwrap()), - self.testpaths.file.to_str().unwrap().to_owned()] - }; - self.compose_and_run(proc_args, Vec::new(), "", None, None, None) + let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap()); + filecheck.arg("--input-file").arg(irfile) + .arg(&self.testpaths.file); + self.compose_and_run(filecheck, "", None, None) } fn run_codegen_test(&self) { @@ -2179,7 +2103,7 @@ actual:\n\ .env("RUSTDOC", cwd.join(&self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed"))) .env("TMPDIR", &tmpdir) - .env("LD_LIB_PATH_ENVVAR", procsrv::dylib_env_var()) + .env("LD_LIB_PATH_ENVVAR", dylib_env_var()) .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path)) .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path)) .env("LLVM_COMPONENTS", &self.config.llvm_components)