33//! `./x.py test` (aka [`Kind::Test`]) is currently allowed to reach build steps in other modules.
44//! However, this contains ~all test parts we expect people to be able to build and run locally.
55
6+ use std:: collections:: HashSet ;
67use std:: ffi:: { OsStr , OsString } ;
78use std:: path:: { Path , PathBuf } ;
89use std:: { env, fs, iter} ;
910
1011use clap_complete:: shells;
1112
13+ use crate :: core:: build_steps:: compile:: run_cargo;
1214use crate :: core:: build_steps:: doc:: DocumentationFormat ;
1315use crate :: core:: build_steps:: synthetic_targets:: MirOptPanicAbortSyntheticTarget ;
1416use crate :: core:: build_steps:: tool:: { self , SourceType , Tool } ;
@@ -2168,9 +2170,11 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
21682170#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
21692171struct BookTest {
21702172 compiler : Compiler ,
2173+ target : TargetSelection ,
21712174 path : PathBuf ,
21722175 name : & ' static str ,
21732176 is_ext_doc : bool ,
2177+ dependencies : Vec < & ' static str > ,
21742178}
21752179
21762180impl Step for BookTest {
@@ -2223,6 +2227,63 @@ impl BookTest {
22232227 // Books often have feature-gated example text.
22242228 rustbook_cmd. env ( "RUSTC_BOOTSTRAP" , "1" ) ;
22252229 rustbook_cmd. env ( "PATH" , new_path) . arg ( "test" ) . arg ( path) ;
2230+
2231+ // Books may also need to build dependencies. For example, `TheBook` has
2232+ // code samples which use the `trpl` crate. For the `rustdoc` invocation
2233+ // to find them them successfully, they need to be built first and their
2234+ // paths used to generate the
2235+ let libs = if !self . dependencies . is_empty ( ) {
2236+ let mut lib_paths = vec ! [ ] ;
2237+ for dep in self . dependencies {
2238+ let mode = Mode :: ToolRustc ;
2239+ let target = builder. config . build ;
2240+ // CHECKME: is this correct, or should it be using `builder::Cargo::new`?
2241+ let cargo = tool:: prepare_tool_cargo (
2242+ builder,
2243+ self . compiler ,
2244+ mode,
2245+ builder. config . build ,
2246+ Kind :: Build ,
2247+ dep,
2248+ SourceType :: Submodule ,
2249+ & [ ] ,
2250+ ) ;
2251+ // CHECKME: this is used for the "stamp" for this `run_cargo`;
2252+ // is there a better way to do this?!?
2253+ let dep_path = PathBuf :: from ( dep) ;
2254+ let file_name = dep_path. file_name ( ) . unwrap ( ) ;
2255+ let file_name = PathBuf :: from ( file_name) ;
2256+
2257+ let stamp = builder
2258+ . cargo_out ( self . compiler , mode, target)
2259+ . join ( file_name)
2260+ . with_extension ( "stamp" ) ;
2261+
2262+ let output_paths = run_cargo ( builder, cargo, vec ! [ ] , & stamp, vec ! [ ] , false , false ) ;
2263+ let directories = output_paths
2264+ . into_iter ( )
2265+ . filter_map ( |p| p. parent ( ) . map ( ToOwned :: to_owned) )
2266+ . fold ( HashSet :: new ( ) , |mut set, dir| {
2267+ set. insert ( dir) ;
2268+ set
2269+ } ) ;
2270+ lib_paths. extend ( directories) ;
2271+ }
2272+ lib_paths
2273+ } else {
2274+ vec ! [ ]
2275+ } ;
2276+
2277+ if !libs. is_empty ( ) {
2278+ let comma_separated_paths = libs
2279+ . into_iter ( )
2280+ . map ( |path| format ! ( "{}" , path. display( ) ) )
2281+ . collect :: < Vec < String > > ( )
2282+ . join ( "," ) ;
2283+
2284+ rustbook_cmd. args ( vec ! [ String :: from( "--library-path" ) , comma_separated_paths] ) ;
2285+ }
2286+
22262287 builder. add_rust_test_threads ( & mut rustbook_cmd) ;
22272288 let _guard = builder. msg (
22282289 Kind :: Test ,
@@ -2281,12 +2342,14 @@ macro_rules! test_book {
22812342 $name: ident, $path: expr, $book_name: expr,
22822343 default =$default: expr
22832344 $( , submodules = $submodules: expr) ?
2345+ $( , dependencies=$dependencies: expr) ?
22842346 ;
22852347 ) +) => {
22862348 $(
22872349 #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
22882350 pub struct $name {
22892351 compiler: Compiler ,
2352+ target: TargetSelection ,
22902353 }
22912354
22922355 impl Step for $name {
@@ -2301,6 +2364,7 @@ macro_rules! test_book {
23012364 fn make_run( run: RunConfig <' _>) {
23022365 run. builder. ensure( $name {
23032366 compiler: run. builder. compiler( run. builder. top_stage, run. target) ,
2367+ target: run. target,
23042368 } ) ;
23052369 }
23062370
@@ -2310,11 +2374,22 @@ macro_rules! test_book {
23102374 builder. require_submodule( submodule, None ) ;
23112375 }
23122376 ) *
2377+
2378+ let dependencies = vec![ ] ;
2379+ $(
2380+ let mut dependencies = dependencies;
2381+ for dep in $dependencies {
2382+ dependencies. push( dep) ;
2383+ }
2384+ ) ?
2385+
23132386 builder. ensure( BookTest {
23142387 compiler: self . compiler,
2388+ target: self . target,
23152389 path: PathBuf :: from( $path) ,
23162390 name: $book_name,
23172391 is_ext_doc: !$default,
2392+ dependencies,
23182393 } ) ;
23192394 }
23202395 }
@@ -2329,7 +2404,7 @@ test_book!(
23292404 RustcBook , "src/doc/rustc" , "rustc" , default =true ;
23302405 RustByExample , "src/doc/rust-by-example" , "rust-by-example" , default =false , submodules=[ "src/doc/rust-by-example" ] ;
23312406 EmbeddedBook , "src/doc/embedded-book" , "embedded-book" , default =false , submodules=[ "src/doc/embedded-book" ] ;
2332- TheBook , "src/doc/book" , "book" , default =false , submodules=[ "src/doc/book" ] ;
2407+ TheBook , "src/doc/book" , "book" , default =false , submodules=[ "src/doc/book" ] , dependencies= [ "src/doc/book/packages/trpl" ] ;
23332408 UnstableBook , "src/doc/unstable-book" , "unstable-book" , default =true ;
23342409 EditionGuide , "src/doc/edition-guide" , "edition-guide" , default =false , submodules=[ "src/doc/edition-guide" ] ;
23352410) ;
0 commit comments