]> git.proxmox.com Git - cargo.git/commitdiff
Fix LTO with doctests.
authorEric Huss <eric@huss.org>
Thu, 27 Aug 2020 23:41:43 +0000 (16:41 -0700)
committerEric Huss <eric@huss.org>
Thu, 27 Aug 2020 23:41:43 +0000 (16:41 -0700)
src/cargo/core/compiler/context/mod.rs
src/cargo/core/compiler/mod.rs
src/cargo/core/profiles.rs
tests/testsuite/lto.rs

index 52b954dd12d13b5756ed6ac9c7e568e3f8148264..82831f42314048699d3495cb943bb0789b36a296 100644 (file)
@@ -210,7 +210,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
             // Collect information for `rustdoc --test`.
             if unit.mode.is_doc_test() {
                 let mut unstable_opts = false;
-                let args = compiler::extern_args(&self, unit, &mut unstable_opts)?;
+                let mut args = compiler::extern_args(&self, unit, &mut unstable_opts)?;
+                args.extend(compiler::lto_args(&self, unit));
                 self.compilation.to_doc_test.push(compilation::Doctest {
                     unit: unit.clone(),
                     args,
index 97012d2ee16b7581aef8adbe5f724e98a462c265..5c118454979b2cca2c8c659f5c2db0e78a57c61d 100644 (file)
@@ -797,28 +797,9 @@ fn build_base_args(
         cmd.arg("-C").arg(format!("panic={}", panic));
     }
 
-    match cx.lto[unit] {
-        lto::Lto::Run(None) => {
-            cmd.arg("-C").arg("lto");
-        }
-        lto::Lto::Run(Some(s)) => {
-            cmd.arg("-C").arg(format!("lto={}", s));
-        }
-        lto::Lto::Off => {
-            cmd.arg("-C").arg("lto=off");
-        }
-        lto::Lto::ObjectAndBitcode => {} // this is rustc's default
-        lto::Lto::OnlyBitcode => {
-            cmd.arg("-C").arg("linker-plugin-lto");
-        }
-        lto::Lto::OnlyObject => {
-            cmd.arg("-C").arg("embed-bitcode=no");
-        }
-    }
+    cmd.args(&lto_args(cx, unit));
 
     if let Some(n) = codegen_units {
-        // There are some restrictions with LTO and codegen-units, so we
-        // only add codegen units when LTO is not used.
         cmd.arg("-C").arg(&format!("codegen-units={}", n));
     }
 
@@ -946,6 +927,23 @@ fn build_base_args(
     Ok(())
 }
 
+fn lto_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec<OsString> {
+    let mut result = Vec::new();
+    let mut push = |arg: &str| {
+        result.push(OsString::from("-C"));
+        result.push(OsString::from(arg));
+    };
+    match cx.lto[unit] {
+        lto::Lto::Run(None) => push("lto"),
+        lto::Lto::Run(Some(s)) => push(&format!("lto={}", s)),
+        lto::Lto::Off => push("lto=off"),
+        lto::Lto::ObjectAndBitcode => {} // this is rustc's default
+        lto::Lto::OnlyBitcode => push("linker-plugin-lto"),
+        lto::Lto::OnlyObject => push("embed-bitcode=no"),
+    }
+    result
+}
+
 fn build_deps_args(
     cmd: &mut ProcessBuilder,
     cx: &mut Context<'_, '_>,
index 6bae0337f7ce8cdaed4755ce6600d97821af966e..d4859cb2078ef33fc36e83eae8b231265c922943 100644 (file)
@@ -299,7 +299,7 @@ impl Profiles {
             let release = matches!(self.requested_profile.as_str(), "release" | "bench");
 
             match mode {
-                CompileMode::Test | CompileMode::Bench => {
+                CompileMode::Test | CompileMode::Bench | CompileMode::Doctest => {
                     if release {
                         (
                             InternedString::new("bench"),
@@ -312,10 +312,7 @@ impl Profiles {
                         )
                     }
                 }
-                CompileMode::Build
-                | CompileMode::Check { .. }
-                | CompileMode::Doctest
-                | CompileMode::RunCustomBuild => {
+                CompileMode::Build | CompileMode::Check { .. } | CompileMode::RunCustomBuild => {
                     // Note: `RunCustomBuild` doesn't normally use this code path.
                     // `build_unit_profiles` normally ensures that it selects the
                     // ancestor's profile. However, `cargo clean -p` can hit this
index 9488b271b203f15b1b342ec5cc63e69cdf6179df..87524c4815a3a2f2b1ae3675dd23b063d09c712f 100644 (file)
@@ -1,6 +1,6 @@
 use cargo::core::compiler::Lto;
 use cargo_test_support::registry::Package;
-use cargo_test_support::{project, Project};
+use cargo_test_support::{basic_manifest, project, Project};
 use std::process::Output;
 
 #[cargo_test]
@@ -514,16 +514,19 @@ fn cdylib_and_rlib() {
     p.cargo("test --release -v --manifest-path bar/Cargo.toml")
         .with_stderr_unordered(
             "\
-[FRESH] registry v0.0.1
-[FRESH] registry-shared v0.0.1
+[COMPILING] registry v0.0.1
+[COMPILING] registry-shared v0.0.1
+[RUNNING] `rustc --crate-name registry [..]-C embed-bitcode=no[..]
+[RUNNING] `rustc --crate-name registry_shared [..]-C embed-bitcode=no[..]
 [COMPILING] bar [..]
+[RUNNING] `rustc --crate-name bar [..]--crate-type cdylib --crate-type rlib [..]-C embed-bitcode=no[..]
 [RUNNING] `rustc --crate-name bar [..]-C embed-bitcode=no --test[..]
 [RUNNING] `rustc --crate-name b [..]-C embed-bitcode=no --test[..]
 [FINISHED] [..]
-[RUNNING] [..]
-[RUNNING] [..]
+[RUNNING] [..]target/release/deps/bar-[..]
+[RUNNING] [..]target/release/deps/b-[..]
 [DOCTEST] bar
-[RUNNING] `rustdoc --crate-type cdylib --crate-type rlib --test [..]
+[RUNNING] `rustdoc --crate-type cdylib --crate-type rlib --test [..]-C embed-bitcode=no[..]
 ",
         )
         .run();
@@ -627,7 +630,7 @@ fn test_profile() {
 [COMPILING] bar v0.0.1
 [RUNNING] `rustc --crate-name bar [..]crate-type lib[..]
 [COMPILING] foo [..]
-[RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no[..]
+[RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C linker-plugin-lto[..]
 [RUNNING] `rustc --crate-name foo [..]--emit=dep-info,link -C lto=thin [..]--test[..]
 [FINISHED] [..]
 [RUNNING] [..]
@@ -680,7 +683,7 @@ fn dev_profile() {
 [COMPILING] bar v0.0.1
 [RUNNING] `rustc --crate-name bar [..]crate-type lib[..]
 [COMPILING] foo [..]
-[RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C linker-plugin-lto [..]
+[RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no [..]
 [RUNNING] `rustc --crate-name foo [..]--emit=dep-info,link -C embed-bitcode=no [..]--test[..]
 [FINISHED] [..]
 [RUNNING] [..]
@@ -689,3 +692,57 @@ fn dev_profile() {
 ")
         .run();
 }
+
+#[cargo_test]
+fn doctest() {
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+                [package]
+                name = "foo"
+                version = "0.1.0"
+                edition = "2018"
+
+                [profile.release]
+                lto = true
+
+                [dependencies]
+                bar = { path = "bar" }
+            "#,
+        )
+        .file(
+            "src/lib.rs",
+            r#"
+                /// Foo!
+                ///
+                /// ```
+                /// foo::foo();
+                /// ```
+                pub fn foo() { bar::bar(); }
+            "#,
+        )
+        .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
+        .file(
+            "bar/src/lib.rs",
+            r#"
+                pub fn bar() { println!("hi!"); }
+            "#,
+        )
+        .build();
+
+    p.cargo("test --doc --release -v")
+        .with_stderr_contains("[..]`rustc --crate-name bar[..]-C embed-bitcode=no[..]")
+        .with_stderr_contains("[..]`rustc --crate-name foo[..]-C embed-bitcode=no[..]")
+        // embed-bitcode should be harmless here
+        .with_stderr_contains("[..]`rustdoc [..]-C embed-bitcode=no[..]")
+        .run();
+
+    // Try with bench profile.
+    p.cargo("test --doc --release -v")
+        .env("CARGO_PROFILE_BENCH_LTO", "true")
+        .with_stderr_contains("[..]`rustc --crate-name bar[..]-C linker-plugin-lto[..]")
+        .with_stderr_contains("[..]`rustc --crate-name foo[..]-C linker-plugin-lto[..]")
+        .with_stderr_contains("[..]`rustdoc [..]-C lto[..]")
+        .run();
+}