Skip to content

Commit 5bbad10

Browse files
committed
Fix LTO with doctests.
1 parent 888ae72 commit 5bbad10

File tree

4 files changed

+87
-34
lines changed

4 files changed

+87
-34
lines changed

src/cargo/core/compiler/context/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
210210
// Collect information for `rustdoc --test`.
211211
if unit.mode.is_doc_test() {
212212
let mut unstable_opts = false;
213-
let args = compiler::extern_args(&self, unit, &mut unstable_opts)?;
213+
let mut args = compiler::extern_args(&self, unit, &mut unstable_opts)?;
214+
args.extend(compiler::lto_args(&self, unit));
214215
self.compilation.to_doc_test.push(compilation::Doctest {
215216
unit: unit.clone(),
216217
args,

src/cargo/core/compiler/mod.rs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -797,28 +797,9 @@ fn build_base_args(
797797
cmd.arg("-C").arg(format!("panic={}", panic));
798798
}
799799

800-
match cx.lto[unit] {
801-
lto::Lto::Run(None) => {
802-
cmd.arg("-C").arg("lto");
803-
}
804-
lto::Lto::Run(Some(s)) => {
805-
cmd.arg("-C").arg(format!("lto={}", s));
806-
}
807-
lto::Lto::Off => {
808-
cmd.arg("-C").arg("lto=off");
809-
}
810-
lto::Lto::ObjectAndBitcode => {} // this is rustc's default
811-
lto::Lto::OnlyBitcode => {
812-
cmd.arg("-C").arg("linker-plugin-lto");
813-
}
814-
lto::Lto::OnlyObject => {
815-
cmd.arg("-C").arg("embed-bitcode=no");
816-
}
817-
}
800+
cmd.args(&lto_args(cx, unit));
818801

819802
if let Some(n) = codegen_units {
820-
// There are some restrictions with LTO and codegen-units, so we
821-
// only add codegen units when LTO is not used.
822803
cmd.arg("-C").arg(&format!("codegen-units={}", n));
823804
}
824805

@@ -946,6 +927,23 @@ fn build_base_args(
946927
Ok(())
947928
}
948929

930+
fn lto_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec<OsString> {
931+
let mut result = Vec::new();
932+
let mut push = |arg: &str| {
933+
result.push(OsString::from("-C"));
934+
result.push(OsString::from(arg));
935+
};
936+
match cx.lto[unit] {
937+
lto::Lto::Run(None) => push("lto"),
938+
lto::Lto::Run(Some(s)) => push(&format!("lto={}", s)),
939+
lto::Lto::Off => push("lto=off"),
940+
lto::Lto::ObjectAndBitcode => {} // this is rustc's default
941+
lto::Lto::OnlyBitcode => push("linker-plugin-lto"),
942+
lto::Lto::OnlyObject => push("embed-bitcode=no"),
943+
}
944+
result
945+
}
946+
949947
fn build_deps_args(
950948
cmd: &mut ProcessBuilder,
951949
cx: &mut Context<'_, '_>,

src/cargo/core/profiles.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ impl Profiles {
299299
let release = matches!(self.requested_profile.as_str(), "release" | "bench");
300300

301301
match mode {
302-
CompileMode::Test | CompileMode::Bench => {
302+
CompileMode::Test | CompileMode::Bench | CompileMode::Doctest => {
303303
if release {
304304
(
305305
InternedString::new("bench"),
@@ -312,10 +312,7 @@ impl Profiles {
312312
)
313313
}
314314
}
315-
CompileMode::Build
316-
| CompileMode::Check { .. }
317-
| CompileMode::Doctest
318-
| CompileMode::RunCustomBuild => {
315+
CompileMode::Build | CompileMode::Check { .. } | CompileMode::RunCustomBuild => {
319316
// Note: `RunCustomBuild` doesn't normally use this code path.
320317
// `build_unit_profiles` normally ensures that it selects the
321318
// ancestor's profile. However, `cargo clean -p` can hit this

tests/testsuite/lto.rs

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use cargo::core::compiler::Lto;
22
use cargo_test_support::registry::Package;
3-
use cargo_test_support::{project, Project};
3+
use cargo_test_support::{basic_manifest, project, Project};
44
use std::process::Output;
55

66
#[cargo_test]
@@ -514,16 +514,19 @@ fn cdylib_and_rlib() {
514514
p.cargo("test --release -v --manifest-path bar/Cargo.toml")
515515
.with_stderr_unordered(
516516
"\
517-
[FRESH] registry v0.0.1
518-
[FRESH] registry-shared v0.0.1
517+
[COMPILING] registry v0.0.1
518+
[COMPILING] registry-shared v0.0.1
519+
[RUNNING] `rustc --crate-name registry [..]-C embed-bitcode=no[..]
520+
[RUNNING] `rustc --crate-name registry_shared [..]-C embed-bitcode=no[..]
519521
[COMPILING] bar [..]
522+
[RUNNING] `rustc --crate-name bar [..]--crate-type cdylib --crate-type rlib [..]-C embed-bitcode=no[..]
520523
[RUNNING] `rustc --crate-name bar [..]-C embed-bitcode=no --test[..]
521524
[RUNNING] `rustc --crate-name b [..]-C embed-bitcode=no --test[..]
522525
[FINISHED] [..]
523-
[RUNNING] [..]
524-
[RUNNING] [..]
526+
[RUNNING] [..]target/release/deps/bar-[..]
527+
[RUNNING] [..]target/release/deps/b-[..]
525528
[DOCTEST] bar
526-
[RUNNING] `rustdoc --crate-type cdylib --crate-type rlib --test [..]
529+
[RUNNING] `rustdoc --crate-type cdylib --crate-type rlib --test [..]-C embed-bitcode=no[..]
527530
",
528531
)
529532
.run();
@@ -627,7 +630,7 @@ fn test_profile() {
627630
[COMPILING] bar v0.0.1
628631
[RUNNING] `rustc --crate-name bar [..]crate-type lib[..]
629632
[COMPILING] foo [..]
630-
[RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no[..]
633+
[RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C linker-plugin-lto[..]
631634
[RUNNING] `rustc --crate-name foo [..]--emit=dep-info,link -C lto=thin [..]--test[..]
632635
[FINISHED] [..]
633636
[RUNNING] [..]
@@ -680,7 +683,7 @@ fn dev_profile() {
680683
[COMPILING] bar v0.0.1
681684
[RUNNING] `rustc --crate-name bar [..]crate-type lib[..]
682685
[COMPILING] foo [..]
683-
[RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C linker-plugin-lto [..]
686+
[RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no [..]
684687
[RUNNING] `rustc --crate-name foo [..]--emit=dep-info,link -C embed-bitcode=no [..]--test[..]
685688
[FINISHED] [..]
686689
[RUNNING] [..]
@@ -689,3 +692,57 @@ fn dev_profile() {
689692
")
690693
.run();
691694
}
695+
696+
#[cargo_test]
697+
fn doctest() {
698+
let p = project()
699+
.file(
700+
"Cargo.toml",
701+
r#"
702+
[package]
703+
name = "foo"
704+
version = "0.1.0"
705+
edition = "2018"
706+
707+
[profile.release]
708+
lto = true
709+
710+
[dependencies]
711+
bar = { path = "bar" }
712+
"#,
713+
)
714+
.file(
715+
"src/lib.rs",
716+
r#"
717+
/// Foo!
718+
///
719+
/// ```
720+
/// foo::foo();
721+
/// ```
722+
pub fn foo() { bar::bar(); }
723+
"#,
724+
)
725+
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
726+
.file(
727+
"bar/src/lib.rs",
728+
r#"
729+
pub fn bar() { println!("hi!"); }
730+
"#,
731+
)
732+
.build();
733+
734+
p.cargo("test --doc --release -v")
735+
.with_stderr_contains("[..]`rustc --crate-name bar[..]-C embed-bitcode=no[..]")
736+
.with_stderr_contains("[..]`rustc --crate-name foo[..]-C embed-bitcode=no[..]")
737+
// embed-bitcode should be harmless here
738+
.with_stderr_contains("[..]`rustdoc [..]-C embed-bitcode=no[..]")
739+
.run();
740+
741+
// Try with bench profile.
742+
p.cargo("test --doc --release -v")
743+
.env("CARGO_PROFILE_BENCH_LTO", "true")
744+
.with_stderr_contains("[..]`rustc --crate-name bar[..]-C linker-plugin-lto[..]")
745+
.with_stderr_contains("[..]`rustc --crate-name foo[..]-C linker-plugin-lto[..]")
746+
.with_stderr_contains("[..]`rustdoc [..]-C lto[..]")
747+
.run();
748+
}

0 commit comments

Comments
 (0)