22
33use  std:: env; 
44use  std:: ffi:: OsStr ; 
5- use  std:: fmt:: Write ; 
65use  std:: path:: PathBuf ; 
76use  std:: process:: { self ,  Command } ; 
87
9- use  rustc_build_sysroot:: { BuildMode ,  SysrootBuilder ,  SysrootConfig } ; 
8+ use  rustc_build_sysroot:: { BuildMode ,  SysrootBuilder ,  SysrootConfig ,   SysrootStatus } ; 
109use  rustc_version:: VersionMeta ; 
1110
1211use  crate :: util:: * ; 
@@ -24,6 +23,7 @@ pub fn setup(
2423    let  only_setup = matches ! ( subcommand,  MiriCommand :: Setup ) ; 
2524    let  ask_user = !only_setup; 
2625    let  print_sysroot = only_setup && has_arg_flag ( "--print-sysroot" ) ;  // whether we just print the sysroot path 
26+     let  show_setup = only_setup && !print_sysroot; 
2727    if  !only_setup { 
2828        if  let  Some ( sysroot)  = std:: env:: var_os ( "MIRI_SYSROOT" )  { 
2929            // Skip setup step if MIRI_SYSROOT is explicitly set, *unless* we are `cargo miri setup`. 
@@ -115,18 +115,16 @@ pub fn setup(
115115        // `config.toml`. 
116116        command. env ( "RUSTC_WRAPPER" ,  "" ) ; 
117117
118-         if  only_setup && !print_sysroot  { 
118+         if  show_setup  { 
119119            // Forward output. Even make it verbose, if requested. 
120+             command. stdout ( process:: Stdio :: inherit ( ) ) ; 
121+             command. stderr ( process:: Stdio :: inherit ( ) ) ; 
120122            for  _ in  0 ..verbose { 
121123                command. arg ( "-v" ) ; 
122124            } 
123125            if  quiet { 
124126                command. arg ( "--quiet" ) ; 
125127            } 
126-         }  else  { 
127-             // Suppress output. 
128-             command. stdout ( process:: Stdio :: null ( ) ) ; 
129-             command. stderr ( process:: Stdio :: null ( ) ) ; 
130128        } 
131129
132130        command
@@ -137,49 +135,52 @@ pub fn setup(
137135    // not apply `RUSTFLAGS` to the sysroot either. 
138136    let  rustflags = & [ "-Cdebug-assertions=off" ,  "-Coverflow-checks=on" ] ; 
139137
140-     // Do the build. 
141-     if  print_sysroot || quiet { 
142-         // Be silent. 
143-     }  else  { 
144-         let  mut  msg = String :: new ( ) ; 
145-         write ! ( msg,  "Preparing a sysroot for Miri (target: {target})" ) . unwrap ( ) ; 
146-         if  verbose > 0  { 
147-             write ! ( msg,  " in {}" ,  sysroot_dir. display( ) ) . unwrap ( ) ; 
148-         } 
149-         write ! ( msg,  "..." ) . unwrap ( ) ; 
150-         if  only_setup { 
151-             // We want to be explicit. 
152-             eprintln ! ( "{msg}" ) ; 
153-         }  else  { 
154-             // We want to be quiet, but still let the user know that something is happening. 
155-             eprint ! ( "{msg} " ) ; 
138+     let  mut  after_build_output = String :: new ( ) ;  // what should be printed when the build is done. 
139+     let  notify = || { 
140+         if  !quiet { 
141+             eprint ! ( "Preparing a sysroot for Miri (target: {target})" ) ; 
142+             if  verbose > 0  { 
143+                 eprint ! ( " in {}" ,  sysroot_dir. display( ) ) ; 
144+             } 
145+             if  show_setup { 
146+                 // Cargo will print things, so we need to finish this line. 
147+                 eprintln ! ( "..." ) ; 
148+                 after_build_output = format ! ( 
149+                     "A sysroot for Miri is now available in `{}`.\n " , 
150+                     sysroot_dir. display( ) 
151+                 ) ; 
152+             }  else  { 
153+                 // Keep all output on a single line. 
154+                 eprint ! ( "... " ) ; 
155+                 after_build_output = format ! ( "done\n " ) ; 
156+             } 
156157        } 
157-     } 
158-     SysrootBuilder :: new ( & sysroot_dir,  target) 
158+     } ; 
159+ 
160+     // Do the build. 
161+     let  status = SysrootBuilder :: new ( & sysroot_dir,  target) 
159162        . build_mode ( BuildMode :: Check ) 
160163        . rustc_version ( rustc_version. clone ( ) ) 
161164        . sysroot_config ( sysroot_config) 
162165        . rustflags ( rustflags) 
163166        . cargo ( cargo_cmd) 
164-         . build_from_source ( & rust_src) 
165-         . unwrap_or_else ( |err| { 
166-             if  print_sysroot { 
167-                 show_error ! ( "failed to build sysroot" ) 
168-             }  else  if  only_setup { 
169-                 show_error ! ( "failed to build sysroot: {err:?}" ) 
170-             }  else  { 
171-                 show_error ! ( 
172-                     "failed to build sysroot; run `cargo miri setup` to see the error details" 
173-                 ) 
174-             } 
175-         } ) ; 
176-     if  print_sysroot || quiet { 
177-         // Be silent. 
178-     }  else  if  only_setup { 
179-         eprintln ! ( "A sysroot for Miri is now available in `{}`." ,  sysroot_dir. display( ) ) ; 
180-     }  else  { 
181-         eprintln ! ( "done" ) ; 
167+         . when_build_required ( notify) 
168+         . build_from_source ( & rust_src) ; 
169+     match  status { 
170+         Ok ( SysrootStatus :: AlreadyCached )  =>
171+             if  !quiet && show_setup { 
172+                 eprintln ! ( 
173+                     "A sysroot for Miri is already available in `{}`." , 
174+                     sysroot_dir. display( ) 
175+                 ) ; 
176+             } , 
177+         Ok ( SysrootStatus :: SysrootBuilt )  => { 
178+             // Print what `notify` prepared. 
179+             eprint ! ( "{after_build_output}" ) ; 
180+         } 
181+         Err ( err)  => show_error ! ( "failed to build sysroot: {err:?}" ) , 
182182    } 
183+ 
183184    if  print_sysroot { 
184185        // Print just the sysroot and nothing else to stdout; this way we do not need any escaping. 
185186        println ! ( "{}" ,  sysroot_dir. display( ) ) ; 
0 commit comments