Skip to content

Commit 275fb6c

Browse files
authored
Unrolled build for rust-lang#124612
Rollup merge of rust-lang#124612 - Urgau:run-make-stdin, r=jieyouxu Add support for inputing via stdin with run-make-support This PR adds the facility to set a input bytes that will be passed via the standard input. This is useful for testing `rustc -` (and soon `rustdoc -`). In rust-lang#124611 took the approach of having a dedicated `run` method but it is not very convenient to use and would necessitate many functions, one for success, one for fail, ... Instead this PR takes a different approach and allows setting the input bytes as if it were a parameter and when calling the (now custom) `output` function, we write the input bytes into stdin. I think this gives us maximum flexibility in the implementation and a simple interface for users. To test this new logic I ported `tests/run-make/stdin-non-utf8/` to an `rmake.rs` one. r? `@jieyouxu`
2 parents 561b5de + 2c4214e commit 275fb6c

File tree

10 files changed

+120
-25
lines changed

10 files changed

+120
-25
lines changed

src/tools/run-make-support/src/cc.rs

+5
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ impl Cc {
7171

7272
self
7373
}
74+
75+
/// Get the [`Output`][::std::process::Output] of the finished process.
76+
pub fn output(&mut self) -> ::std::process::Output {
77+
self.cmd.output().expect("failed to get output of finished process")
78+
}
7479
}
7580

7681
/// `EXTRACFLAGS`

src/tools/run-make-support/src/clang.rs

+5
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,9 @@ impl Clang {
7070
self.cmd.arg(format!("-fuse-ld={ld}"));
7171
self
7272
}
73+
74+
/// Get the [`Output`][::std::process::Output] of the finished process.
75+
pub fn output(&mut self) -> ::std::process::Output {
76+
self.cmd.output().expect("failed to get output of finished process")
77+
}
7378
}

src/tools/run-make-support/src/lib.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ pub fn set_host_rpath(cmd: &mut Command) {
144144
}
145145

146146
/// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
147-
/// containing a `cmd: Command` field. The provided helpers are:
147+
/// containing a `cmd: Command` field and a `output` function. The provided helpers are:
148148
///
149149
/// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended
150150
/// to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add
@@ -160,7 +160,12 @@ pub fn set_host_rpath(cmd: &mut Command) {
160160
/// Example usage:
161161
///
162162
/// ```ignore (illustrative)
163-
/// struct CommandWrapper { cmd: Command }
163+
/// struct CommandWrapper { cmd: Command } // <- required `cmd` field
164+
///
165+
/// impl CommandWrapper {
166+
/// /// Get the [`Output`][::std::process::Output] of the finished process.
167+
/// pub fn output(&mut self) -> Output { /* ... */ } // <- required `output()` method
168+
/// }
164169
///
165170
/// crate::impl_common_helpers!(CommandWrapper);
166171
///
@@ -231,18 +236,13 @@ macro_rules! impl_common_helpers {
231236
self
232237
}
233238

234-
/// Get the [`Output`][::std::process::Output] of the finished process.
235-
pub fn output(&mut self) -> ::std::process::Output {
236-
self.cmd.output().expect("failed to get output of finished process")
237-
}
238-
239239
/// Run the constructed command and assert that it is successfully run.
240240
#[track_caller]
241241
pub fn run(&mut self) -> ::std::process::Output {
242242
let caller_location = ::std::panic::Location::caller();
243243
let caller_line_number = caller_location.line();
244244

245-
let output = self.cmd.output().unwrap();
245+
let output = self.output();
246246
if !output.status.success() {
247247
handle_failed_output(&self.cmd, output, caller_line_number);
248248
}
@@ -255,7 +255,7 @@ macro_rules! impl_common_helpers {
255255
let caller_location = ::std::panic::Location::caller();
256256
let caller_line_number = caller_location.line();
257257

258-
let output = self.cmd.output().unwrap();
258+
let output = self.output();
259259
if output.status.success() {
260260
handle_failed_output(&self.cmd, output, caller_line_number);
261261
}

src/tools/run-make-support/src/llvm_readobj.rs

+6
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,10 @@ impl LlvmReadobj {
4141
self.cmd.arg("--file-header");
4242
self
4343
}
44+
45+
/// Get the [`Output`][::std::process::Output] of the finished process.
46+
#[track_caller]
47+
pub fn output(&mut self) -> ::std::process::Output {
48+
self.cmd.output().expect("failed to get output of finished process")
49+
}
4450
}

src/tools/run-make-support/src/rustc.rs

+34-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use std::env;
22
use std::ffi::OsString;
3+
use std::io::Write;
34
use std::path::Path;
4-
use std::process::{Command, Output};
5+
use std::process::{Command, Output, Stdio};
56

67
use crate::{handle_failed_output, set_host_rpath, tmp_dir};
78

@@ -19,6 +20,7 @@ pub fn aux_build() -> Rustc {
1920
#[derive(Debug)]
2021
pub struct Rustc {
2122
cmd: Command,
23+
stdin: Option<Box<[u8]>>,
2224
}
2325

2426
crate::impl_common_helpers!(Rustc);
@@ -37,14 +39,14 @@ impl Rustc {
3739
/// Construct a new `rustc` invocation.
3840
pub fn new() -> Self {
3941
let cmd = setup_common();
40-
Self { cmd }
42+
Self { cmd, stdin: None }
4143
}
4244

4345
/// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`).
4446
pub fn new_aux_build() -> Self {
4547
let mut cmd = setup_common();
4648
cmd.arg("--crate-type=lib");
47-
Self { cmd }
49+
Self { cmd, stdin: None }
4850
}
4951

5052
// Argument provider methods
@@ -161,12 +163,40 @@ impl Rustc {
161163
self
162164
}
163165

166+
/// Specify a stdin input
167+
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
168+
self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
169+
self
170+
}
171+
172+
/// Get the [`Output`][::std::process::Output] of the finished process.
173+
#[track_caller]
174+
pub fn output(&mut self) -> ::std::process::Output {
175+
// let's make sure we piped all the input and outputs
176+
self.cmd.stdin(Stdio::piped());
177+
self.cmd.stdout(Stdio::piped());
178+
self.cmd.stderr(Stdio::piped());
179+
180+
if let Some(input) = &self.stdin {
181+
let mut child = self.cmd.spawn().unwrap();
182+
183+
{
184+
let mut stdin = child.stdin.take().unwrap();
185+
stdin.write_all(input.as_ref()).unwrap();
186+
}
187+
188+
child.wait_with_output().expect("failed to get output of finished process")
189+
} else {
190+
self.cmd.output().expect("failed to get output of finished process")
191+
}
192+
}
193+
164194
#[track_caller]
165195
pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
166196
let caller_location = std::panic::Location::caller();
167197
let caller_line_number = caller_location.line();
168198

169-
let output = self.cmd.output().unwrap();
199+
let output = self.output();
170200
if output.status.code().unwrap() != code {
171201
handle_failed_output(&self.cmd, output, caller_line_number);
172202
}

src/tools/run-make-support/src/rustdoc.rs

+35-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::env;
2+
use std::io::Write;
23
use std::path::Path;
3-
use std::process::{Command, Output};
4+
use std::process::{Command, Output, Stdio};
45

56
use crate::{handle_failed_output, set_host_rpath};
67

@@ -17,6 +18,7 @@ pub fn rustdoc() -> Rustdoc {
1718
#[derive(Debug)]
1819
pub struct Rustdoc {
1920
cmd: Command,
21+
stdin: Option<Box<[u8]>>,
2022
}
2123

2224
crate::impl_common_helpers!(Rustdoc);
@@ -32,15 +34,15 @@ impl Rustdoc {
3234
/// Construct a bare `rustdoc` invocation.
3335
pub fn bare() -> Self {
3436
let cmd = setup_common();
35-
Self { cmd }
37+
Self { cmd, stdin: None }
3638
}
3739

3840
/// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
3941
pub fn new() -> Self {
4042
let mut cmd = setup_common();
4143
let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap();
4244
cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
43-
Self { cmd }
45+
Self { cmd, stdin: None }
4446
}
4547

4648
/// Specify path to the input file.
@@ -62,12 +64,41 @@ impl Rustdoc {
6264
self
6365
}
6466

67+
/// Specify a stdin input
68+
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
69+
self.cmd.stdin(Stdio::piped());
70+
self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
71+
self
72+
}
73+
74+
/// Get the [`Output`][::std::process::Output] of the finished process.
75+
#[track_caller]
76+
pub fn output(&mut self) -> ::std::process::Output {
77+
// let's make sure we piped all the input and outputs
78+
self.cmd.stdin(Stdio::piped());
79+
self.cmd.stdout(Stdio::piped());
80+
self.cmd.stderr(Stdio::piped());
81+
82+
if let Some(input) = &self.stdin {
83+
let mut child = self.cmd.spawn().unwrap();
84+
85+
{
86+
let mut stdin = child.stdin.take().unwrap();
87+
stdin.write_all(input.as_ref()).unwrap();
88+
}
89+
90+
child.wait_with_output().expect("failed to get output of finished process")
91+
} else {
92+
self.cmd.output().expect("failed to get output of finished process")
93+
}
94+
}
95+
6596
#[track_caller]
6697
pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
6798
let caller_location = std::panic::Location::caller();
6899
let caller_line_number = caller_location.line();
69100

70-
let output = self.cmd.output().unwrap();
101+
let output = self.output();
71102
if output.status.code().unwrap() != code {
72103
handle_failed_output(&self.cmd, output, caller_line_number);
73104
}

src/tools/tidy/src/allowed_run_make_makefiles.txt

-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,6 @@ run-make/static-unwinding/Makefile
288288
run-make/staticlib-blank-lib/Makefile
289289
run-make/staticlib-dylib-linkage/Makefile
290290
run-make/std-core-cycle/Makefile
291-
run-make/stdin-non-utf8/Makefile
292291
run-make/suspicious-library/Makefile
293292
run-make/symbol-mangling-hashed/Makefile
294293
run-make/symbol-visibility/Makefile

tests/run-make/stdin-non-utf8/Makefile

-6
This file was deleted.

tests/run-make/stdin-non-utf8/non-utf8

-1
This file was deleted.

tests/run-make/stdin-rustc/rmake.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! This test checks rustc `-` (stdin) support
2+
3+
use run_make_support::{is_windows, rustc, tmp_dir};
4+
5+
const HELLO_WORLD: &str = r#"
6+
fn main() {
7+
println!("Hello world!");
8+
}
9+
"#;
10+
11+
const NOT_UTF8: &[u8] = &[0xff, 0xff, 0xff];
12+
13+
fn main() {
14+
let out_dir = tmp_dir();
15+
16+
// echo $HELLO_WORLD | rustc -
17+
rustc().arg("-").stdin(HELLO_WORLD).run();
18+
assert!(
19+
out_dir.join(if !is_windows() { "rust_out" } else { "rust_out.exe" }).try_exists().unwrap()
20+
);
21+
22+
// echo $NOT_UTF8 | rustc -
23+
let output = rustc().arg("-").stdin(NOT_UTF8).run_fail();
24+
let stderr = String::from_utf8(output.stderr).unwrap();
25+
assert!(stderr.contains("error: couldn't read from stdin, as it did not contain valid UTF-8"));
26+
}

0 commit comments

Comments
 (0)