@@ -2,14 +2,13 @@ use std::any::{type_name, Any};
2
2
use std:: cell:: { Cell , RefCell } ;
3
3
use std:: collections:: BTreeSet ;
4
4
use std:: env;
5
- use std:: ffi:: { OsStr , OsString } ;
5
+ use std:: ffi:: OsStr ;
6
6
use std:: fmt:: { Debug , Write } ;
7
- use std:: fs:: { self , File } ;
7
+ use std:: fs:: { self } ;
8
8
use std:: hash:: Hash ;
9
- use std:: io:: { BufRead , BufReader , ErrorKind } ;
10
9
use std:: ops:: Deref ;
11
10
use std:: path:: { Component , Path , PathBuf } ;
12
- use std:: process:: { Command , Stdio } ;
11
+ use std:: process:: Command ;
13
12
use std:: time:: { Duration , Instant } ;
14
13
15
14
use crate :: cache:: { Cache , Interned , INTERNER } ;
@@ -24,14 +23,12 @@ use crate::test;
24
23
use crate :: tool:: { self , SourceType } ;
25
24
use crate :: util:: { self , add_dylib_path, add_link_lib_path, exe, libdir, output, t} ;
26
25
use crate :: EXTRA_CHECK_CFGS ;
27
- use crate :: { check, Config } ;
28
- use crate :: { compile, Crate } ;
26
+ use crate :: { check, compile, Crate } ;
29
27
use crate :: { Build , CLang , DocTests , GitRepo , Mode } ;
30
28
31
29
pub use crate :: Compiler ;
32
30
// FIXME: replace with std::lazy after it gets stabilized and reaches beta
33
- use once_cell:: sync:: { Lazy , OnceCell } ;
34
- use xz2:: bufread:: XzDecoder ;
31
+ use once_cell:: sync:: Lazy ;
35
32
36
33
pub struct Builder < ' a > {
37
34
pub build : & ' a Build ,
@@ -853,241 +850,6 @@ impl<'a> Builder<'a> {
853
850
StepDescription :: run ( v, self , paths) ;
854
851
}
855
852
856
- /// Modifies the interpreter section of 'fname' to fix the dynamic linker,
857
- /// or the RPATH section, to fix the dynamic library search path
858
- ///
859
- /// This is only required on NixOS and uses the PatchELF utility to
860
- /// change the interpreter/RPATH of ELF executables.
861
- ///
862
- /// Please see https://nixos.org/patchelf.html for more information
863
- pub ( crate ) fn fix_bin_or_dylib ( & self , fname : & Path ) {
864
- // FIXME: cache NixOS detection?
865
- match Command :: new ( "uname" ) . arg ( "-s" ) . stderr ( Stdio :: inherit ( ) ) . output ( ) {
866
- Err ( _) => return ,
867
- Ok ( output) if !output. status . success ( ) => return ,
868
- Ok ( output) => {
869
- let mut s = output. stdout ;
870
- if s. last ( ) == Some ( & b'\n' ) {
871
- s. pop ( ) ;
872
- }
873
- if s != b"Linux" {
874
- return ;
875
- }
876
- }
877
- }
878
-
879
- // If the user has asked binaries to be patched for Nix, then
880
- // don't check for NixOS or `/lib`, just continue to the patching.
881
- // NOTE: this intentionally comes after the Linux check:
882
- // - patchelf only works with ELF files, so no need to run it on Mac or Windows
883
- // - On other Unix systems, there is no stable syscall interface, so Nix doesn't manage the global libc.
884
- if !self . config . patch_binaries_for_nix {
885
- // Use `/etc/os-release` instead of `/etc/NIXOS`.
886
- // The latter one does not exist on NixOS when using tmpfs as root.
887
- const NIX_IDS : & [ & str ] = & [ "ID=nixos" , "ID='nixos'" , "ID=\" nixos\" " ] ;
888
- let os_release = match File :: open ( "/etc/os-release" ) {
889
- Err ( e) if e. kind ( ) == ErrorKind :: NotFound => return ,
890
- Err ( e) => panic ! ( "failed to access /etc/os-release: {}" , e) ,
891
- Ok ( f) => f,
892
- } ;
893
- if !BufReader :: new ( os_release) . lines ( ) . any ( |l| NIX_IDS . contains ( & t ! ( l) . trim ( ) ) ) {
894
- return ;
895
- }
896
- if Path :: new ( "/lib" ) . exists ( ) {
897
- return ;
898
- }
899
- }
900
-
901
- // At this point we're pretty sure the user is running NixOS or using Nix
902
- println ! ( "info: you seem to be using Nix. Attempting to patch {}" , fname. display( ) ) ;
903
-
904
- // Only build `.nix-deps` once.
905
- static NIX_DEPS_DIR : OnceCell < PathBuf > = OnceCell :: new ( ) ;
906
- let mut nix_build_succeeded = true ;
907
- let nix_deps_dir = NIX_DEPS_DIR . get_or_init ( || {
908
- // Run `nix-build` to "build" each dependency (which will likely reuse
909
- // the existing `/nix/store` copy, or at most download a pre-built copy).
910
- //
911
- // Importantly, we create a gc-root called `.nix-deps` in the `build/`
912
- // directory, but still reference the actual `/nix/store` path in the rpath
913
- // as it makes it significantly more robust against changes to the location of
914
- // the `.nix-deps` location.
915
- //
916
- // bintools: Needed for the path of `ld-linux.so` (via `nix-support/dynamic-linker`).
917
- // zlib: Needed as a system dependency of `libLLVM-*.so`.
918
- // patchelf: Needed for patching ELF binaries (see doc comment above).
919
- let nix_deps_dir = self . out . join ( ".nix-deps" ) ;
920
- const NIX_EXPR : & str = "
921
- with (import <nixpkgs> {});
922
- symlinkJoin {
923
- name = \" rust-stage0-dependencies\" ;
924
- paths = [
925
- zlib
926
- patchelf
927
- stdenv.cc.bintools
928
- ];
929
- }
930
- " ;
931
- nix_build_succeeded = self . try_run ( Command :: new ( "nix-build" ) . args ( & [
932
- Path :: new ( "-E" ) ,
933
- Path :: new ( NIX_EXPR ) ,
934
- Path :: new ( "-o" ) ,
935
- & nix_deps_dir,
936
- ] ) ) ;
937
- nix_deps_dir
938
- } ) ;
939
- if !nix_build_succeeded {
940
- return ;
941
- }
942
-
943
- let mut patchelf = Command :: new ( nix_deps_dir. join ( "bin/patchelf" ) ) ;
944
- let rpath_entries = {
945
- // ORIGIN is a relative default, all binary and dynamic libraries we ship
946
- // appear to have this (even when `../lib` is redundant).
947
- // NOTE: there are only two paths here, delimited by a `:`
948
- let mut entries = OsString :: from ( "$ORIGIN/../lib:" ) ;
949
- entries. push ( t ! ( fs:: canonicalize( nix_deps_dir) ) ) ;
950
- entries. push ( "/lib" ) ;
951
- entries
952
- } ;
953
- patchelf. args ( & [ OsString :: from ( "--set-rpath" ) , rpath_entries] ) ;
954
- if !fname. extension ( ) . map_or ( false , |ext| ext == "so" ) {
955
- // Finally, set the correct .interp for binaries
956
- let dynamic_linker_path = nix_deps_dir. join ( "nix-support/dynamic-linker" ) ;
957
- // FIXME: can we support utf8 here? `args` doesn't accept Vec<u8>, only OsString ...
958
- let dynamic_linker = t ! ( String :: from_utf8( t!( fs:: read( dynamic_linker_path) ) ) ) ;
959
- patchelf. args ( & [ "--set-interpreter" , dynamic_linker. trim_end ( ) ] ) ;
960
- }
961
-
962
- self . try_run ( patchelf. arg ( fname) ) ;
963
- }
964
-
965
- pub ( crate ) fn download_component ( & self , url : & str , dest_path : & Path , help_on_error : & str ) {
966
- self . verbose ( & format ! ( "download {url}" ) ) ;
967
- // Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/.
968
- let tempfile = self . tempdir ( ) . join ( dest_path. file_name ( ) . unwrap ( ) ) ;
969
- // While bootstrap itself only supports http and https downloads, downstream forks might
970
- // need to download components from other protocols. The match allows them adding more
971
- // protocols without worrying about merge conflicts if we change the HTTP implementation.
972
- match url. split_once ( "://" ) . map ( |( proto, _) | proto) {
973
- Some ( "http" ) | Some ( "https" ) => {
974
- self . download_http_with_retries ( & tempfile, url, help_on_error)
975
- }
976
- Some ( other) => panic ! ( "unsupported protocol {other} in {url}" ) ,
977
- None => panic ! ( "no protocol in {url}" ) ,
978
- }
979
- t ! ( std:: fs:: rename( & tempfile, dest_path) ) ;
980
- }
981
-
982
- fn download_http_with_retries ( & self , tempfile : & Path , url : & str , help_on_error : & str ) {
983
- println ! ( "downloading {}" , url) ;
984
- // Try curl. If that fails and we are on windows, fallback to PowerShell.
985
- let mut curl = Command :: new ( "curl" ) ;
986
- curl. args ( & [
987
- "-#" ,
988
- "-y" ,
989
- "30" ,
990
- "-Y" ,
991
- "10" , // timeout if speed is < 10 bytes/sec for > 30 seconds
992
- "--connect-timeout" ,
993
- "30" , // timeout if cannot connect within 30 seconds
994
- "--retry" ,
995
- "3" ,
996
- "-Sf" ,
997
- "-o" ,
998
- ] ) ;
999
- curl. arg ( tempfile) ;
1000
- curl. arg ( url) ;
1001
- if !self . check_run ( & mut curl) {
1002
- if self . build . build . contains ( "windows-msvc" ) {
1003
- println ! ( "Fallback to PowerShell" ) ;
1004
- for _ in 0 ..3 {
1005
- if self . try_run ( Command :: new ( "PowerShell.exe" ) . args ( & [
1006
- "/nologo" ,
1007
- "-Command" ,
1008
- "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;" ,
1009
- & format ! (
1010
- "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')" ,
1011
- url, tempfile. to_str( ) . expect( "invalid UTF-8 not supported with powershell downloads" ) ,
1012
- ) ,
1013
- ] ) ) {
1014
- return ;
1015
- }
1016
- println ! ( "\n spurious failure, trying again" ) ;
1017
- }
1018
- }
1019
- if !help_on_error. is_empty ( ) {
1020
- eprintln ! ( "{}" , help_on_error) ;
1021
- }
1022
- crate :: detail_exit ( 1 ) ;
1023
- }
1024
- }
1025
-
1026
- pub ( crate ) fn unpack ( & self , tarball : & Path , dst : & Path , pattern : & str ) {
1027
- println ! ( "extracting {} to {}" , tarball. display( ) , dst. display( ) ) ;
1028
- if !dst. exists ( ) {
1029
- t ! ( fs:: create_dir_all( dst) ) ;
1030
- }
1031
-
1032
- // `tarball` ends with `.tar.xz`; strip that suffix
1033
- // example: `rust-dev-nightly-x86_64-unknown-linux-gnu`
1034
- let uncompressed_filename =
1035
- Path :: new ( tarball. file_name ( ) . expect ( "missing tarball filename" ) ) . file_stem ( ) . unwrap ( ) ;
1036
- let directory_prefix = Path :: new ( Path :: new ( uncompressed_filename) . file_stem ( ) . unwrap ( ) ) ;
1037
-
1038
- // decompress the file
1039
- let data = t ! ( File :: open( tarball) ) ;
1040
- let decompressor = XzDecoder :: new ( BufReader :: new ( data) ) ;
1041
-
1042
- let mut tar = tar:: Archive :: new ( decompressor) ;
1043
- for member in t ! ( tar. entries( ) ) {
1044
- let mut member = t ! ( member) ;
1045
- let original_path = t ! ( member. path( ) ) . into_owned ( ) ;
1046
- // skip the top-level directory
1047
- if original_path == directory_prefix {
1048
- continue ;
1049
- }
1050
- let mut short_path = t ! ( original_path. strip_prefix( directory_prefix) ) ;
1051
- if !short_path. starts_with ( pattern) {
1052
- continue ;
1053
- }
1054
- short_path = t ! ( short_path. strip_prefix( pattern) ) ;
1055
- let dst_path = dst. join ( short_path) ;
1056
- self . verbose ( & format ! ( "extracting {} to {}" , original_path. display( ) , dst. display( ) ) ) ;
1057
- if !t ! ( member. unpack_in( dst) ) {
1058
- panic ! ( "path traversal attack ??" ) ;
1059
- }
1060
- let src_path = dst. join ( original_path) ;
1061
- if src_path. is_dir ( ) && dst_path. exists ( ) {
1062
- continue ;
1063
- }
1064
- t ! ( fs:: rename( src_path, dst_path) ) ;
1065
- }
1066
- t ! ( fs:: remove_dir_all( dst. join( directory_prefix) ) ) ;
1067
- }
1068
-
1069
- /// Returns whether the SHA256 checksum of `path` matches `expected`.
1070
- pub ( crate ) fn verify ( & self , path : & Path , expected : & str ) -> bool {
1071
- use sha2:: Digest ;
1072
-
1073
- self . verbose ( & format ! ( "verifying {}" , path. display( ) ) ) ;
1074
- let mut hasher = sha2:: Sha256 :: new ( ) ;
1075
- // FIXME: this is ok for rustfmt (4.1 MB large at time of writing), but it seems memory-intensive for rustc and larger components.
1076
- // Consider using streaming IO instead?
1077
- let contents = if self . config . dry_run ( ) { vec ! [ ] } else { t ! ( fs:: read( path) ) } ;
1078
- hasher. update ( & contents) ;
1079
- let found = hex:: encode ( hasher. finalize ( ) . as_slice ( ) ) ;
1080
- let verified = found == expected;
1081
- if !verified && !self . config . dry_run ( ) {
1082
- println ! (
1083
- "invalid checksum: \n \
1084
- found: {found}\n \
1085
- expected: {expected}",
1086
- ) ;
1087
- }
1088
- return verified;
1089
- }
1090
-
1091
853
/// Obtain a compiler at a given stage and for a given host. Explicitly does
1092
854
/// not take `Compiler` since all `Compiler` instances are meant to be
1093
855
/// obtained through this function, since it ensures that they are valid
@@ -1301,19 +1063,6 @@ impl<'a> Builder<'a> {
1301
1063
None
1302
1064
}
1303
1065
1304
- /// Convenience wrapper to allow `builder.llvm_link_shared()` instead of `builder.config.llvm_link_shared(&builder)`.
1305
- pub ( crate ) fn llvm_link_shared ( & self ) -> bool {
1306
- Config :: llvm_link_shared ( self )
1307
- }
1308
-
1309
- pub ( crate ) fn download_rustc ( & self ) -> bool {
1310
- Config :: download_rustc ( self )
1311
- }
1312
-
1313
- pub ( crate ) fn initial_rustfmt ( & self ) -> Option < PathBuf > {
1314
- Config :: initial_rustfmt ( self )
1315
- }
1316
-
1317
1066
/// Prepares an invocation of `cargo` to be run.
1318
1067
///
1319
1068
/// This will create a `Command` that represents a pending execution of
0 commit comments