@@ -270,19 +270,44 @@ fn setup(ask_user: bool) {
270
270
ask_to_run ( cmd, ask_user, "install a recent enough xargo" ) ;
271
271
}
272
272
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
285
307
}
308
+ } ;
309
+ if !rust_src. exists ( ) {
310
+ show_error ( format ! ( "Given Rust source directory `{}` does not exist." , rust_src. display( ) ) ) ;
286
311
}
287
312
288
313
// 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"
321
346
command. arg ( "build" ) . arg ( "-q" ) ;
322
347
command. current_dir ( & dir) ;
323
348
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) ;
325
351
// In bootstrap, make sure we don't get debug assertons into our libstd.
326
352
command. env ( "RUSTC_DEBUG_ASSERTIONS" , "false" ) ;
327
353
// Handle target flag.
0 commit comments