about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs67
1 files changed, 66 insertions, 1 deletions
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index dcea9f5f7d1..1cabd1c39f1 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -3,12 +3,14 @@
 //! `./x.py test` (aka [`Kind::Test`]) is currently allowed to reach build steps in other modules.
 //! However, this contains ~all test parts we expect people to be able to build and run locally.
 
+use std::collections::HashSet;
 use std::ffi::{OsStr, OsString};
 use std::path::{Path, PathBuf};
 use std::{env, fs, iter};
 
 use clap_complete::shells;
 
+use crate::core::build_steps::compile::run_cargo;
 use crate::core::build_steps::doc::DocumentationFormat;
 use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
 use crate::core::build_steps::tool::{self, SourceType, Tool};
@@ -2185,6 +2187,7 @@ struct BookTest {
     path: PathBuf,
     name: &'static str,
     is_ext_doc: bool,
+    dependencies: Vec<&'static str>,
 }
 
 impl Step for BookTest {
@@ -2237,6 +2240,57 @@ impl BookTest {
         // Books often have feature-gated example text.
         rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
         rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
+
+        // Books may also need to build dependencies. For example, `TheBook` has
+        // code samples which use the `trpl` crate. For the `rustdoc` invocation
+        // to find them them successfully, they need to be built first and their
+        // paths used to generate the
+        let libs = if !self.dependencies.is_empty() {
+            let mut lib_paths = vec![];
+            for dep in self.dependencies {
+                let mode = Mode::ToolRustc;
+                let target = builder.config.build;
+                let cargo = tool::prepare_tool_cargo(
+                    builder,
+                    compiler,
+                    mode,
+                    target,
+                    Kind::Build,
+                    dep,
+                    SourceType::Submodule,
+                    &[],
+                );
+
+                let stamp = builder
+                    .cargo_out(compiler, mode, target)
+                    .join(PathBuf::from(dep).file_name().unwrap())
+                    .with_extension("stamp");
+
+                let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
+                let directories = output_paths
+                    .into_iter()
+                    .filter_map(|p| p.parent().map(ToOwned::to_owned))
+                    .fold(HashSet::new(), |mut set, dir| {
+                        set.insert(dir);
+                        set
+                    });
+
+                lib_paths.extend(directories);
+            }
+            lib_paths
+        } else {
+            vec![]
+        };
+
+        if !libs.is_empty() {
+            let paths = libs
+                .into_iter()
+                .map(|path| path.into_os_string())
+                .collect::<Vec<OsString>>()
+                .join(OsStr::new(","));
+            rustbook_cmd.args([OsString::from("--library-path"), paths]);
+        }
+
         builder.add_rust_test_threads(&mut rustbook_cmd);
         let _guard = builder.msg(
             Kind::Test,
@@ -2295,6 +2349,7 @@ macro_rules! test_book {
         $name:ident, $path:expr, $book_name:expr,
         default=$default:expr
         $(,submodules = $submodules:expr)?
+        $(,dependencies=$dependencies:expr)?
         ;
     )+) => {
         $(
@@ -2324,11 +2379,21 @@ macro_rules! test_book {
                             builder.require_submodule(submodule, None);
                         }
                     )*
+
+                    let dependencies = vec![];
+                    $(
+                        let mut dependencies = dependencies;
+                        for dep in $dependencies {
+                            dependencies.push(dep);
+                        }
+                    )?
+
                     builder.ensure(BookTest {
                         compiler: self.compiler,
                         path: PathBuf::from($path),
                         name: $book_name,
                         is_ext_doc: !$default,
+                        dependencies,
                     });
                 }
             }
@@ -2343,7 +2408,7 @@ test_book!(
     RustcBook, "src/doc/rustc", "rustc", default=true;
     RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
     EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
-    TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"];
+    TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
     UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
     EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
 );