mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-18 09:53:26 +00:00
Introduce a custom Command
wrapper in run-make-support
This commit is contained in:
parent
cfdb6175c2
commit
18ae9afa82
@ -1,7 +1,7 @@
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use crate::{bin_name, cygpath_windows, env_var, handle_failed_output, is_msvc, is_windows, uname};
|
||||
use crate::command::Command;
|
||||
|
||||
/// Construct a new platform-specific C compiler invocation.
|
||||
///
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use crate::{bin_name, env_var, handle_failed_output};
|
||||
use crate::command::Command;
|
||||
|
||||
/// Construct a new `clang` invocation. `clang` is not always available for all targets.
|
||||
pub fn clang() -> Clang {
|
||||
@ -68,9 +68,4 @@ impl Clang {
|
||||
self.cmd.arg(format!("-fuse-ld={ld}"));
|
||||
self
|
||||
}
|
||||
|
||||
/// Get the [`Output`][::std::process::Output] of the finished process.
|
||||
pub fn command_output(&mut self) -> ::std::process::Output {
|
||||
self.cmd.output().expect("failed to get output of finished process")
|
||||
}
|
||||
}
|
||||
|
91
src/tools/run-make-support/src/command.rs
Normal file
91
src/tools/run-make-support/src/command.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use std::ffi::OsStr;
|
||||
use std::io::Write;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Command {
|
||||
cmd: StdCommand,
|
||||
stdin: Option<Box<[u8]>>,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn new<S: AsRef<OsStr>>(program: S) -> Self {
|
||||
Self {
|
||||
cmd: StdCommand::new(program),
|
||||
stdin: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_stdin(&mut self, stdin: Box<[u8]>) {
|
||||
self.stdin = Some(stdin);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub(crate) fn command_output(&mut self) -> CompletedProcess {
|
||||
// let's make sure we piped all the input and outputs
|
||||
self.cmd.stdin(Stdio::piped());
|
||||
self.cmd.stdout(Stdio::piped());
|
||||
self.cmd.stderr(Stdio::piped());
|
||||
|
||||
let output = if let Some(input) = &self.stdin {
|
||||
let mut child = self.cmd.spawn().unwrap();
|
||||
|
||||
{
|
||||
let mut stdin = child.stdin.take().unwrap();
|
||||
stdin.write_all(input.as_ref()).unwrap();
|
||||
}
|
||||
|
||||
child.wait_with_output().expect("failed to get output of finished process")
|
||||
} else {
|
||||
self.cmd.output().expect("failed to get output of finished process")
|
||||
};
|
||||
output.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Command {
|
||||
type Target = StdCommand;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.cmd
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Command {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.cmd
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the result of an executed process.
|
||||
pub struct CompletedProcess {
|
||||
output: Output,
|
||||
}
|
||||
|
||||
impl CompletedProcess {
|
||||
pub fn stdout_utf8(&self) -> String {
|
||||
String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8")
|
||||
}
|
||||
|
||||
pub fn stderr_utf8(&self) -> String {
|
||||
String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8")
|
||||
}
|
||||
|
||||
pub fn status(&self) -> ExitStatus {
|
||||
self.output.status
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn assert_exit_code(&self, code: i32) {
|
||||
assert!(self.output.status.code() == Some(code));
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Output> for CompletedProcess {
|
||||
fn from(output: Output) -> Self {
|
||||
Self {
|
||||
output
|
||||
}
|
||||
}
|
||||
}
|
@ -10,13 +10,13 @@ pub mod llvm_readobj;
|
||||
pub mod run;
|
||||
pub mod rustc;
|
||||
pub mod rustdoc;
|
||||
mod command;
|
||||
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Output};
|
||||
|
||||
pub use gimli;
|
||||
pub use object;
|
||||
@ -167,13 +167,12 @@ pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
|
||||
let mut cygpath = Command::new("cygpath");
|
||||
cygpath.arg("-w");
|
||||
cygpath.arg(path.as_ref());
|
||||
let output = cygpath.output().unwrap();
|
||||
if !output.status.success() {
|
||||
let output = cygpath.command_output();
|
||||
if !output.status().success() {
|
||||
handle_failed_output(&cygpath, output, caller_line_number);
|
||||
}
|
||||
let s = String::from_utf8(output.stdout).unwrap();
|
||||
// cygpath -w can attach a newline
|
||||
s.trim().to_string()
|
||||
output.stdout_utf8().trim().to_string()
|
||||
}
|
||||
|
||||
/// Run `uname`. This assumes that `uname` is available on the platform!
|
||||
@ -183,23 +182,23 @@ pub fn uname() -> String {
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let mut uname = Command::new("uname");
|
||||
let output = uname.output().unwrap();
|
||||
if !output.status.success() {
|
||||
let output = uname.command_output();
|
||||
if !output.status().success() {
|
||||
handle_failed_output(&uname, output, caller_line_number);
|
||||
}
|
||||
String::from_utf8(output.stdout).unwrap()
|
||||
output.stdout_utf8()
|
||||
}
|
||||
|
||||
fn handle_failed_output(cmd: &Command, output: Output, caller_line_number: u32) -> ! {
|
||||
if output.status.success() {
|
||||
fn handle_failed_output(cmd: &Command, output: CompletedProcess, caller_line_number: u32) -> ! {
|
||||
if output.status().success() {
|
||||
eprintln!("command unexpectedly succeeded at line {caller_line_number}");
|
||||
} else {
|
||||
eprintln!("command failed at line {caller_line_number}");
|
||||
}
|
||||
eprintln!("{cmd:?}");
|
||||
eprintln!("output status: `{}`", output.status);
|
||||
eprintln!("=== STDOUT ===\n{}\n\n", String::from_utf8(output.stdout).unwrap());
|
||||
eprintln!("=== STDERR ===\n{}\n\n", String::from_utf8(output.stderr).unwrap());
|
||||
eprintln!("output status: `{}`", output.status());
|
||||
eprintln!("=== STDOUT ===\n{}\n\n", output.stdout_utf8());
|
||||
eprintln!("=== STDERR ===\n{}\n\n", output.stderr_utf8());
|
||||
std::process::exit(1)
|
||||
}
|
||||
|
||||
@ -412,12 +411,12 @@ macro_rules! impl_common_helpers {
|
||||
|
||||
/// Run the constructed command and assert that it is successfully run.
|
||||
#[track_caller]
|
||||
pub fn run(&mut self) -> ::std::process::Output {
|
||||
pub fn run(&mut self) -> crate::command::CompletedProcess {
|
||||
let caller_location = ::std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let output = self.command_output();
|
||||
if !output.status.success() {
|
||||
let output = self.cmd.command_output();
|
||||
if !output.status().success() {
|
||||
handle_failed_output(&self.cmd, output, caller_line_number);
|
||||
}
|
||||
output
|
||||
@ -425,12 +424,12 @@ macro_rules! impl_common_helpers {
|
||||
|
||||
/// Run the constructed command and assert that it does not successfully run.
|
||||
#[track_caller]
|
||||
pub fn run_fail(&mut self) -> ::std::process::Output {
|
||||
pub fn run_fail(&mut self) -> crate::command::CompletedProcess {
|
||||
let caller_location = ::std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let output = self.command_output();
|
||||
if output.status.success() {
|
||||
let output = self.cmd.command_output();
|
||||
if output.status().success() {
|
||||
handle_failed_output(&self.cmd, output, caller_line_number);
|
||||
}
|
||||
output
|
||||
@ -446,3 +445,4 @@ macro_rules! impl_common_helpers {
|
||||
}
|
||||
|
||||
pub(crate) use impl_common_helpers;
|
||||
use crate::command::{Command, CompletedProcess};
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use crate::{env_var, handle_failed_output};
|
||||
use crate::command::Command;
|
||||
|
||||
/// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
|
||||
/// at `$LLVM_BIN_DIR/llvm-readobj`.
|
||||
@ -39,10 +39,4 @@ impl LlvmReadobj {
|
||||
self.cmd.arg("--file-header");
|
||||
self
|
||||
}
|
||||
|
||||
/// Get the [`Output`][::std::process::Output] of the finished process.
|
||||
#[track_caller]
|
||||
pub fn command_output(&mut self) -> ::std::process::Output {
|
||||
self.cmd.output().expect("failed to get output of finished process")
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Output};
|
||||
|
||||
use crate::{cwd, env_var, is_windows};
|
||||
use crate::command::{Command, CompletedProcess};
|
||||
|
||||
use super::handle_failed_output;
|
||||
|
||||
fn run_common(name: &str) -> (Command, Output) {
|
||||
fn run_common(name: &str) -> (Command, CompletedProcess) {
|
||||
let mut bin_path = PathBuf::new();
|
||||
bin_path.push(cwd());
|
||||
bin_path.push(name);
|
||||
@ -33,18 +33,18 @@ fn run_common(name: &str) -> (Command, Output) {
|
||||
cmd.env("PATH", env::join_paths(paths.iter()).unwrap());
|
||||
}
|
||||
|
||||
let output = cmd.output().unwrap();
|
||||
let output = cmd.command_output();
|
||||
(cmd, output)
|
||||
}
|
||||
|
||||
/// Run a built binary and make sure it succeeds.
|
||||
#[track_caller]
|
||||
pub fn run(name: &str) -> Output {
|
||||
pub fn run(name: &str) -> CompletedProcess {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let (cmd, output) = run_common(name);
|
||||
if !output.status.success() {
|
||||
if !output.status().success() {
|
||||
handle_failed_output(&cmd, output, caller_line_number);
|
||||
}
|
||||
output
|
||||
@ -52,12 +52,12 @@ pub fn run(name: &str) -> Output {
|
||||
|
||||
/// Run a built binary and make sure it fails.
|
||||
#[track_caller]
|
||||
pub fn run_fail(name: &str) -> Output {
|
||||
pub fn run_fail(name: &str) -> CompletedProcess {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let (cmd, output) = run_common(name);
|
||||
if output.status.success() {
|
||||
if output.status().success() {
|
||||
handle_failed_output(&cmd, output, caller_line_number);
|
||||
}
|
||||
output
|
||||
|
@ -1,9 +1,8 @@
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Output, Stdio};
|
||||
use command::Command;
|
||||
|
||||
use crate::{cwd, env_var, handle_failed_output, set_host_rpath};
|
||||
use crate::{command, cwd, env_var, handle_failed_output, set_host_rpath};
|
||||
|
||||
/// Construct a new `rustc` invocation.
|
||||
pub fn rustc() -> Rustc {
|
||||
@ -19,7 +18,6 @@ pub fn aux_build() -> Rustc {
|
||||
#[derive(Debug)]
|
||||
pub struct Rustc {
|
||||
cmd: Command,
|
||||
stdin: Option<Box<[u8]>>,
|
||||
}
|
||||
|
||||
crate::impl_common_helpers!(Rustc);
|
||||
@ -38,14 +36,14 @@ impl Rustc {
|
||||
/// Construct a new `rustc` invocation.
|
||||
pub fn new() -> Self {
|
||||
let cmd = setup_common();
|
||||
Self { cmd, stdin: None }
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
/// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`).
|
||||
pub fn new_aux_build() -> Self {
|
||||
let mut cmd = setup_common();
|
||||
cmd.arg("--crate-type=lib");
|
||||
Self { cmd, stdin: None }
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
// Argument provider methods
|
||||
@ -197,7 +195,7 @@ impl Rustc {
|
||||
|
||||
/// Specify a stdin input
|
||||
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
|
||||
self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
|
||||
self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
|
||||
self
|
||||
}
|
||||
|
||||
@ -213,38 +211,4 @@ impl Rustc {
|
||||
self.cmd.arg(format!("-Clinker={linker}"));
|
||||
self
|
||||
}
|
||||
|
||||
/// Get the [`Output`] of the finished process.
|
||||
#[track_caller]
|
||||
pub fn command_output(&mut self) -> Output {
|
||||
// let's make sure we piped all the input and outputs
|
||||
self.cmd.stdin(Stdio::piped());
|
||||
self.cmd.stdout(Stdio::piped());
|
||||
self.cmd.stderr(Stdio::piped());
|
||||
|
||||
if let Some(input) = &self.stdin {
|
||||
let mut child = self.cmd.spawn().unwrap();
|
||||
|
||||
{
|
||||
let mut stdin = child.stdin.take().unwrap();
|
||||
stdin.write_all(input.as_ref()).unwrap();
|
||||
}
|
||||
|
||||
child.wait_with_output().expect("failed to get output of finished process")
|
||||
} else {
|
||||
self.cmd.output().expect("failed to get output of finished process")
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let output = self.command_output();
|
||||
if output.status.code().unwrap() != code {
|
||||
handle_failed_output(&self.cmd, output, caller_line_number);
|
||||
}
|
||||
output
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
use std::ffi::OsStr;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Output, Stdio};
|
||||
|
||||
use crate::{env_var, env_var_os, handle_failed_output, set_host_rpath};
|
||||
use crate::command::Command;
|
||||
|
||||
/// Construct a plain `rustdoc` invocation with no flags set.
|
||||
pub fn bare_rustdoc() -> Rustdoc {
|
||||
@ -18,7 +17,6 @@ pub fn rustdoc() -> Rustdoc {
|
||||
#[derive(Debug)]
|
||||
pub struct Rustdoc {
|
||||
cmd: Command,
|
||||
stdin: Option<Box<[u8]>>,
|
||||
}
|
||||
|
||||
crate::impl_common_helpers!(Rustdoc);
|
||||
@ -34,7 +32,7 @@ impl Rustdoc {
|
||||
/// Construct a bare `rustdoc` invocation.
|
||||
pub fn bare() -> Self {
|
||||
let cmd = setup_common();
|
||||
Self { cmd, stdin: None }
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
/// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
|
||||
@ -42,7 +40,7 @@ impl Rustdoc {
|
||||
let mut cmd = setup_common();
|
||||
let target_rpath_dir = env_var_os("TARGET_RPATH_DIR");
|
||||
cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
|
||||
Self { cmd, stdin: None }
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
/// Specify where an external library is located.
|
||||
@ -88,33 +86,10 @@ impl Rustdoc {
|
||||
|
||||
/// Specify a stdin input
|
||||
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
|
||||
self.cmd.stdin(Stdio::piped());
|
||||
self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
|
||||
self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
|
||||
self
|
||||
}
|
||||
|
||||
/// Get the [`Output`] of the finished process.
|
||||
#[track_caller]
|
||||
pub fn command_output(&mut self) -> ::std::process::Output {
|
||||
// let's make sure we piped all the input and outputs
|
||||
self.cmd.stdin(Stdio::piped());
|
||||
self.cmd.stdout(Stdio::piped());
|
||||
self.cmd.stderr(Stdio::piped());
|
||||
|
||||
if let Some(input) = &self.stdin {
|
||||
let mut child = self.cmd.spawn().unwrap();
|
||||
|
||||
{
|
||||
let mut stdin = child.stdin.take().unwrap();
|
||||
stdin.write_all(input.as_ref()).unwrap();
|
||||
}
|
||||
|
||||
child.wait_with_output().expect("failed to get output of finished process")
|
||||
} else {
|
||||
self.cmd.output().expect("failed to get output of finished process")
|
||||
}
|
||||
}
|
||||
|
||||
/// Specify the edition year.
|
||||
pub fn edition(&mut self, edition: &str) -> &mut Self {
|
||||
self.cmd.arg("--edition");
|
||||
@ -156,16 +131,4 @@ impl Rustdoc {
|
||||
self.cmd.arg(format);
|
||||
self
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let output = self.command_output();
|
||||
if output.status.code().unwrap() != code {
|
||||
handle_failed_output(&self.cmd, output, caller_line_number);
|
||||
}
|
||||
output
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user