From 58dee7d7817f8edcd32d7eb259e22d49a4e1abbe Mon Sep 17 00:00:00 2001 From: Travis Finkenauer Date: Sat, 19 Aug 2023 15:40:24 -0700 Subject: [PATCH 1/4] rustdoc: add `--test-builder-wrapper` argument Instead of executing the test builder directly, the test builder wrapper will be called with test builder as the first argument and subsequent arguments. This is similar to cargo's RUSTC_WRAPPER argument. The `--test-builder-wrapper` argument can be passed multiple times to allow "nesting" of wrappers. --- src/librustdoc/config.rs | 7 +++++++ src/librustdoc/doctest.rs | 14 ++++++++++++-- src/librustdoc/lib.rs | 8 ++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 4b1a417b21127..be7e319bc79f4 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -130,6 +130,9 @@ pub(crate) struct Options { /// default to loading from `$sysroot/bin/rustc`. pub(crate) test_builder: Option, + /// Run these wrapper instead of rustc directly + pub(crate) test_builder_wrappers: Vec, + // Options that affect the documentation process /// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items /// with and without documentation. @@ -204,6 +207,7 @@ impl fmt::Debug for Options { .field("enable-per-target-ignores", &self.enable_per_target_ignores) .field("run_check", &self.run_check) .field("no_run", &self.no_run) + .field("test_builder_wrappers", &self.test_builder_wrappers) .field("nocapture", &self.nocapture) .field("scrape_examples_options", &self.scrape_examples_options) .field("unstable_features", &self.unstable_features) @@ -521,6 +525,8 @@ impl Options { dcx.fatal("the `--test` flag must be passed to enable `--no-run`"); } + let test_builder_wrappers = + matches.opt_strs("test-builder-wrapper").iter().map(PathBuf::from).collect(); let out_dir = matches.opt_str("out-dir").map(|s| PathBuf::from(&s)); let output = matches.opt_str("output").map(|s| PathBuf::from(&s)); let output = match (out_dir, output) { @@ -727,6 +733,7 @@ impl Options { test_builder, run_check, no_run, + test_builder_wrappers, nocapture, crate_name, output_format, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index d446b781bf139..96ad83e786763 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -25,7 +25,7 @@ use tempfile::Builder as TempFileBuilder; use std::env; use std::io::{self, Write}; use std::panic; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::{self, Command, Stdio}; use std::str; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -306,6 +306,16 @@ fn add_exe_suffix(input: String, target: &TargetTriple) -> String { input + &exe_suffix } +fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Command { + let args: Vec<&Path> = + rustc_wrappers.iter().map(PathBuf::as_path).chain([rustc_binary].into_iter()).collect(); + let (exe, args) = args.split_first().expect("unable to create rustc command"); + + let mut command = Command::new(exe); + command.args(args); + command +} + fn run_test( test: &str, crate_name: &str, @@ -334,7 +344,7 @@ fn run_test( .test_builder .as_deref() .unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc")); - let mut compiler = Command::new(&rustc_binary); + let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary); compiler.arg("--crate-type").arg("bin"); for cfg in &rustdoc_options.cfgs { compiler.arg("--cfg").arg(&cfg); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 39d27b104cdde..9618690575a21 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -530,6 +530,14 @@ fn opts() -> Vec { unstable("test-builder", |o| { o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH") }), + unstable("test-builder-wrapper", |o| { + o.optmulti( + "", + "test-builder-wrapper", + "The wrapper program for running rustc", + "WRAPPER", + ) + }), unstable("check", |o| o.optflagmulti("", "check", "Run rustdoc checks")), unstable("generate-redirect-map", |o| { o.optflagmulti( From 3d53242e53bcf4f43f7d361cb7e2a4a28f30db9c Mon Sep 17 00:00:00 2001 From: Travis Finkenauer Date: Sun, 20 Aug 2023 01:02:13 -0700 Subject: [PATCH 2/4] rustdoc: fix test's saved stdout Also reword "test-builder-wrapper" argument help. --- src/librustdoc/lib.rs | 4 ++-- .../run-make/issue-88756-default-output/output-default.stdout | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 9618690575a21..18651875130fc 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -534,8 +534,8 @@ fn opts() -> Vec { o.optmulti( "", "test-builder-wrapper", - "The wrapper program for running rustc", - "WRAPPER", + "Wrapper program to pass test-builder and arguments", + "PATH", ) }), unstable("check", |o| o.optflagmulti("", "check", "Run rustdoc checks")), diff --git a/tests/run-make/issue-88756-default-output/output-default.stdout b/tests/run-make/issue-88756-default-output/output-default.stdout index 38a3965f0c53d..12c1b389fb340 100644 --- a/tests/run-make/issue-88756-default-output/output-default.stdout +++ b/tests/run-make/issue-88756-default-output/output-default.stdout @@ -147,6 +147,8 @@ Options: --test-builder PATH The rustc-like binary to use as the test builder + --test-builder-wrapper PATH + Wrapper program to pass test-builder and arguments --check Run rustdoc checks --generate-redirect-map Generate JSON file at the top level instead of From 713043ef226332216ed75c1bd5ec1f6068a8439c Mon Sep 17 00:00:00 2001 From: Travis Finkenauer Date: Sun, 20 Aug 2023 20:25:30 -0700 Subject: [PATCH 3/4] rustdoc: create rustc command with an iterator This avoids unnecessary allocation with a temporary Vec. --- src/librustdoc/doctest.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 96ad83e786763..c6eb7be08cd81 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -307,12 +307,14 @@ fn add_exe_suffix(input: String, target: &TargetTriple) -> String { } fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Command { - let args: Vec<&Path> = - rustc_wrappers.iter().map(PathBuf::as_path).chain([rustc_binary].into_iter()).collect(); - let (exe, args) = args.split_first().expect("unable to create rustc command"); + let mut args = rustc_wrappers.iter().map(PathBuf::as_path).chain([rustc_binary].into_iter()); + let exe = args.next().expect("unable to create rustc command"); let mut command = Command::new(exe); - command.args(args); + for arg in args { + command.arg(arg); + } + command } From d02e66ddf0f1b0d436b3a8374479ec8efbe4b1db Mon Sep 17 00:00:00 2001 From: Travis Finkenauer Date: Fri, 15 Mar 2024 03:19:29 -0700 Subject: [PATCH 4/4] doc: add --test-builder/--test-builder-wrapper --- src/doc/rustdoc/src/command-line-arguments.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index b46d80eb362e2..fe5cb529c2638 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -427,3 +427,32 @@ This flag is **deprecated** and **has no effect**. Rustdoc only supports Rust source code and Markdown input formats. If the file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file. Otherwise, it assumes that the input file is Rust. + +## `--test-builder`: `rustc`-like program to build tests + +Using this flag looks like this: + +```bash +$ rustdoc --test-builder /path/to/rustc src/lib.rs +``` + +Rustdoc will use the provided program to compile tests instead of the default `rustc` program from +the sysroot. + +## `--test-builder-wrapper`: wrap calls to the test builder + +Using this flag looks like this: + +```bash +$ rustdoc --test-builder-wrapper /path/to/rustc-wrapper src/lib.rs +$ rustdoc \ + --test-builder-wrapper rustc-wrapper1 \ + --test-builder-wrapper rustc-wrapper2 \ + --test-builder rustc \ + src/lib.rs +``` + +Similar to cargo `build.rustc-wrapper` option, this flag takes a `rustc` wrapper program. +The first argument to the program will be the test builder program. + +This flag can be passed multiple times to nest wrappers.