@@ -123,6 +123,7 @@ impl SysrootDownload {
123123 let components = ToolchainComponents :: from_binaries_and_libdir (
124124 sysroot_bin ( "rustc" ) ?,
125125 Some ( sysroot_bin ( "rustdoc" ) ?) ,
126+ sysroot_bin ( "cargo-clippy" ) . ok ( ) ,
126127 sysroot_bin ( "cargo" ) ?,
127128 & self . directory . join ( & self . rust_sha ) . join ( "lib" ) ,
128129 ) ?;
@@ -241,6 +242,7 @@ impl Toolchain {
241242pub struct ToolchainComponents {
242243 pub rustc : PathBuf ,
243244 pub rustdoc : Option < PathBuf > ,
245+ pub clippy : Option < PathBuf > ,
244246 pub cargo : PathBuf ,
245247 pub lib_rustc : Option < PathBuf > ,
246248 pub lib_std : Option < PathBuf > ,
@@ -252,12 +254,14 @@ impl ToolchainComponents {
252254 fn from_binaries_and_libdir (
253255 rustc : PathBuf ,
254256 rustdoc : Option < PathBuf > ,
257+ clippy : Option < PathBuf > ,
255258 cargo : PathBuf ,
256259 libdir : & Path ,
257260 ) -> anyhow:: Result < Self > {
258261 let mut component = ToolchainComponents {
259262 rustc,
260263 rustdoc,
264+ clippy,
261265 cargo,
262266 ..Default :: default ( )
263267 } ;
@@ -288,6 +292,36 @@ impl ToolchainComponents {
288292 }
289293}
290294
295+ #[ derive( Clone , Copy , Default ) ]
296+ pub struct ToolchainConfig < ' a > {
297+ rustdoc : Option < & ' a Path > ,
298+ clippy : Option < & ' a Path > ,
299+ cargo : Option < & ' a Path > ,
300+ id : Option < & ' a str > ,
301+ }
302+
303+ impl < ' a > ToolchainConfig < ' a > {
304+ pub fn rustdoc ( & mut self , rustdoc : Option < & ' a Path > ) -> & mut Self {
305+ self . rustdoc = rustdoc;
306+ self
307+ }
308+
309+ pub fn clippy ( & mut self , clippy : Option < & ' a Path > ) -> & mut Self {
310+ self . clippy = clippy;
311+ self
312+ }
313+
314+ pub fn cargo ( & mut self , cargo : Option < & ' a Path > ) -> & mut Self {
315+ self . cargo = cargo;
316+ self
317+ }
318+
319+ pub fn id ( & mut self , id : Option < & ' a str > ) -> & mut Self {
320+ self . id = id;
321+ self
322+ }
323+ }
324+
291325/// Get a toolchain from the input.
292326/// - `rustc`: check if the given one is acceptable.
293327/// - `rustdoc`: if one is given, check if it is acceptable. Otherwise, if
@@ -297,9 +331,7 @@ impl ToolchainComponents {
297331pub fn get_local_toolchain (
298332 profiles : & [ Profile ] ,
299333 rustc : & str ,
300- rustdoc : Option < & Path > ,
301- cargo : Option < & Path > ,
302- id : Option < & str > ,
334+ toolchain_config : ToolchainConfig < ' _ > ,
303335 id_suffix : & str ,
304336 target_triple : String ,
305337) -> anyhow:: Result < Toolchain > {
@@ -354,7 +386,7 @@ pub fn get_local_toolchain(
354386 debug ! ( "found rustc: {:?}" , & rustc) ;
355387
356388 // When the id comes from a +toolchain, the suffix is *not* added.
357- let id = if let Some ( id) = id {
389+ let id = if let Some ( id) = toolchain_config . id {
358390 let mut id = id. to_owned ( ) ;
359391 id. push_str ( id_suffix) ;
360392 id
@@ -369,7 +401,7 @@ pub fn get_local_toolchain(
369401
370402 // When specifying rustc via a path, the suffix is always added to the
371403 // id.
372- let mut id = if let Some ( id) = id {
404+ let mut id = if let Some ( id) = toolchain_config . id {
373405 id. to_owned ( )
374406 } else {
375407 "Id" . to_string ( )
@@ -380,7 +412,7 @@ pub fn get_local_toolchain(
380412 } ;
381413
382414 let rustdoc =
383- if let Some ( rustdoc) = & rustdoc {
415+ if let Some ( rustdoc) = & toolchain_config . rustdoc {
384416 Some ( rustdoc. canonicalize ( ) . with_context ( || {
385417 format ! ( "failed to canonicalize rustdoc executable {:?}" , rustdoc)
386418 } ) ?)
@@ -400,7 +432,28 @@ pub fn get_local_toolchain(
400432 None
401433 } ;
402434
403- let cargo = if let Some ( cargo) = & cargo {
435+ let clippy = if let Some ( clippy) = & toolchain_config. clippy {
436+ Some (
437+ clippy. canonicalize ( ) . with_context ( || {
438+ format ! ( "failed to canonicalize clippy executable {:?}" , clippy)
439+ } ) ?,
440+ )
441+ } else if profiles. contains ( & Profile :: Clippy ) {
442+ // We need a `clippy`. Look for one next to `rustc`.
443+ if let Ok ( clippy) = rustc. with_file_name ( "cargo-clippy" ) . canonicalize ( ) {
444+ debug ! ( "found clippy: {:?}" , & clippy) ;
445+ Some ( clippy)
446+ } else {
447+ anyhow:: bail!(
448+ "'Clippy' build specified but '--cargo-clippy' not specified and no 'cargo-clippy' found \
449+ next to 'rustc'"
450+ ) ;
451+ }
452+ } else {
453+ // No `clippy` provided, but none needed.
454+ None
455+ } ;
456+ let cargo = if let Some ( cargo) = & toolchain_config. cargo {
404457 cargo
405458 . canonicalize ( )
406459 . with_context ( || format ! ( "failed to canonicalize cargo executable {:?}" , cargo) ) ?
@@ -428,7 +481,9 @@ pub fn get_local_toolchain(
428481 let lib_dir = get_lib_dir_from_rustc ( & rustc) . context ( "Cannot find libdir for rustc" ) ?;
429482
430483 Ok ( Toolchain {
431- components : ToolchainComponents :: from_binaries_and_libdir ( rustc, rustdoc, cargo, & lib_dir) ?,
484+ components : ToolchainComponents :: from_binaries_and_libdir (
485+ rustc, rustdoc, clippy, cargo, & lib_dir,
486+ ) ?,
432487 id,
433488 triple : target_triple,
434489 } )
@@ -465,16 +520,23 @@ pub fn create_toolchain_from_published_version(
465520 } ;
466521 let rustc = which ( "rustc" ) ?;
467522 let rustdoc = which ( "rustdoc" ) ?;
523+ let clippy = which ( "clippy" ) ?;
468524 let cargo = which ( "cargo" ) ?;
469525
470526 debug ! ( "Found rustc: {}" , rustc. display( ) ) ;
471527 debug ! ( "Found rustdoc: {}" , rustdoc. display( ) ) ;
528+ debug ! ( "Found clippy: {}" , clippy. display( ) ) ;
472529 debug ! ( "Found cargo: {}" , cargo. display( ) ) ;
473530
474531 let lib_dir = get_lib_dir_from_rustc ( & rustc) ?;
475532
476- let components =
477- ToolchainComponents :: from_binaries_and_libdir ( rustc, Some ( rustdoc) , cargo, & lib_dir) ?;
533+ let components = ToolchainComponents :: from_binaries_and_libdir (
534+ rustc,
535+ Some ( rustdoc) ,
536+ Some ( clippy) ,
537+ cargo,
538+ & lib_dir,
539+ ) ?;
478540
479541 Ok ( Toolchain {
480542 components,
0 commit comments