Skip to content

Commit aa8f0d9

Browse files
committed
Added ability to crosscompile doctests
1 parent e79b2a1 commit aa8f0d9

File tree

6 files changed

+119
-35
lines changed

6 files changed

+119
-35
lines changed

src/librustdoc/config.rs

+10
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ pub struct Options {
7171
/// Optional path to persist the doctest executables to, defaults to a
7272
/// temporary directory if not set.
7373
pub persist_doctests: Option<PathBuf>,
74+
/// Runtool to run doctests with
75+
pub runtool: Option<String>,
76+
/// Arguments to pass to the runtool
77+
pub runtool_args: Vec<String>,
7478

7579
// Options that affect the documentation process
7680

@@ -134,6 +138,8 @@ impl fmt::Debug for Options {
134138
.field("show_coverage", &self.show_coverage)
135139
.field("crate_version", &self.crate_version)
136140
.field("render_options", &self.render_options)
141+
.field("runtool", &self.runtool)
142+
.field("runtool_args", &self.runtool_args)
137143
.finish()
138144
}
139145
}
@@ -476,6 +482,8 @@ impl Options {
476482
let generate_search_filter = !matches.opt_present("disable-per-crate-search");
477483
let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from);
478484
let generate_redirect_pages = matches.opt_present("generate-redirect-pages");
485+
let runtool = matches.opt_str("runtool");
486+
let runtool_args = matches.opt_strs("runtool-arg");
479487

480488
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
481489

@@ -503,6 +511,8 @@ impl Options {
503511
show_coverage,
504512
crate_version,
505513
persist_doctests,
514+
runtool,
515+
runtool_args,
506516
render_options: RenderOptions {
507517
output,
508518
external_html,

src/librustdoc/html/markdown.rs

+28-6
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
256256
))
257257
});
258258

259-
let tooltip = if ignore {
259+
let tooltip = if ignore != Ignore::None {
260260
Some(("This example is not tested".to_owned(), "ignore"))
261261
} else if compile_fail {
262262
Some(("This example deliberately fails to compile".to_owned(), "compile_fail"))
@@ -270,7 +270,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
270270
s.push_str(&highlight::render_with_highlighting(
271271
&text,
272272
Some(&format!("rust-example-rendered{}",
273-
if ignore { " ignore" }
273+
if ignore != Ignore::None { " ignore" }
274274
else if compile_fail { " compile_fail" }
275275
else if explicit_edition { " edition " }
276276
else { "" })),
@@ -281,7 +281,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
281281
s.push_str(&highlight::render_with_highlighting(
282282
&text,
283283
Some(&format!("rust-example-rendered{}",
284-
if ignore { " ignore" }
284+
if ignore != Ignore::None { " ignore" }
285285
else if compile_fail { " compile_fail" }
286286
else if explicit_edition { " edition " }
287287
else { "" })),
@@ -592,7 +592,7 @@ pub struct LangString {
592592
original: String,
593593
pub should_panic: bool,
594594
pub no_run: bool,
595-
pub ignore: bool,
595+
pub ignore: Ignore,
596596
pub rust: bool,
597597
pub test_harness: bool,
598598
pub compile_fail: bool,
@@ -601,13 +601,20 @@ pub struct LangString {
601601
pub edition: Option<Edition>
602602
}
603603

604+
#[derive(Eq, PartialEq, Clone, Debug)]
605+
pub enum Ignore {
606+
All,
607+
None,
608+
Some(Vec<String>),
609+
}
610+
604611
impl LangString {
605612
fn all_false() -> LangString {
606613
LangString {
607614
original: String::new(),
608615
should_panic: false,
609616
no_run: false,
610-
ignore: false,
617+
ignore: Ignore::None,
611618
rust: true, // NB This used to be `notrust = false`
612619
test_harness: false,
613620
compile_fail: false,
@@ -622,6 +629,7 @@ impl LangString {
622629
let mut seen_rust_tags = false;
623630
let mut seen_other_tags = false;
624631
let mut data = LangString::all_false();
632+
let mut ignores = vec![];
625633

626634
data.original = string.to_owned();
627635
let tokens = string.split(|c: char|
@@ -636,7 +644,11 @@ impl LangString {
636644
seen_rust_tags = seen_other_tags == false;
637645
}
638646
"no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; }
639-
"ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; }
647+
"ignore" => { data.ignore = Ignore::All; seen_rust_tags = !seen_other_tags; }
648+
x if x.starts_with("ignore-") => {
649+
ignores.push(x.trim_start_matches("ignore-").to_owned());
650+
seen_rust_tags = !seen_other_tags;
651+
}
640652
"allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; }
641653
"rust" => { data.rust = true; seen_rust_tags = true; }
642654
"test_harness" => {
@@ -665,6 +677,16 @@ impl LangString {
665677
}
666678
}
667679

680+
match data.ignore {
681+
Ignore::All => {},
682+
Ignore::None => {
683+
if !ignores.is_empty() {
684+
data.ignore = Ignore::Some(ignores);
685+
}
686+
},
687+
_ => unreachable!(),
688+
}
689+
668690
data.rust &= !seen_other_tags || seen_rust_tags;
669691

670692
data

src/librustdoc/html/markdown/tests.rs

+23-21
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
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};
55

66
#[test]
77
fn test_lang_string_parse() {
88
fn t(s: &str,
9-
should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
9+
should_panic: bool, no_run: bool, ignore: Ignore, rust: bool, test_harness: bool,
1010
compile_fail: bool, allow_fail: bool, error_codes: Vec<String>,
11-
edition: Option<Edition>) {
12-
assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString {
11+
edition: Option<Edition>) {
12+
assert_eq!(LangString::parse(s, ErrorCodes::Yes, true), LangString {
1313
should_panic,
1414
no_run,
1515
ignore,
@@ -22,6 +22,7 @@ fn test_lang_string_parse() {
2222
edition,
2323
})
2424
}
25+
let ignore_foo = Ignore::Some(vec!("foo".to_string()));
2526

2627
fn v() -> Vec<String> {
2728
Vec::new()
@@ -30,23 +31,24 @@ fn test_lang_string_parse() {
3031
// ignore-tidy-linelength
3132
// marker | should_panic | no_run | ignore | rust | test_harness
3233
// | compile_fail | allow_fail | error_codes | edition
33-
t("", false, false, false, true, false, false, false, v(), None);
34-
t("rust", false, false, false, true, false, false, false, v(), None);
35-
t("sh", false, false, false, false, false, false, false, v(), None);
36-
t("ignore", false, false, true, true, false, false, false, v(), None);
37-
t("should_panic", true, false, false, true, false, false, false, v(), None);
38-
t("no_run", false, true, false, true, false, false, false, v(), None);
39-
t("test_harness", false, false, false, true, true, false, false, v(), None);
40-
t("compile_fail", false, true, false, true, false, true, false, v(), None);
41-
t("allow_fail", false, false, false, true, false, false, true, v(), None);
42-
t("{.no_run .example}", false, true, false, true, false, false, false, v(), None);
43-
t("{.sh .should_panic}", true, false, false, false, false, false, false, v(), None);
44-
t("{.example .rust}", false, false, false, true, false, false, false, v(), None);
45-
t("{.test_harness .rust}", false, false, false, true, true, false, false, v(), None);
46-
t("text, no_run", false, true, false, false, false, false, false, v(), None);
47-
t("text,no_run", false, true, false, false, false, false, false, v(), None);
48-
t("edition2015", false, false, false, true, false, false, false, v(), Some(Edition::Edition2015));
49-
t("edition2018", false, false, false, true, false, false, false, v(), Some(Edition::Edition2018));
34+
t("", false, false, Ignore::None, true, false, false, false, v(), None);
35+
t("rust", false, false, Ignore::None, true, false, false, false, v(), None);
36+
t("sh", false, false, Ignore::None, false, false, false, false, v(), None);
37+
t("ignore", false, false, Ignore::All, true, false, false, false, v(), None);
38+
t("ignore-foo", false, false, ignore_foo, true, false, false, false, v(), None);
39+
t("should_panic", true, false, Ignore::None, true, false, false, false, v(), None);
40+
t("no_run", false, true, Ignore::None, true, false, false, false, v(), None);
41+
t("test_harness", false, false, Ignore::None, true, true, false, false, v(), None);
42+
t("compile_fail", false, true, Ignore::None, true, false, true, false, v(), None);
43+
t("allow_fail", false, false, Ignore::None, true, false, false, true, v(), None);
44+
t("{.no_run .example}", false, true, Ignore::None, true, false, false, false, v(), None);
45+
t("{.sh .should_panic}", true, false, Ignore::None, false, false, false, false, v(), None);
46+
t("{.example .rust}", false, false, Ignore::None, true, false, false, false, v(), None);
47+
t("{.test_harness .rust}", false, false, Ignore::None, true, true, false, false, v(), None);
48+
t("text, no_run", false, true, Ignore::None, false, false, false, false, v(), None);
49+
t("text,no_run", false, true, Ignore::None, false, false, false, false, v(), None);
50+
t("edition2015", false, false, Ignore::None, true, false, false, false, v(), Some(Edition::Edition2015));
51+
t("edition2018", false, false, Ignore::None, true, false, false, false, v(), Some(Edition::Edition2018));
5052
}
5153

5254
#[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/markdown.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ pub fn test(mut options: Options, diag: &errors::Handler) -> i32 {
146146
options.libs, options.codegen_options, options.externs,
147147
true, opts, options.maybe_sysroot, None,
148148
Some(options.input),
149-
options.linker, options.edition, options.persist_doctests);
149+
options.linker, options.edition, options.persist_doctests,
150+
options.runtool, options.runtool_args, options.target);
150151
collector.set_position(DUMMY_SP);
151152
let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
152153

src/librustdoc/test.rs

+44-7
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::hir::def_id::LOCAL_CRATE;
@@ -27,7 +28,7 @@ use testing;
2728

2829
use crate::clean::Attributes;
2930
use crate::config::Options;
30-
use crate::html::markdown::{self, ErrorCodes, LangString};
31+
use crate::html::markdown::{self, ErrorCodes, LangString, Ignore};
3132

3233
#[derive(Clone, Default)]
3334
pub struct TestOptions {
@@ -43,7 +44,7 @@ pub struct TestOptions {
4344
pub fn run(options: Options) -> i32 {
4445
let input = config::Input::File(options.input.clone());
4546

46-
let sessopts = config::Options {
47+
let mut sessopts = config::Options {
4748
maybe_sysroot: options.maybe_sysroot.clone().or_else(
4849
|| Some(env::current_exe().unwrap().parent().unwrap().parent().unwrap().to_path_buf())),
4950
search_paths: options.libs.clone(),
@@ -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()),
@@ -96,6 +97,9 @@ pub fn run(options: Options) -> i32 {
9697
options.linker,
9798
options.edition,
9899
options.persist_doctests,
100+
options.runtool,
101+
options.runtool_args,
102+
options.target.clone(),
99103
);
100104

101105
let mut global_ctxt = compiler.global_ctxt()?.take();
@@ -191,6 +195,9 @@ fn run_test(
191195
should_panic: bool,
192196
no_run: bool,
193197
as_test_harness: bool,
198+
runtool: Option<String>,
199+
runtool_args: Vec<String>,
200+
target: Option<TargetTriple>,
194201
compile_fail: bool,
195202
mut error_codes: Vec<String>,
196203
opts: &TestOptions,
@@ -236,6 +243,7 @@ fn run_test(
236243
..cg
237244
},
238245
test: as_test_harness,
246+
target_triple: target.unwrap_or(TargetTriple::from_triple(config::host_triple())),
239247
unstable_features: UnstableFeatures::from_environment(),
240248
debugging_opts: config::DebuggingOptions {
241249
..config::basic_debugging_options()
@@ -362,7 +370,15 @@ fn run_test(
362370
}
363371

364372
// Run the code!
365-
let mut cmd = Command::new(output_file);
373+
let mut cmd;
374+
375+
if let Some(tool) = runtool {
376+
cmd = Command::new(tool);
377+
cmd.arg(output_file);
378+
cmd.args(runtool_args);
379+
}else{
380+
cmd = Command::new(output_file);
381+
}
366382

367383
match cmd.output() {
368384
Err(e) => return Err(TestFailure::ExecutionError(e)),
@@ -667,14 +683,18 @@ pub struct Collector {
667683
linker: Option<PathBuf>,
668684
edition: Edition,
669685
persist_doctests: Option<PathBuf>,
686+
runtool: Option<String>,
687+
runtool_args: Vec<String>,
688+
target: Option<TargetTriple>,
670689
}
671690

672691
impl Collector {
673692
pub fn new(cratename: String, cfgs: Vec<String>, libs: Vec<SearchPath>, cg: CodegenOptions,
674693
externs: Externs, use_headers: bool, opts: TestOptions,
675694
maybe_sysroot: Option<PathBuf>, source_map: Option<Lrc<SourceMap>>,
676695
filename: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition,
677-
persist_doctests: Option<PathBuf>) -> Collector {
696+
persist_doctests: Option<PathBuf>, runtool: Option<String>,
697+
runtool_args: Vec<String>, target: Option<TargetTriple>) -> Collector {
678698
Collector {
679699
tests: Vec::new(),
680700
names: Vec::new(),
@@ -692,6 +712,9 @@ impl Collector {
692712
linker,
693713
edition,
694714
persist_doctests,
715+
runtool,
716+
runtool_args,
717+
target,
695718
}
696719
}
697720

@@ -736,12 +759,23 @@ impl Tester for Collector {
736759
let linker = self.linker.clone();
737760
let edition = config.edition.unwrap_or(self.edition);
738761
let persist_doctests = self.persist_doctests.clone();
762+
let runtool = self.runtool.clone();
763+
let runtool_args = self.runtool_args.clone();
764+
let target = self.target.clone();
765+
let target_str = target.as_ref().map(|t| t.to_string());
739766

740767
debug!("Creating test {}: {}", name, test);
741768
self.tests.push(testing::TestDescAndFn {
742769
desc: testing::TestDesc {
743-
name: testing::DynTestName(name),
744-
ignore: config.ignore,
770+
name: testing::DynTestName(name.clone()),
771+
ignore: match config.ignore {
772+
Ignore::All => true,
773+
Ignore::None => false,
774+
Ignore::Some(ref ignores) => {
775+
target_str.map_or(false,
776+
|s| ignores.iter().any(|t| s.contains(t)))
777+
},
778+
},
745779
// compiler failures are test failures
746780
should_panic: testing::ShouldPanic::No,
747781
allow_fail: config.allow_fail,
@@ -759,6 +793,9 @@ impl Tester for Collector {
759793
config.should_panic,
760794
config.no_run,
761795
config.test_harness,
796+
runtool,
797+
runtool_args,
798+
target,
762799
config.compile_fail,
763800
config.error_codes,
764801
&opts,

0 commit comments

Comments
 (0)