@@ -458,23 +458,52 @@ def unpack_component(download_info):
458
458
verbose = download_info .verbose ,
459
459
)
460
460
461
- class RustBuild ( object ) :
462
- """Provide all the methods required to build Rust """
461
+ class FakeArgs :
462
+ """Used for unit tests to avoid updating all call sites """
463
463
def __init__ (self ):
464
- self .checksums_sha256 = {}
465
- self .stage0_compiler = None
466
- self .download_url = ''
467
464
self .build = ''
468
465
self .build_dir = ''
469
466
self .clean = False
470
- self .config_toml = ''
471
- self .rust_root = ''
472
- self .use_locked_deps = False
473
- self .use_vendored_sources = False
474
467
self .verbose = False
468
+ self .json_output = False
469
+
470
+ class RustBuild (object ):
471
+ """Provide all the methods required to build Rust"""
472
+ def __init__ (self , config_toml = "" , args = FakeArgs ()):
475
473
self .git_version = None
476
474
self .nix_deps_dir = None
477
475
self ._should_fix_bins_and_dylibs = None
476
+ self .rust_root = os .path .abspath (os .path .join (__file__ , '../../..' ))
477
+
478
+ self .config_toml = config_toml
479
+
480
+ self .verbose = args .verbose != 0
481
+ self .clean = args .clean
482
+ self .json_output = args .json_output
483
+
484
+ profile = self .get_toml ('profile' )
485
+ if profile is not None :
486
+ include_file = 'config.{}.toml' .format (profile )
487
+ include_dir = os .path .join (self .rust_root , 'src' , 'bootstrap' , 'defaults' )
488
+ include_path = os .path .join (include_dir , include_file )
489
+ # HACK: This works because `self.get_toml()` returns the first match it finds for a
490
+ # specific key, so appending our defaults at the end allows the user to override them
491
+ with open (include_path ) as included_toml :
492
+ self .config_toml += os .linesep + included_toml .read ()
493
+
494
+ self .use_vendored_sources = self .get_toml ('vendor' , 'build' ) == 'true'
495
+ self .use_locked_deps = self .get_toml ('locked-deps' , 'build' ) == 'true'
496
+
497
+ build_dir = args .build_dir or self .get_toml ('build-dir' , 'build' ) or 'build'
498
+ self .build_dir = os .path .abspath (build_dir )
499
+
500
+ with open (os .path .join (self .rust_root , "src" , "stage0.json" )) as f :
501
+ data = json .load (f )
502
+ self .checksums_sha256 = data ["checksums_sha256" ]
503
+ self .stage0_compiler = Stage0Toolchain (data ["compiler" ])
504
+ self .download_url = os .getenv ("RUSTUP_DIST_SERVER" ) or data ["config" ]["dist_server" ]
505
+
506
+ self .build = args .build or self .build_triple ()
478
507
479
508
def download_toolchain (self ):
480
509
"""Fetch the build system for Rust, written in Rust
@@ -704,9 +733,10 @@ def rustc_stamp(self):
704
733
"""Return the path for .rustc-stamp at the given stage
705
734
706
735
>>> rb = RustBuild()
736
+ >>> rb.build = "host"
707
737
>>> rb.build_dir = "build"
708
- >>> rb.rustc_stamp() == os.path.join("build", "stage0", ".rustc-stamp")
709
- True
738
+ >>> expected = os.path.join("build", "host ", "stage0", ".rustc-stamp")
739
+ >>> assert rb.rustc_stamp() == expected, rb.rustc_stamp()
710
740
"""
711
741
return os .path .join (self .bin_root (), '.rustc-stamp' )
712
742
@@ -721,15 +751,9 @@ def bin_root(self):
721
751
"""Return the binary root directory for the given stage
722
752
723
753
>>> rb = RustBuild()
724
- >>> rb.build_dir = "build"
725
- >>> rb.bin_root() == os.path.join("build", "stage0")
726
- True
727
-
728
- When the 'build' property is given should be a nested directory:
729
-
730
754
>>> rb.build = "devel"
731
- >>> rb.bin_root() == os.path.join("build", "devel", "stage0")
732
- True
755
+ >>> expected = os.path.abspath(os.path. join("build", "devel", "stage0") )
756
+ >>> assert rb.bin_root() == expected, rb.bin_root()
733
757
"""
734
758
subdir = "stage0"
735
759
return os .path .join (self .build_dir , self .build , subdir )
@@ -842,6 +866,16 @@ def build_bootstrap(self, color, warnings, verbose_count):
842
866
print ("::group::Building bootstrap" )
843
867
else :
844
868
print ("Building bootstrap" , file = sys .stderr )
869
+
870
+ args = self .build_bootstrap_cmd (env , color , warnings , verbose_count )
871
+ # Run this from the source directory so cargo finds .cargo/config
872
+ run (args , env = env , verbose = self .verbose , cwd = self .rust_root )
873
+
874
+ if "GITHUB_ACTIONS" in env :
875
+ print ("::endgroup::" )
876
+
877
+ def build_bootstrap_cmd (self , env , color , warnings , verbose_count ):
878
+ """For tests."""
845
879
build_dir = os .path .join (self .build_dir , "bootstrap" )
846
880
if self .clean and os .path .exists (build_dir ):
847
881
shutil .rmtree (build_dir )
@@ -927,11 +961,7 @@ def build_bootstrap(self, color, warnings, verbose_count):
927
961
except KeyError :
928
962
pass
929
963
930
- # Run this from the source directory so cargo finds .cargo/config
931
- run (args , env = env , verbose = self .verbose , cwd = self .rust_root )
932
-
933
- if "GITHUB_ACTIONS" in env :
934
- print ("::endgroup::" )
964
+ return args
935
965
936
966
def build_triple (self ):
937
967
"""Build triple as in LLVM
@@ -981,7 +1011,7 @@ def check_vendored_status(self):
981
1011
if os .path .exists (cargo_dir ):
982
1012
shutil .rmtree (cargo_dir )
983
1013
984
- def parse_args ():
1014
+ def parse_args (args ):
985
1015
"""Parse the command line arguments that the python script needs."""
986
1016
parser = argparse .ArgumentParser (add_help = False )
987
1017
parser .add_argument ('-h' , '--help' , action = 'store_true' )
@@ -994,16 +1024,11 @@ def parse_args():
994
1024
parser .add_argument ('--warnings' , choices = ['deny' , 'warn' , 'default' ], default = 'default' )
995
1025
parser .add_argument ('-v' , '--verbose' , action = 'count' , default = 0 )
996
1026
997
- return parser .parse_known_args (sys . argv )[0 ]
1027
+ return parser .parse_known_args (args )[0 ]
998
1028
999
1029
def bootstrap (args ):
1000
1030
"""Configure, fetch, build and run the initial bootstrap"""
1001
- # Configure initial bootstrap
1002
- build = RustBuild ()
1003
- build .rust_root = os .path .abspath (os .path .join (__file__ , '../../..' ))
1004
- build .verbose = args .verbose != 0
1005
- build .clean = args .clean
1006
- build .json_output = args .json_output
1031
+ rust_root = os .path .abspath (os .path .join (__file__ , '../../..' ))
1007
1032
1008
1033
# Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`,
1009
1034
# then `config.toml` in the root directory.
@@ -1012,45 +1037,23 @@ def bootstrap(args):
1012
1037
if using_default_path :
1013
1038
toml_path = 'config.toml'
1014
1039
if not os .path .exists (toml_path ):
1015
- toml_path = os .path .join (build . rust_root , toml_path )
1040
+ toml_path = os .path .join (rust_root , toml_path )
1016
1041
1017
1042
# Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path,
1018
1043
# but not if `config.toml` hasn't been created.
1019
1044
if not using_default_path or os .path .exists (toml_path ):
1020
1045
with open (toml_path ) as config :
1021
- build .config_toml = config .read ()
1022
-
1023
- profile = build .get_toml ('profile' )
1024
- if profile is not None :
1025
- include_file = 'config.{}.toml' .format (profile )
1026
- include_dir = os .path .join (build .rust_root , 'src' , 'bootstrap' , 'defaults' )
1027
- include_path = os .path .join (include_dir , include_file )
1028
- # HACK: This works because `build.get_toml()` returns the first match it finds for a
1029
- # specific key, so appending our defaults at the end allows the user to override them
1030
- with open (include_path ) as included_toml :
1031
- build .config_toml += os .linesep + included_toml .read ()
1046
+ config_toml = config .read ()
1047
+
1048
+ # Configure initial bootstrap
1049
+ build = RustBuild (config_toml , args )
1050
+ build .check_vendored_status ()
1032
1051
1033
1052
verbose_count = args .verbose
1034
1053
config_verbose_count = build .get_toml ('verbose' , 'build' )
1035
1054
if config_verbose_count is not None :
1036
1055
verbose_count = max (args .verbose , int (config_verbose_count ))
1037
1056
1038
- build .use_vendored_sources = build .get_toml ('vendor' , 'build' ) == 'true'
1039
- build .use_locked_deps = build .get_toml ('locked-deps' , 'build' ) == 'true'
1040
-
1041
- build .check_vendored_status ()
1042
-
1043
- build_dir = args .build_dir or build .get_toml ('build-dir' , 'build' ) or 'build'
1044
- build .build_dir = os .path .abspath (build_dir )
1045
-
1046
- with open (os .path .join (build .rust_root , "src" , "stage0.json" )) as f :
1047
- data = json .load (f )
1048
- build .checksums_sha256 = data ["checksums_sha256" ]
1049
- build .stage0_compiler = Stage0Toolchain (data ["compiler" ])
1050
- build .download_url = os .getenv ("RUSTUP_DIST_SERVER" ) or data ["config" ]["dist_server" ]
1051
-
1052
- build .build = args .build or build .build_triple ()
1053
-
1054
1057
if not os .path .exists (build .build_dir ):
1055
1058
os .makedirs (build .build_dir )
1056
1059
@@ -1077,7 +1080,7 @@ def main():
1077
1080
if len (sys .argv ) > 1 and sys .argv [1 ] == 'help' :
1078
1081
sys .argv [1 ] = '-h'
1079
1082
1080
- args = parse_args ()
1083
+ args = parse_args (sys . argv )
1081
1084
help_triggered = args .help or len (sys .argv ) == 1
1082
1085
1083
1086
# If the user is asking for help, let them know that the whole download-and-build
0 commit comments