@@ -378,6 +378,7 @@ def __init__(self):
378
378
self .verbose = False
379
379
self .git_version = None
380
380
self .nix_deps_dir = None
381
+ self .rustc_commit = None
381
382
382
383
def download_stage0 (self ):
383
384
"""Fetch the build system for Rust, written in Rust
@@ -394,20 +395,27 @@ def download_stage0(self):
394
395
395
396
if self .rustc ().startswith (self .bin_root ()) and \
396
397
(not os .path .exists (self .rustc ()) or
397
- self .program_out_of_date (self .rustc_stamp (), self .date )):
398
+ self .program_out_of_date (self .rustc_stamp (), self .date + str ( self . rustc_commit ) )):
398
399
if os .path .exists (self .bin_root ()):
399
400
shutil .rmtree (self .bin_root ())
401
+ download_rustc = self .rustc_commit is not None
400
402
tarball_suffix = '.tar.xz' if support_xz () else '.tar.gz'
401
403
filename = "rust-std-{}-{}{}" .format (
402
404
rustc_channel , self .build , tarball_suffix )
403
405
pattern = "rust-std-{}" .format (self .build )
404
- self ._download_stage0_helper (filename , pattern , tarball_suffix )
406
+ self ._download_component_helper (filename , pattern , tarball_suffix , download_rustc )
405
407
filename = "rustc-{}-{}{}" .format (rustc_channel , self .build ,
406
408
tarball_suffix )
407
- self ._download_stage0_helper (filename , "rustc" , tarball_suffix )
409
+ self ._download_component_helper (filename , "rustc" , tarball_suffix , download_rustc )
408
410
filename = "cargo-{}-{}{}" .format (rustc_channel , self .build ,
409
411
tarball_suffix )
410
- self ._download_stage0_helper (filename , "cargo" , tarball_suffix )
412
+ self ._download_component_helper (filename , "cargo" , tarball_suffix )
413
+ if self .rustc_commit is not None :
414
+ filename = "rustc-dev-{}-{}{}" .format (rustc_channel , self .build , tarball_suffix )
415
+ self ._download_component_helper (
416
+ filename , "rustc-dev" , tarball_suffix , download_rustc
417
+ )
418
+
411
419
self .fix_bin_or_dylib ("{}/bin/rustc" .format (self .bin_root ()))
412
420
self .fix_bin_or_dylib ("{}/bin/rustdoc" .format (self .bin_root ()))
413
421
self .fix_bin_or_dylib ("{}/bin/cargo" .format (self .bin_root ()))
@@ -416,7 +424,7 @@ def download_stage0(self):
416
424
if lib .endswith (".so" ):
417
425
self .fix_bin_or_dylib (os .path .join (lib_dir , lib ), rpath_libz = True )
418
426
with output (self .rustc_stamp ()) as rust_stamp :
419
- rust_stamp .write (self .date )
427
+ rust_stamp .write (self .date + str ( self . rustc_commit ) )
420
428
421
429
if self .rustfmt () and self .rustfmt ().startswith (self .bin_root ()) and (
422
430
not os .path .exists (self .rustfmt ())
@@ -426,7 +434,9 @@ def download_stage0(self):
426
434
tarball_suffix = '.tar.xz' if support_xz () else '.tar.gz'
427
435
[channel , date ] = rustfmt_channel .split ('-' , 1 )
428
436
filename = "rustfmt-{}-{}{}" .format (channel , self .build , tarball_suffix )
429
- self ._download_stage0_helper (filename , "rustfmt-preview" , tarball_suffix , date )
437
+ self ._download_component_helper (
438
+ filename , "rustfmt-preview" , tarball_suffix , key = date
439
+ )
430
440
self .fix_bin_or_dylib ("{}/bin/rustfmt" .format (self .bin_root ()))
431
441
self .fix_bin_or_dylib ("{}/bin/cargo-fmt" .format (self .bin_root ()))
432
442
with output (self .rustfmt_stamp ()) as rustfmt_stamp :
@@ -482,18 +492,27 @@ def downloading_llvm(self):
482
492
return opt == "true" \
483
493
or (opt == "if-available" and self .build in supported_platforms )
484
494
485
- def _download_stage0_helper (self , filename , pattern , tarball_suffix , date = None ):
486
- if date is None :
487
- date = self .date
495
+ def _download_component_helper (
496
+ self , filename , pattern , tarball_suffix , download_rustc = False , key = None
497
+ ):
498
+ if key is None :
499
+ if download_rustc :
500
+ key = self .rustc_commit
501
+ else :
502
+ key = self .date
488
503
cache_dst = os .path .join (self .build_dir , "cache" )
489
- rustc_cache = os .path .join (cache_dst , date )
504
+ rustc_cache = os .path .join (cache_dst , key )
490
505
if not os .path .exists (rustc_cache ):
491
506
os .makedirs (rustc_cache )
492
507
493
- url = "{}/dist/{}" .format (self ._download_url , date )
508
+ if download_rustc :
509
+ url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}" .format (self .rustc_commit )
510
+ else :
511
+ url = "{}/dist/{}" .format (self ._download_url , key )
494
512
tarball = os .path .join (rustc_cache , filename )
495
513
if not os .path .exists (tarball ):
496
- get ("{}/{}" .format (url , filename ), tarball , verbose = self .verbose )
514
+ do_verify = not download_rustc
515
+ get ("{}/{}" .format (url , filename ), tarball , verbose = self .verbose , do_verify = do_verify )
497
516
unpack (tarball , tarball_suffix , self .bin_root (), match = pattern , verbose = self .verbose )
498
517
499
518
def _download_ci_llvm (self , llvm_sha , llvm_assertions ):
@@ -613,6 +632,46 @@ def fix_bin_or_dylib(self, fname, rpath_libz=False):
613
632
print ("warning: failed to call patchelf:" , reason )
614
633
return
615
634
635
+ # Return the stage1 compiler to download, if any.
636
+ def maybe_download_rustc (self ):
637
+ # If `download-rustc` is not set, default to rebuilding.
638
+ if self .get_toml ("download-rustc" , section = "rust" ) != "true" :
639
+ return None
640
+ # Look for a version to compare to based on the current commit.
641
+ # There are a few different cases to handle.
642
+ # 1. This commit is a fast-forward from master: `master - * - * - HEAD`
643
+ # 2. This commit and master have diverged:
644
+ # ```
645
+ # Y - * - HEAD
646
+ # /
647
+ # X - * - master
648
+ # ```
649
+ # In this case, we should compare to `X`.
650
+ # 3. `master` and `HEAD` are radically different (>100 commits, or similar). This probably
651
+ # means that `master` does *not* correspond to the version we want to compare to, e.g. a
652
+ # fork. Instead, we want to compare to `rust-lang/rust:master`, which this has to share a
653
+ # recent merge base with.
654
+
655
+ # Find which remote corresponds to `rust-lang/rust`.
656
+ remotes = subprocess .check_output (["git" , "remote" , "-v" ], universal_newlines = True )
657
+ # e.g. `origin https://github.com//rust-lang/rust (fetch)`
658
+ rust_lang_remote = next (line for line in remotes .splitlines () if "rust-lang/rust" in line )
659
+ rust_lang_remote = rust_lang_remote .split ()[0 ]
660
+
661
+ # Find which commit to compare to
662
+ merge_base = ["git" , "merge-base" , "HEAD" , "{}/master" .format (rust_lang_remote )]
663
+ commit = subprocess .check_output (merge_base , universal_newlines = True ).strip ()
664
+
665
+ # Warn if there were changes to the compiler since the ancestor commit.
666
+ rev_parse = ["git" , "rev-parse" , "--show-toplevel" ]
667
+ top_level = subprocess .check_output (rev_parse , universal_newlines = True ).strip ()
668
+ compiler = "{}/compiler/" .format (top_level )
669
+ status = subprocess .call (["git" , "diff-index" , "--quiet" , commit , "--" , compiler ])
670
+ if status != 0 :
671
+ print ("warning: `download-rustc` is enabled, but there are changes to compiler/" )
672
+
673
+ return commit
674
+
616
675
def rustc_stamp (self ):
617
676
"""Return the path for .rustc-stamp
618
677
@@ -1090,6 +1149,13 @@ def bootstrap(help_triggered):
1090
1149
build .update_submodules ()
1091
1150
1092
1151
# Fetch/build the bootstrap
1152
+ build .rustc_commit = build .maybe_download_rustc ()
1153
+ if build .rustc_commit is not None :
1154
+ if build .verbose :
1155
+ commit = build .rustc_commit
1156
+ print ("using downloaded stage1 artifacts from CI (commit {})" .format (commit ))
1157
+ # FIXME: support downloading artifacts from the beta channel
1158
+ build .rustc_channel = "nightly"
1093
1159
build .download_stage0 ()
1094
1160
sys .stdout .flush ()
1095
1161
build .ensure_vendored ()
0 commit comments