Skip to content

Commit 98bd8fd

Browse files
committed
Added ability to crosscompile doctests
1 parent b9de4ef commit 98bd8fd

File tree

5 files changed

+109
-33
lines changed

5 files changed

+109
-33
lines changed

src/librustdoc/config.rs

+10
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ pub struct Options {
7777
/// Optional path to persist the doctest executables to, defaults to a
7878
/// temporary directory if not set.
7979
pub persist_doctests: Option<PathBuf>,
80+
/// Runtool to run doctests with
81+
pub runtool: Option<String>,
82+
/// Arguments to pass to the runtool
83+
pub runtool_args: Vec<String>,
8084

8185
// Options that affect the documentation process
8286

@@ -140,6 +144,8 @@ impl fmt::Debug for Options {
140144
.field("show_coverage", &self.show_coverage)
141145
.field("crate_version", &self.crate_version)
142146
.field("render_options", &self.render_options)
147+
.field("runtool", &self.runtool)
148+
.field("runtool_args", &self.runtool_args)
143149
.finish()
144150
}
145151
}
@@ -466,6 +472,8 @@ impl Options {
466472
let codegen_options_strs = matches.opt_strs("C");
467473
let lib_strs = matches.opt_strs("L");
468474
let extern_strs = matches.opt_strs("extern");
475+
let runtool = matches.opt_str("runtool");
476+
let runtool_args = matches.opt_strs("runtool-arg");
469477

470478
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
471479

@@ -496,6 +504,8 @@ impl Options {
496504
show_coverage,
497505
crate_version,
498506
persist_doctests,
507+
runtool,
508+
runtool_args,
499509
render_options: RenderOptions {
500510
output,
501511
external_html,

src/librustdoc/html/markdown.rs

+28-6
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
272272
))
273273
});
274274

275-
let tooltip = if ignore {
275+
let tooltip = if ignore != Ignore::None {
276276
Some(("This example is not tested".to_owned(), "ignore"))
277277
} else if compile_fail {
278278
Some(("This example deliberately fails to compile".to_owned(), "compile_fail"))
@@ -286,7 +286,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
286286
s.push_str(&highlight::render_with_highlighting(
287287
&text,
288288
Some(&format!("rust-example-rendered{}",
289-
if ignore { " ignore" }
289+
if ignore != Ignore::None { " ignore" }
290290
else if compile_fail { " compile_fail" }
291291
else if explicit_edition { " edition " }
292292
else { "" })),
@@ -297,7 +297,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
297297
s.push_str(&highlight::render_with_highlighting(
298298
&text,
299299
Some(&format!("rust-example-rendered{}",
300-
if ignore { " ignore" }
300+
if ignore != Ignore::None { " ignore" }
301301
else if compile_fail { " compile_fail" }
302302
else if explicit_edition { " edition " }
303303
else { "" })),
@@ -607,7 +607,7 @@ pub struct LangString {
607607
original: String,
608608
pub should_panic: bool,
609609
pub no_run: bool,
610-
pub ignore: bool,
610+
pub ignore: Ignore,
611611
pub rust: bool,
612612
pub test_harness: bool,
613613
pub compile_fail: bool,
@@ -616,13 +616,20 @@ pub struct LangString {
616616
pub edition: Option<Edition>
617617
}
618618

619+
#[derive(Eq, PartialEq, Clone, Debug)]
620+
pub enum Ignore {
621+
All,
622+
None,
623+
Some(Vec<String>),
624+
}
625+
619626
impl LangString {
620627
fn all_false() -> LangString {
621628
LangString {
622629
original: String::new(),
623630
should_panic: false,
624631
no_run: false,
625-
ignore: false,
632+
ignore: Ignore::None,
626633
rust: true, // NB This used to be `notrust = false`
627634
test_harness: false,
628635
compile_fail: false,
@@ -637,6 +644,7 @@ impl LangString {
637644
let mut seen_rust_tags = false;
638645
let mut seen_other_tags = false;
639646
let mut data = LangString::all_false();
647+
let mut ignores = vec![];
640648

641649
data.original = string.to_owned();
642650
let tokens = string.split(|c: char|
@@ -651,7 +659,11 @@ impl LangString {
651659
seen_rust_tags = seen_other_tags == false;
652660
}
653661
"no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; }
654-
"ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; }
662+
"ignore" => { data.ignore = Ignore::All; seen_rust_tags = !seen_other_tags; }
663+
x if x.starts_with("ignore-") => {
664+
ignores.push(x.trim_start_matches("ignore-").to_owned());
665+
seen_rust_tags = !seen_other_tags;
666+
}
655667
"allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; }
656668
"rust" => { data.rust = true; seen_rust_tags = true; }
657669
"test_harness" => {
@@ -680,6 +692,16 @@ impl LangString {
680692
}
681693
}
682694

695+
match data.ignore {
696+
Ignore::All => {},
697+
Ignore::None => {
698+
if !ignores.is_empty() {
699+
data.ignore = Ignore::Some(ignores);
700+
}
701+
},
702+
_ => unreachable!(),
703+
}
704+
683705
data.rust &= !seen_other_tags || seen_rust_tags;
684706

685707
data

src/librustdoc/html/markdown/tests.rs

+23-21
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap};
1+
use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap, Ignore};
22
use super::plain_summary_line;
33
use std::cell::RefCell;
44
use syntax::edition::{Edition, DEFAULT_EDITION};
@@ -26,10 +26,10 @@ fn test_unique_id() {
2626
#[test]
2727
fn test_lang_string_parse() {
2828
fn t(s: &str,
29-
should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
29+
should_panic: bool, no_run: bool, ignore: Ignore, rust: bool, test_harness: bool,
3030
compile_fail: bool, allow_fail: bool, error_codes: Vec<String>,
31-
edition: Option<Edition>) {
32-
assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString {
31+
edition: Option<Edition>) {
32+
assert_eq!(LangString::parse(s, ErrorCodes::Yes, true), LangString {
3333
should_panic,
3434
no_run,
3535
ignore,
@@ -42,6 +42,7 @@ fn test_lang_string_parse() {
4242
edition,
4343
})
4444
}
45+
let ignore_foo = Ignore::Some(vec!("foo".to_string()));
4546

4647
fn v() -> Vec<String> {
4748
Vec::new()
@@ -50,23 +51,24 @@ fn test_lang_string_parse() {
5051
// ignore-tidy-linelength
5152
// marker | should_panic | no_run | ignore | rust | test_harness
5253
// | compile_fail | allow_fail | error_codes | edition
53-
t("", false, false, false, true, false, false, false, v(), None);
54-
t("rust", false, false, false, true, false, false, false, v(), None);
55-
t("sh", false, false, false, false, false, false, false, v(), None);
56-
t("ignore", false, false, true, true, false, false, false, v(), None);
57-
t("should_panic", true, false, false, true, false, false, false, v(), None);
58-
t("no_run", false, true, false, true, false, false, false, v(), None);
59-
t("test_harness", false, false, false, true, true, false, false, v(), None);
60-
t("compile_fail", false, true, false, true, false, true, false, v(), None);
61-
t("allow_fail", false, false, false, true, false, false, true, v(), None);
62-
t("{.no_run .example}", false, true, false, true, false, false, false, v(), None);
63-
t("{.sh .should_panic}", true, false, false, false, false, false, false, v(), None);
64-
t("{.example .rust}", false, false, false, true, false, false, false, v(), None);
65-
t("{.test_harness .rust}", false, false, false, true, true, false, false, v(), None);
66-
t("text, no_run", false, true, false, false, false, false, false, v(), None);
67-
t("text,no_run", false, true, false, false, false, false, false, v(), None);
68-
t("edition2015", false, false, false, true, false, false, false, v(), Some(Edition::Edition2015));
69-
t("edition2018", false, false, false, true, false, false, false, v(), Some(Edition::Edition2018));
54+
t("", false, false, Ignore::None, true, false, false, false, v(), None);
55+
t("rust", false, false, Ignore::None, true, false, false, false, v(), None);
56+
t("sh", false, false, Ignore::None, false, false, false, false, v(), None);
57+
t("ignore", false, false, Ignore::All, true, false, false, false, v(), None);
58+
t("ignore-foo", false, false, ignore_foo, true, false, false, false, v(), None);
59+
t("should_panic", true, false, Ignore::None, true, false, false, false, v(), None);
60+
t("no_run", false, true, Ignore::None, true, false, false, false, v(), None);
61+
t("test_harness", false, false, Ignore::None, true, true, false, false, v(), None);
62+
t("compile_fail", false, true, Ignore::None, true, false, true, false, v(), None);
63+
t("allow_fail", false, false, Ignore::None, true, false, false, true, v(), None);
64+
t("{.no_run .example}", false, true, Ignore::None, true, false, false, false, v(), None);
65+
t("{.sh .should_panic}", true, false, Ignore::None, false, false, false, false, v(), None);
66+
t("{.example .rust}", false, false, Ignore::None, true, false, false, false, v(), None);
67+
t("{.test_harness .rust}", false, false, Ignore::None, true, true, false, false, v(), None);
68+
t("text, no_run", false, true, Ignore::None, false, false, false, false, v(), None);
69+
t("text,no_run", false, true, Ignore::None, false, false, false, false, v(), None);
70+
t("edition2015", false, false, Ignore::None, true, false, false, false, v(), Some(Edition::Edition2015));
71+
t("edition2018", false, false, Ignore::None, true, false, false, false, v(), Some(Edition::Edition2018));
7072
}
7173

7274
#[test]

src/librustdoc/lib.rs

+12
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,18 @@ fn opts() -> Vec<RustcOptGroup> {
355355
"show-coverage",
356356
"calculate percentage of public items with documentation")
357357
}),
358+
unstable("runtool", |o| {
359+
o.optopt("",
360+
"runtool",
361+
"",
362+
"The tool to run tests with when building for a different target than host")
363+
}),
364+
unstable("runtool-arg", |o| {
365+
o.optmulti("",
366+
"runtool-arg",
367+
"",
368+
"One (of possibly many) arguments to pass to the runtool")
369+
}),
358370
]
359371
}
360372

src/librustdoc/test.rs

+36-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_data_structures::sync::Lrc;
22
use rustc_interface::interface;
3+
use rustc_target::spec::TargetTriple;
34
use rustc::hir;
45
use rustc::hir::intravisit;
56
use rustc::session::{self, config, DiagnosticOutput};
@@ -22,7 +23,7 @@ use testing;
2223

2324
use crate::clean::Attributes;
2425
use crate::config::Options;
25-
use crate::html::markdown::{self, ErrorCodes, LangString};
26+
use crate::html::markdown::{self, ErrorCodes, LangString, Ignore};
2627

2728
#[derive(Clone, Default)]
2829
pub struct TestOptions {
@@ -44,7 +45,7 @@ pub fn run(options: Options) -> i32 {
4445
vec![config::CrateType::Dylib]
4546
};
4647

47-
let sessopts = config::Options {
48+
let mut sessopts = config::Options {
4849
maybe_sysroot: options.maybe_sysroot.clone(),
4950
search_paths: options.libs.clone(),
5051
crate_types,
@@ -59,7 +60,7 @@ pub fn run(options: Options) -> i32 {
5960
edition: options.edition,
6061
..config::Options::default()
6162
};
62-
63+
options.target.as_ref().map(|t| { sessopts.target_triple = t.clone() });
6364
let config = interface::Config {
6465
opts: sessopts,
6566
crate_cfg: config::parse_cfgspecs(options.cfgs.clone()),
@@ -181,6 +182,9 @@ fn run_test(
181182
should_panic: bool,
182183
no_run: bool,
183184
as_test_harness: bool,
185+
runtool: Option<String>,
186+
runtool_args: Vec<String>,
187+
target: Option<TargetTriple>,
184188
compile_fail: bool,
185189
mut error_codes: Vec<String>,
186190
opts: &TestOptions,
@@ -315,7 +319,15 @@ fn run_test(
315319
}
316320

317321
// Run the code!
318-
let mut cmd = Command::new(output_file);
322+
let mut cmd;
323+
324+
if let Some(tool) = runtool {
325+
cmd = Command::new(tool);
326+
cmd.arg(output_file);
327+
cmd.args(runtool_args);
328+
}else{
329+
cmd = Command::new(output_file);
330+
}
319331

320332
match cmd.output() {
321333
Err(e) => return Err(TestFailure::ExecutionError(e)),
@@ -661,12 +673,27 @@ impl Tester for Collector {
661673
let opts = self.opts.clone();
662674
let edition = config.edition.unwrap_or(self.options.edition.clone());
663675
let options = self.options.clone();
676+
let maybe_sysroot = self.maybe_sysroot.clone();
677+
let linker = self.linker.clone();
678+
let edition = config.edition.unwrap_or(self.edition);
679+
let persist_doctests = self.persist_doctests.clone();
680+
let runtool = self.runtool.clone();
681+
let runtool_args = self.runtool_args.clone();
682+
let target = self.target.clone();
683+
let target_str = target.as_ref().map(|t| t.to_string());
664684

665685
debug!("creating test {}: {}", name, test);
666686
self.tests.push(testing::TestDescAndFn {
667687
desc: testing::TestDesc {
668-
name: testing::DynTestName(name),
669-
ignore: config.ignore,
688+
name: testing::DynTestName(name.clone()),
689+
ignore: match config.ignore {
690+
Ignore::All => true,
691+
Ignore::None => false,
692+
Ignore::Some(ref ignores) => {
693+
target_str.map_or(false,
694+
|s| ignores.iter().any(|t| s.contains(t)))
695+
},
696+
},
670697
// compiler failures are test failures
671698
should_panic: testing::ShouldPanic::No,
672699
allow_fail: config.allow_fail,
@@ -681,6 +708,9 @@ impl Tester for Collector {
681708
config.should_panic,
682709
config.no_run,
683710
config.test_harness,
711+
runtool,
712+
runtool_args,
713+
target,
684714
config.compile_fail,
685715
config.error_codes,
686716
&opts,

0 commit comments

Comments
 (0)