@@ -270,19 +270,44 @@ fn setup(ask_user: bool) {
270270 ask_to_run ( cmd, ask_user, "install a recent enough xargo" ) ;
271271 }
272272
273- // Then, unless `XARGO_RUST_SRC` is set, we also need rust-src.
274- // Let's see if it is already installed.
275- if std:: env:: var ( "XARGO_RUST_SRC" ) . is_err ( ) {
276- let sysroot = Command :: new ( "rustc" ) . args ( & [ "--print" , "sysroot" ] ) . output ( )
277- . expect ( "failed to get rustc sysroot" )
278- . stdout ;
279- let sysroot = std:: str:: from_utf8 ( & sysroot) . unwrap ( ) ;
280- let src = Path :: new ( sysroot. trim_end_matches ( '\n' ) ) . join ( "lib" ) . join ( "rustlib" ) . join ( "src" ) ;
281- if !src. exists ( ) {
282- let mut cmd = Command :: new ( "rustup" ) ;
283- cmd. args ( & [ "component" , "add" , "rust-src" ] ) ;
284- ask_to_run ( cmd, ask_user, "install the rustc-src component for the selected toolchain" ) ;
273+ // Determine where the rust sources are located. `XARGO_RUST_SRC` env var trumps everything.
274+ let rust_src = match std:: env:: var ( "XARGO_RUST_SRC" ) {
275+ Ok ( val) => PathBuf :: from ( val) ,
276+ Err ( _) => {
277+ // Check for `rust-src` rustup component.
278+ let sysroot = Command :: new ( "rustc" ) . args ( & [ "--print" , "sysroot" ] ) . output ( )
279+ . expect ( "failed to get rustc sysroot" )
280+ . stdout ;
281+ let sysroot = std:: str:: from_utf8 ( & sysroot) . unwrap ( ) ;
282+ let sysroot = Path :: new ( sysroot. trim_end_matches ( '\n' ) ) ;
283+ // First try: `$SYSROOT/lib/rustlib/src/rust`; test if that contains `Cargo.lock`.
284+ let rustup_src = sysroot. join ( "lib" ) . join ( "rustlib" ) . join ( "src" ) . join ( "rust" ) ;
285+ let base_dir = if rustup_src. join ( "Cargo.lock" ) . exists ( ) {
286+ // Just use this.
287+ rustup_src
288+ } else {
289+ // Maybe this is a local toolchain built with `x.py` and linked into `rustup`?
290+ // Second try: `$SYSROOT/../../..`; test if that contains `x.py`.
291+ let local_src = sysroot. parent ( ) . and_then ( Path :: parent) . and_then ( Path :: parent) ;
292+ match local_src {
293+ Some ( local_src) if local_src. join ( "x.py" ) . exists ( ) => {
294+ // Use this.
295+ PathBuf :: from ( local_src)
296+ }
297+ _ => {
298+ // Fallback: Ask the user to install the `rust-src` component, and use that.
299+ let mut cmd = Command :: new ( "rustup" ) ;
300+ cmd. args ( & [ "component" , "add" , "rust-src" ] ) ;
301+ ask_to_run ( cmd, ask_user, "install the rustc-src component for the selected toolchain" ) ;
302+ rustup_src
303+ }
304+ }
305+ } ;
306+ base_dir. join ( "src" ) // Xargo wants the src-subdir
285307 }
308+ } ;
309+ if !rust_src. exists ( ) {
310+ show_error ( format ! ( "Given Rust source directory `{}` does not exist." , rust_src. display( ) ) ) ;
286311 }
287312
288313 // Next, we need our own libstd. We will do this work in whatever is a good cache dir for this platform.
@@ -321,7 +346,8 @@ path = "lib.rs"
321346 command. arg ( "build" ) . arg ( "-q" ) ;
322347 command. current_dir ( & dir) ;
323348 command. env ( "RUSTFLAGS" , miri:: miri_default_args ( ) . join ( " " ) ) ;
324- command. env ( "XARGO_HOME" , dir. to_str ( ) . unwrap ( ) ) ;
349+ command. env ( "XARGO_HOME" , & dir) ;
350+ command. env ( "XARGO_RUST_SRC" , & rust_src) ;
325351 // In bootstrap, make sure we don't get debug assertons into our libstd.
326352 command. env ( "RUSTC_DEBUG_ASSERTIONS" , "false" ) ;
327353 // Handle target flag.
0 commit comments