Skip to content

Commit 47c911e

Browse files
authored
Stabilize doctest-xcompile (#15462)
This stabilizes the doctest-xcompile feature by unconditionally enabling it. Closes #7040 Closes #12118 ## What is being stabilized? This changes it so that cargo will run doctests when using the `--target` flag for a target that is not the host. Previously, cargo would ignore doctests (and show a note if passing `--verbose`). A wrapper for running the doctest can be specified with the [`target.*.runner`](https://doc.rust-lang.org/cargo/reference/config.html#targettriplerunner) configuration option (which is powered by the `--test-runtool` rustdoc flag). This would typically be something like qemu to run under emulation. It is my understanding that this should work just like running other kinds of tests. Additionally, the [`target.*.linker`](https://doc.rust-lang.org/cargo/reference/config.html#targettriplelinker) config option is honored for using a custom linker. Already stabilized in rustdoc is the ability to [ignore tests per-target](https://doc.rust-lang.org/nightly/rustdoc/write-documentation/documentation-tests.html#ignoring-targets). ## Motivation The lack of doctest cross-compile support has always been simply due to the lack of functionality in rustdoc to support this. Rustdoc gained the ability to cross-compile doctests some time ago, but there were additional flags like the test runner that were not stabilized until just recently. This is intended to ensure that projects have full test coverage even when doing cross-compilation. It can be [surprising](#12118) to some that this was not happening, particularly since cargo is silent about it. ## Risks The cargo team had several conversations about how to roll out this feature. Ultimately we decided to enable it unconditionally with the understanding that most projects will probably want to have their doctests covered, and that any breakage will be a local concern that can be resolved by either fixing the test or ignoring the target. Tests in rust-lang/rust run into this issue, [particularly on android](rust-lang/rust#119147 (comment)), and those will need to be fixed before this reaches beta. This is something I am looking into. Some cross-compiling scenarios may need codegen flags that are not supported. It's not clear how common this will be, or if ignoring will be a solution, or how difficult it would be to update rustdoc and cargo to support these. Additionally, the split between RUSTFLAGS and RUSTDOCFLAGS can be cumbersome. ## Implementation history - rust-lang/rust#60387 -- Support added to rustdoc to support the `--target` flag and runtool and per-target-ignores. - #6892 -- Initial support in cargo. - #7391 -- Added unstable documentation. - #8094 -- Fix target for doc test cross compilation - #8358 -- Fixed regression with `--target=HOST` not working on stable. - #10132 -- Added note about doctests not running (under `--verbose`). - rust-lang/rust#112751 -- Fixed `--test-run-directory` interaction with `--test-runtool`. - rust-lang/rust#137096 -- Stabilization (and rename) of the rustdoc `--test-runtool` and `--test-runtool-arg` CLI args, and drops `--enable-per-target-ignores` unconditionally enabling it. ## Test coverage Cargo tests: - [artifact_dep::cross_doctests_works_with_artifacts](https://github.com/ehuss/cargo/blob/56c08f84e28d3653ae0c842f331a226738108188/tests/testsuite/artifact_dep.rs#L1248-L1326) -- Checks that doctest has access to the artifact dependencies. - [build_script::duplicate_script_with_extra_env](https://github.com/ehuss/cargo/blob/56c08f84e28d3653ae0c842f331a226738108188/tests/testsuite/build_script.rs#L5514-L5614) -- Checks that build-script env and cfg values are correctly handled on host versus target when cross running doctests. - [cross_compile::cross_tests](https://github.com/ehuss/cargo/blob/56c08f84e28d3653ae0c842f331a226738108188/tests/testsuite/cross_compile.rs#L416-L502) -- Basic test that cross-compiled tests work. - [cross_compile::doctest_xcompile_linker](https://github.com/ehuss/cargo/blob/56c08f84e28d3653ae0c842f331a226738108188/tests/testsuite/cross_compile.rs#L1139-L1182) -- Checks that the linker config argument works. - [custom_target::custom_target_minimal](https://github.com/ehuss/cargo/blob/56c08f84e28d3653ae0c842f331a226738108188/tests/testsuite/custom_target.rs#L39-L71) -- Checks that `.json` targets work with rustdoc cross tests. - [test::cargo_test_doctest_xcompile_ignores](https://github.com/ehuss/cargo/blob/56c08f84e28d3653ae0c842f331a226738108188/tests/testsuite/test.rs#L4743-L4777) -- Checks the `ignore-*` syntax works. - [test::cargo_test_doctest_xcompile_runner](https://github.com/ehuss/cargo/blob/2603268cda3e32565ac27ee642f2b755fa590bac/tests/testsuite/test.rs#L4783-L4863) -- Checks runner with cross doctests. - [test::cargo_test_doctest_xcompile_no_runner](https://github.com/ehuss/cargo/blob/2603268cda3e32565ac27ee642f2b755fa590bac/tests/testsuite/test.rs#L4869-L4907) -- Checks cross doctests without a runner. Rustdoc tests: - [run-make/doctest-runtool](https://github.com/rust-lang/rust/tree/25cdf1f67463c9365d8d83778c933ec7480e940b/tests/run-make/doctests-runtool) -- Tests behavior of `--test-run-directory` with relative paths of the runner. - [rustdoc/doctest/doctest-runtool](https://github.com/rust-lang/rust/blob/25cdf1f67463c9365d8d83778c933ec7480e940b/tests/rustdoc/doctest/doctest-runtool.rs) -- Tests for `--test-runtool` and `--test-runtool-arg`. ## Future concerns There have been some discussions (rust-lang/testing-devex-team#5) about changing how doctests are driven. My understanding is that stabilizing this should not affect those plans, since if cargo becomes the driver, it will simply need to build things with `--target` and use the appropriate runner. ## Change notes This PR changed tests a little: - artifact_dep::no_cross_doctests_works_with_artifacts was changed now that doctests actually work. - cross_compile::cross_tests was changed to properly check doctests. - cross_compile::no_cross_doctests dropped since it is no longer relevant. - standard_lib::doctest didn't need `-Zdoctest-xcompile` since `-Zbuild-std` no longer uses a target. - test::cargo_test_doctest_xcompile was removed since it is a duplicate of cross_compile::cross_tests I think this should probably wait until the next release cutoff, moving this to 1.89 (will update the PR accordingly if that happens).
2 parents a14791c + 4194703 commit 47c911e

File tree

10 files changed

+92
-293
lines changed

10 files changed

+92
-293
lines changed

src/cargo/core/features.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,6 @@ unstable_cli_options!(
769769
codegen_backend: bool = ("Enable the `codegen-backend` option in profiles in .cargo/config.toml file"),
770770
config_include: bool = ("Enable the `include` key in config files"),
771771
direct_minimal_versions: bool = ("Resolve minimal dependency versions instead of maximum (direct dependencies only)"),
772-
doctest_xcompile: bool = ("Compile and run doctests for non-host target using runner config"),
773772
dual_proc_macros: bool = ("Build proc-macros for both the host and the target"),
774773
feature_unification: bool = ("Enable new feature unification modes in workspaces"),
775774
features: Option<Vec<String>>,
@@ -879,6 +878,8 @@ const STABILIZED_LINTS: &str = "The `[lints]` table is now always available.";
879878
const STABILIZED_CHECK_CFG: &str =
880879
"Compile-time checking of conditional (a.k.a. `-Zcheck-cfg`) is now always enabled.";
881880

881+
const STABILIZED_DOCTEST_XCOMPILE: &str = "Doctest cross-compiling is now always enabled.";
882+
882883
fn deserialize_comma_separated_list<'de, D>(
883884
deserializer: D,
884885
) -> Result<Option<Vec<String>>, D::Error>
@@ -1275,7 +1276,7 @@ impl CliUnstable {
12751276
"codegen-backend" => self.codegen_backend = parse_empty(k, v)?,
12761277
"config-include" => self.config_include = parse_empty(k, v)?,
12771278
"direct-minimal-versions" => self.direct_minimal_versions = parse_empty(k, v)?,
1278-
"doctest-xcompile" => self.doctest_xcompile = parse_empty(k, v)?,
1279+
"doctest-xcompile" => stabilized_warn(k, "1.89", STABILIZED_DOCTEST_XCOMPILE),
12791280
"dual-proc-macros" => self.dual_proc_macros = parse_empty(k, v)?,
12801281
"feature-unification" => self.feature_unification = parse_empty(k, v)?,
12811282
"gc" => self.gc = parse_empty(k, v)?,

src/cargo/ops/cargo_test.rs

+9-34
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ fn run_doc_tests(
176176
) -> Result<Vec<UnitTestError>, CliError> {
177177
let gctx = ws.gctx();
178178
let mut errors = Vec::new();
179-
let doctest_xcompile = gctx.cli_unstable().doctest_xcompile;
180179
let color = gctx.shell().color_choice();
181180

182181
for doctest_info in &compilation.to_doc_test {
@@ -189,28 +188,6 @@ fn run_doc_tests(
189188
env,
190189
} = doctest_info;
191190

192-
if !doctest_xcompile {
193-
match unit.kind {
194-
CompileKind::Host => {}
195-
CompileKind::Target(target) => {
196-
if target.short_name() != compilation.host {
197-
// Skip doctests, -Zdoctest-xcompile not enabled.
198-
gctx.shell().verbose(|shell| {
199-
shell.note(format!(
200-
"skipping doctests for {} ({}), \
201-
cross-compilation doctests are not yet supported\n\
202-
See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#doctest-xcompile \
203-
for more information.",
204-
unit.pkg,
205-
unit.target.description_named()
206-
))
207-
})?;
208-
continue;
209-
}
210-
}
211-
}
212-
}
213-
214191
gctx.shell().status("Doc-tests", unit.target.name())?;
215192
let mut p = compilation.rustdoc_process(unit, *script_meta)?;
216193

@@ -237,19 +214,17 @@ fn run_doc_tests(
237214
p.arg("--target").arg(target.rustc_target());
238215
}
239216

240-
if doctest_xcompile {
241-
if let Some((runtool, runtool_args)) = compilation.target_runner(unit.kind) {
242-
p.arg("--test-runtool").arg(runtool);
243-
for arg in runtool_args {
244-
p.arg("--test-runtool-arg").arg(arg);
245-
}
246-
}
247-
if let Some(linker) = linker {
248-
let mut joined = OsString::from("linker=");
249-
joined.push(linker);
250-
p.arg("-C").arg(joined);
217+
if let Some((runtool, runtool_args)) = compilation.target_runner(unit.kind) {
218+
p.arg("--test-runtool").arg(runtool);
219+
for arg in runtool_args {
220+
p.arg("--test-runtool-arg").arg(arg);
251221
}
252222
}
223+
if let Some(linker) = linker {
224+
let mut joined = OsString::from("linker=");
225+
joined.push(linker);
226+
p.arg("-C").arg(joined);
227+
}
253228

254229
if unit.profile.panic != PanicStrategy::Unwind {
255230
p.arg("-C").arg(format!("panic={}", unit.profile.panic));

src/doc/src/reference/unstable.md

+4-16
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ Each new feature described below should explain how to use it.
8484
* [root-dir](#root-dir) --- Controls the root directory relative to which paths are printed
8585
* Compile behavior
8686
* [mtime-on-use](#mtime-on-use) --- Updates the last-modified timestamp on every dependency every time it is used, to provide a mechanism to delete unused artifacts.
87-
* [doctest-xcompile](#doctest-xcompile) --- Supports running doctests with the `--target` flag.
8887
* [build-std](#build-std) --- Builds the standard library instead of using pre-built binaries.
8988
* [build-std-features](#build-std-features) --- Sets features to use with the standard library.
9089
* [binary-dep-depinfo](#binary-dep-depinfo) --- Causes the dep-info file to track binary dependencies.
@@ -278,21 +277,6 @@ Available template variables:
278277
The `-Zroot-dir` flag sets the root directory relative to which paths are printed.
279278
This affects both diagnostics and paths emitted by the `file!()` macro.
280279

281-
## doctest-xcompile
282-
* Tracking Issue: [#7040](https://github.com/rust-lang/cargo/issues/7040)
283-
* Tracking Rustc Issue: [#64245](https://github.com/rust-lang/rust/issues/64245)
284-
285-
This flag changes `cargo test`'s behavior when handling doctests when
286-
a target is passed. Currently, if a target is passed that is different
287-
from the host cargo will simply skip testing doctests. If this flag is
288-
present, cargo will continue as normal, passing the tests to doctest,
289-
while also passing it a `--target` option, as well as passing along
290-
information from `.cargo/config.toml`. See the rustc issue for more information.
291-
292-
```sh
293-
cargo test --target foo -Zdoctest-xcompile
294-
```
295-
296280
## Build-plan
297281
* Tracking Issue: [#5579](https://github.com/rust-lang/cargo/issues/5579)
298282

@@ -2171,3 +2155,7 @@ See [`cargo fix --edition`](../commands/cargo-fix.md) and [The Edition Guide](..
21712155

21722156
Support for automatically deleting old files was stabilized in Rust 1.88.
21732157
More information can be found in the [config chapter](config.md#cache).
2158+
2159+
## doctest-xcompile
2160+
2161+
Doctest cross-compiling is now unconditionally enabled starting in Rust 1.89. Running doctests with `cargo test` will now honor the `--target` flag.

tests/testsuite/artifact_dep.rs

+8-24
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,7 @@ fn non_build_script_deps_adopt_specified_target_unconditionally() {
12461246
}
12471247

12481248
#[cargo_test]
1249-
fn no_cross_doctests_works_with_artifacts() {
1249+
fn cross_doctests_works_with_artifacts() {
12501250
if cross_compile::disabled() {
12511251
return;
12521252
}
@@ -1302,40 +1302,24 @@ fn no_cross_doctests_works_with_artifacts() {
13021302
println!("c");
13031303
let target = cross_compile::alternate();
13041304

1305-
// This will build the library, but does not build or run doc tests.
1306-
// This should probably be a warning or error.
1307-
p.cargo("test -Z bindeps -v --doc --target")
1308-
.arg(&target)
1309-
.masquerade_as_nightly_cargo(&["bindeps"])
1310-
.with_stderr_data(str![[r#"
1311-
[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)
1312-
[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--target [ALT_TARGET] [..]
1313-
[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..]--target [ALT_TARGET] [..]
1314-
[COMPILING] foo v0.0.1 ([ROOT]/foo)
1315-
[RUNNING] `rustc --crate-name foo [..]`
1316-
[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
1317-
[NOTE] skipping doctests for foo v0.0.1 ([ROOT]/foo) (lib), cross-compilation doctests are not yet supported
1318-
See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#doctest-xcompile for more information.
1319-
1320-
"#]])
1321-
.run();
1322-
13231305
if !cross_compile::can_run_on_host() {
13241306
return;
13251307
}
13261308

1327-
// This tests the library, but does not run the doc tests.
13281309
p.cargo("test -Z bindeps -v --target")
13291310
.arg(&target)
13301311
.masquerade_as_nightly_cargo(&["bindeps"])
13311312
.with_stderr_data(str![[r#"
1332-
[FRESH] bar v0.5.0 ([ROOT]/foo/bar)
1313+
[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)
1314+
[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--target [ALT_TARGET] [..]
1315+
[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..]--target [ALT_TARGET] [..]
13331316
[COMPILING] foo v0.0.1 ([ROOT]/foo)
1334-
[RUNNING] `rustc --crate-name foo [..]--test[..]
1317+
[RUNNING] `rustc --crate-name foo [..]
1318+
[RUNNING] `rustc --crate-name foo [..]
13351319
[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
13361320
[RUNNING] `[ROOT]/foo/target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE]`
1337-
[NOTE] skipping doctests for foo v0.0.1 ([ROOT]/foo) (lib), cross-compilation doctests are not yet supported
1338-
See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#doctest-xcompile for more information.
1321+
[DOCTEST] foo
1322+
[RUNNING] `rustdoc [..]--test src/lib.rs --test-run-directory [ROOT]/foo --target [ALT_TARGET] [..]
13391323
13401324
"#]])
13411325
.run();

tests/testsuite/build_script.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5600,10 +5600,10 @@ test check_target ... ok
56005600
"#]])
56015601
.run();
56025602

5603+
// Remove check once 1.88 is stable
56035604
if cargo_test_support::is_nightly() {
5604-
p.cargo("test --workspace -Z doctest-xcompile --doc --target")
5605+
p.cargo("test --workspace --doc --target")
56055606
.arg(&target)
5606-
.masquerade_as_nightly_cargo(&["doctest-xcompile"])
56075607
.with_stdout_data(str![[r#"
56085608
...
56095609
test foo/src/lib.rs - (line 2) ... ok

tests/testsuite/cargo/z_help/stdout.term.svg

+32-34
Loading

0 commit comments

Comments
 (0)