Skip to content

Commit b5f5149

Browse files
committed
Auto merge of #13490 - weihanglo:rustdoc-shared-libs, r=<try>
fix(doctest): search native libs in build script outputs
2 parents f415cb2 + 34215b1 commit b5f5149

File tree

2 files changed

+86
-6
lines changed

2 files changed

+86
-6
lines changed

src/cargo/core/compiler/compilation.rs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,25 @@ use crate::core::compiler::{CompileKind, Metadata, Unit};
1313
use crate::core::Package;
1414
use crate::util::{config, CargoResult, GlobalContext};
1515

16+
/// Represents the kind of process we are creating.
17+
#[derive(Debug)]
18+
enum ToolKind {
19+
/// See [`Compilation::rustc_process`].
20+
Rustc,
21+
/// See [`Compilation::rustdoc_process`].
22+
Rustdoc,
23+
/// See [`Compilation::host_process`].
24+
HostProcess,
25+
/// See [`Compilation::target_process`].
26+
TargetProcess,
27+
}
28+
29+
impl ToolKind {
30+
fn is_rustc_tool(&self) -> bool {
31+
matches!(self, ToolKind::Rustc | ToolKind::Rustdoc)
32+
}
33+
}
34+
1635
/// Structure with enough information to run `rustdoc --test`.
1736
pub struct Doctest {
1837
/// What's being doctested
@@ -176,7 +195,7 @@ impl<'gctx> Compilation<'gctx> {
176195
};
177196

178197
let cmd = fill_rustc_tool_env(rustc, unit);
179-
self.fill_env(cmd, &unit.pkg, None, unit.kind, true)
198+
self.fill_env(cmd, &unit.pkg, None, unit.kind, ToolKind::Rustc)
180199
}
181200

182201
/// Returns a [`ProcessBuilder`] for running `rustdoc`.
@@ -187,7 +206,7 @@ impl<'gctx> Compilation<'gctx> {
187206
) -> CargoResult<ProcessBuilder> {
188207
let rustdoc = ProcessBuilder::new(&*self.gctx.rustdoc()?);
189208
let cmd = fill_rustc_tool_env(rustdoc, unit);
190-
let mut cmd = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, true)?;
209+
let mut cmd = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, ToolKind::Rustdoc)?;
191210
cmd.retry_with_argfile(true);
192211
unit.target.edition().cmd_edition_arg(&mut cmd);
193212

@@ -214,7 +233,7 @@ impl<'gctx> Compilation<'gctx> {
214233
pkg,
215234
None,
216235
CompileKind::Host,
217-
false,
236+
ToolKind::HostProcess,
218237
)
219238
}
220239

@@ -249,7 +268,8 @@ impl<'gctx> Compilation<'gctx> {
249268
} else {
250269
ProcessBuilder::new(cmd)
251270
};
252-
let mut builder = self.fill_env(builder, pkg, script_meta, kind, false)?;
271+
let tool_kind = ToolKind::TargetProcess;
272+
let mut builder = self.fill_env(builder, pkg, script_meta, kind, tool_kind)?;
253273

254274
if let Some(client) = self.gctx.jobserver_from_env() {
255275
builder.inherit_jobserver(client);
@@ -269,10 +289,22 @@ impl<'gctx> Compilation<'gctx> {
269289
pkg: &Package,
270290
script_meta: Option<Metadata>,
271291
kind: CompileKind,
272-
is_rustc_tool: bool,
292+
tool_kind: ToolKind,
273293
) -> CargoResult<ProcessBuilder> {
274294
let mut search_path = Vec::new();
275-
if is_rustc_tool {
295+
if tool_kind.is_rustc_tool() {
296+
if matches!(tool_kind, ToolKind::Rustdoc) {
297+
// HACK: `rustdoc --test` not only compiles but executes doctests.
298+
// Ideally only execution phase should have search paths appended,
299+
// so the executions can find native libs just like other tests.
300+
// However, there is no way to separate these two phase, so this
301+
// hack is added for both phases.
302+
// TODO: handle doctest-xcompile
303+
search_path.extend(super::filter_dynamic_search_path(
304+
self.native_dirs.iter(),
305+
&self.root_output[&CompileKind::Host],
306+
));
307+
}
276308
search_path.push(self.deps_output[&CompileKind::Host].clone());
277309
} else {
278310
search_path.extend(super::filter_dynamic_search_path(

tests/testsuite/test.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use cargo_test_support::{
77
};
88
use cargo_test_support::{cross_compile, paths};
99
use cargo_test_support::{rustc_host, rustc_host_env, sleep_ms};
10+
use cargo_util::paths::dylib_path_envvar;
1011
use std::fs;
1112

1213
#[cargo_test]
@@ -2767,6 +2768,53 @@ fn only_test_docs() {
27672768
.run();
27682769
}
27692770

2771+
#[cargo_test]
2772+
fn doctest_with_library_paths() {
2773+
let p = project();
2774+
// Only link search directories within the target output directory are
2775+
// propagated through to dylib_path_envvar() (see #3366).
2776+
let dir1 = p.target_debug_dir().join("foo\\backslash");
2777+
let dir2 = p.target_debug_dir().join("dir=containing=equal=signs");
2778+
2779+
let p = p
2780+
.file("Cargo.toml", &basic_manifest("foo", "0.0.0"))
2781+
.file(
2782+
"build.rs",
2783+
&format!(
2784+
r##"
2785+
fn main() {{
2786+
println!(r#"cargo::rustc-link-search=native={}"#);
2787+
println!(r#"cargo::rustc-link-search={}"#);
2788+
}}
2789+
"##,
2790+
dir1.display(),
2791+
dir2.display()
2792+
),
2793+
)
2794+
.file(
2795+
"src/lib.rs",
2796+
&format!(
2797+
r##"
2798+
/// ```
2799+
/// foo::assert_search_path();
2800+
/// ```
2801+
pub fn assert_search_path() {{
2802+
let search_path = std::env::var_os("{}").unwrap();
2803+
let paths = std::env::split_paths(&search_path).collect::<Vec<_>>();
2804+
assert!(paths.contains(&r#"{}"#.into()));
2805+
assert!(paths.contains(&r#"{}"#.into()));
2806+
}}
2807+
"##,
2808+
dylib_path_envvar(),
2809+
dir1.display(),
2810+
dir2.display()
2811+
),
2812+
)
2813+
.build();
2814+
2815+
p.cargo("test --doc").run();
2816+
}
2817+
27702818
#[cargo_test]
27712819
fn test_panic_abort_with_dep() {
27722820
let p = project()

0 commit comments

Comments
 (0)