Skip to content

Commit eadbaec

Browse files
committed
Auto merge of #6892 - Goirad:doctest-xcompile, r=alexcrichton
Added ability to crosscompile doctests This commit adds the ability to cross-compile and run doctests. Like before cargo checks if target == host, the difference is that if there is a runtool defined in config.toml, it passes the information forward to rustdoc so that it can run the doctests with that tool. If no tool is defined and the target != host, cargo instead displays a message that doctests will not be compiled because of the missing runtool. See [here](rust-lang/rust#60387) for the companion PR in the rust project that modifies rustdoc to accept the relevant options as well as allow ignoring doctests on a per target level. Partially resolves [#6460](#6460) See [here](#7040) for the tracking issue.
2 parents e2ed0d0 + a2209fc commit eadbaec

File tree

4 files changed

+254
-4
lines changed

4 files changed

+254
-4
lines changed

src/cargo/core/compiler/compilation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ impl<'cfg> Compilation<'cfg> {
163163
self.fill_env(process(cmd), pkg, true)
164164
}
165165

166-
fn target_runner(&self) -> &Option<(PathBuf, Vec<String>)> {
166+
pub fn target_runner(&self) -> &Option<(PathBuf, Vec<String>)> {
167167
&self.target_runner
168168
}
169169

src/cargo/core/features.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ pub struct CliUnstable {
336336
pub binary_dep_depinfo: bool,
337337
pub build_std: Option<Vec<String>>,
338338
pub timings: Option<Vec<String>>,
339+
pub doctest_xcompile: bool,
339340
}
340341

341342
impl CliUnstable {
@@ -393,6 +394,7 @@ impl CliUnstable {
393394
self.build_std = Some(crate::core::compiler::standard_lib::parse_unstable_flag(v))
394395
}
395396
"timings" => self.timings = Some(parse_timings(v)),
397+
"doctest-xcompile" => self.doctest_xcompile = true,
396398
_ => failure::bail!("unknown `-Z` flag specified: {}", k),
397399
}
398400

src/cargo/ops/cargo_test.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,14 @@ fn run_doc_tests(
140140
let mut errors = Vec::new();
141141
let config = options.compile_opts.config;
142142

143-
// We don't build/run doc tests if `target` does not equal `host`.
144-
if compilation.host != compilation.target {
143+
// The unstable doctest-xcompile feature enables both per-target-ignores and
144+
// cross-compiling doctests. As a side effect, this feature also gates running
145+
// doctests with runtools when target == host.
146+
let doctest_xcompile = config.cli_unstable().doctest_xcompile;
147+
let mut runtool: &Option<(std::path::PathBuf, Vec<String>)> = &None;
148+
if doctest_xcompile {
149+
runtool = compilation.target_runner();
150+
} else if compilation.host != compilation.target {
145151
return Ok((Test::Doc, errors));
146152
}
147153

@@ -158,6 +164,19 @@ fn run_doc_tests(
158164
.arg("--crate-name")
159165
.arg(&target.crate_name());
160166

167+
if doctest_xcompile {
168+
p.arg("--target").arg(&compilation.target);
169+
p.arg("-Zunstable-options");
170+
p.arg("--enable-per-target-ignores");
171+
}
172+
173+
runtool.as_ref().map(|(runtool, runtool_args)| {
174+
p.arg("--runtool").arg(runtool);
175+
for arg in runtool_args {
176+
p.arg("--runtool-arg").arg(arg);
177+
}
178+
});
179+
161180
for &rust_dep in &[&compilation.deps_output] {
162181
let mut arg = OsString::from("dependency=");
163182
arg.push(rust_dep);
@@ -194,7 +213,6 @@ fn run_doc_tests(
194213
if let Some(flags) = compilation.rustdocflags.get(&package.package_id()) {
195214
p.args(flags);
196215
}
197-
198216
config
199217
.shell()
200218
.verbose(|shell| shell.status("Running", p.to_string()))?;

tests/testsuite/test.rs

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use cargo_test_support::registry::Package;
88
use cargo_test_support::{
99
basic_bin_manifest, basic_lib_manifest, basic_manifest, cargo_exe, project,
1010
};
11+
use cargo_test_support::{cross_compile, is_nightly, paths};
1112
use cargo_test_support::{rustc_host, sleep_ms};
1213

1314
#[cargo_test]
@@ -3660,3 +3661,232 @@ fn test_dep_with_dev() {
36603661
)
36613662
.run();
36623663
}
3664+
3665+
#[cargo_test]
3666+
fn cargo_test_doctest_xcompile_ignores() {
3667+
if !is_nightly() {
3668+
return;
3669+
}
3670+
let p = project()
3671+
.file("Cargo.toml", &basic_lib_manifest("foo"))
3672+
.file(
3673+
"src/lib.rs",
3674+
r#"
3675+
///```ignore-x86_64
3676+
///assert!(cfg!(not(target_arch = "x86_64")));
3677+
///```
3678+
pub fn foo() -> u8 {
3679+
4
3680+
}
3681+
"#,
3682+
)
3683+
.build();
3684+
3685+
p.cargo("build").run();
3686+
#[cfg(not(target_arch = "x86_64"))]
3687+
p.cargo("test")
3688+
.with_stdout_contains(
3689+
"\
3690+
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out\
3691+
",
3692+
)
3693+
.run();
3694+
#[cfg(target_arch = "x86_64")]
3695+
p.cargo("test")
3696+
.with_status(101)
3697+
.with_stdout_contains(
3698+
"\
3699+
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out\
3700+
",
3701+
)
3702+
.run();
3703+
3704+
#[cfg(not(target_arch = "x86_64"))]
3705+
p.cargo("test -Zdoctest-xcompile")
3706+
.masquerade_as_nightly_cargo()
3707+
.with_stdout_contains(
3708+
"\
3709+
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out\
3710+
",
3711+
)
3712+
.run();
3713+
3714+
#[cfg(target_arch = "x86_64")]
3715+
p.cargo("test -Zdoctest-xcompile")
3716+
.masquerade_as_nightly_cargo()
3717+
.with_stdout_contains(
3718+
"\
3719+
test result: ok. 0 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out\
3720+
",
3721+
)
3722+
.run();
3723+
}
3724+
3725+
#[cargo_test]
3726+
fn cargo_test_doctest_xcompile() {
3727+
if !is_nightly() {
3728+
return;
3729+
}
3730+
let p = project()
3731+
.file("Cargo.toml", &basic_lib_manifest("foo"))
3732+
.file(
3733+
"src/lib.rs",
3734+
r#"
3735+
3736+
///```
3737+
///assert!(1 == 1);
3738+
///```
3739+
pub fn foo() -> u8 {
3740+
4
3741+
}
3742+
"#,
3743+
)
3744+
.build();
3745+
3746+
p.cargo("build").run();
3747+
p.cargo(&format!("test --target {}", cross_compile::alternate()))
3748+
.with_stdout_contains(
3749+
"\
3750+
running 0 tests\
3751+
",
3752+
)
3753+
.run();
3754+
p.cargo(&format!(
3755+
"test --target {} -Zdoctest-xcompile",
3756+
cross_compile::alternate()
3757+
))
3758+
.masquerade_as_nightly_cargo()
3759+
.with_stdout_contains(
3760+
"\
3761+
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out\
3762+
",
3763+
)
3764+
.run();
3765+
}
3766+
3767+
#[cargo_test]
3768+
fn cargo_test_doctest_xcompile_runner() {
3769+
use std::fs;
3770+
if !is_nightly() {
3771+
return;
3772+
}
3773+
3774+
let runner = project()
3775+
.file("Cargo.toml", &basic_bin_manifest("runner"))
3776+
.file(
3777+
"src/main.rs",
3778+
r#"
3779+
pub fn main() {
3780+
eprintln!("this is a runner");
3781+
let args: Vec<String> = std::env::args().collect();
3782+
std::process::Command::new(&args[1]).spawn();
3783+
}
3784+
"#,
3785+
)
3786+
.build();
3787+
3788+
runner.cargo("build").run();
3789+
assert!(runner.bin("runner").is_file());
3790+
let runner_path = paths::root().join("runner");
3791+
fs::copy(&runner.bin("runner"), &runner_path).unwrap();
3792+
3793+
let config = paths::root().join(".cargo/config");
3794+
3795+
fs::create_dir_all(config.parent().unwrap()).unwrap();
3796+
File::create(config)
3797+
.unwrap()
3798+
.write_all(
3799+
format!(
3800+
r#"
3801+
[target.'cfg(target_arch = "x86")']
3802+
runner = "{}"
3803+
"#,
3804+
runner_path.to_str().unwrap()
3805+
)
3806+
.as_bytes(),
3807+
)
3808+
.unwrap();
3809+
3810+
let p = project()
3811+
.file("Cargo.toml", &basic_lib_manifest("foo"))
3812+
.file(
3813+
"src/lib.rs",
3814+
r#"
3815+
///```
3816+
///assert!(cfg!(target_arch = "x86"));
3817+
///```
3818+
pub fn foo() -> u8 {
3819+
4
3820+
}
3821+
"#,
3822+
)
3823+
.build();
3824+
3825+
p.cargo("build").run();
3826+
p.cargo(&format!("test --target {}", cross_compile::alternate()))
3827+
.with_stdout_contains(
3828+
"\
3829+
running 0 tests\
3830+
",
3831+
)
3832+
.run();
3833+
p.cargo(&format!(
3834+
"test --target {} -Zdoctest-xcompile",
3835+
cross_compile::alternate()
3836+
))
3837+
.masquerade_as_nightly_cargo()
3838+
.with_stdout_contains(
3839+
"\
3840+
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out\
3841+
",
3842+
)
3843+
.with_stderr_contains(
3844+
"\
3845+
this is a runner\
3846+
",
3847+
)
3848+
.run();
3849+
}
3850+
3851+
#[cargo_test]
3852+
fn cargo_test_doctest_xcompile_no_runner() {
3853+
if !is_nightly() {
3854+
return;
3855+
}
3856+
3857+
let p = project()
3858+
.file("Cargo.toml", &basic_lib_manifest("foo"))
3859+
.file(
3860+
"src/lib.rs",
3861+
r#"
3862+
3863+
///```
3864+
///assert!(cfg!(target_arch = "x86"));
3865+
///```
3866+
pub fn foo() -> u8 {
3867+
4
3868+
}
3869+
"#,
3870+
)
3871+
.build();
3872+
3873+
p.cargo("build").run();
3874+
p.cargo(&format!("test --target {}", cross_compile::alternate()))
3875+
.with_stdout_contains(
3876+
"\
3877+
running 0 tests\
3878+
",
3879+
)
3880+
.run();
3881+
p.cargo(&format!(
3882+
"test --target {} -Zdoctest-xcompile",
3883+
cross_compile::alternate()
3884+
))
3885+
.masquerade_as_nightly_cargo()
3886+
.with_stdout_contains(
3887+
"\
3888+
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out\
3889+
",
3890+
)
3891+
.run();
3892+
}

0 commit comments

Comments
 (0)