@@ -429,7 +429,7 @@ def download_toolchain(self, stage0=True, rustc_channel=None):
429429 lib_dir = "{}/lib" .format (bin_root )
430430 for lib in os .listdir (lib_dir ):
431431 if lib .endswith (".so" ):
432- self .fix_bin_or_dylib (os .path .join (lib_dir , lib ), rpath_libz = True )
432+ self .fix_bin_or_dylib (os .path .join (lib_dir , lib ))
433433 with output (self .rustc_stamp (stage0 )) as rust_stamp :
434434 rust_stamp .write (key )
435435
@@ -477,10 +477,10 @@ def download_toolchain(self, stage0=True, rustc_channel=None):
477477 if self .program_out_of_date (self .llvm_stamp (), llvm_sha + str (llvm_assertions )):
478478 self ._download_ci_llvm (llvm_sha , llvm_assertions )
479479 for binary in ["llvm-config" , "FileCheck" ]:
480- self .fix_bin_or_dylib (os .path .join (llvm_root , "bin" , binary ), rpath_libz = True )
480+ self .fix_bin_or_dylib (os .path .join (llvm_root , "bin" , binary ))
481481 for lib in os .listdir (llvm_lib ):
482482 if lib .endswith (".so" ):
483- self .fix_bin_or_dylib (os .path .join (llvm_lib , lib ), rpath_libz = True )
483+ self .fix_bin_or_dylib (os .path .join (llvm_lib , lib ))
484484 with output (self .llvm_stamp ()) as llvm_stamp :
485485 llvm_stamp .write (llvm_sha + str (llvm_assertions ))
486486
@@ -548,7 +548,7 @@ def _download_ci_llvm(self, llvm_sha, llvm_assertions):
548548 match = "rust-dev" ,
549549 verbose = self .verbose )
550550
551- def fix_bin_or_dylib (self , fname , rpath_libz = False ):
551+ def fix_bin_or_dylib (self , fname ):
552552 """Modifies the interpreter section of 'fname' to fix the dynamic linker,
553553 or the RPATH section, to fix the dynamic library search path
554554
@@ -583,56 +583,49 @@ def fix_bin_or_dylib(self, fname, rpath_libz=False):
583583 # Only build `.nix-deps` once.
584584 nix_deps_dir = self .nix_deps_dir
585585 if not nix_deps_dir :
586- nix_deps_dir = ".nix-deps"
587- if not os .path .exists (nix_deps_dir ):
588- os .makedirs (nix_deps_dir )
589-
590- nix_deps = [
591- # Needed for the path of `ld-linux.so` (via `nix-support/dynamic-linker`).
592- "stdenv.cc.bintools" ,
593-
594- # Needed as a system dependency of `libLLVM-*.so`.
595- "zlib" ,
596-
597- # Needed for patching ELF binaries (see doc comment above).
598- "patchelf" ,
599- ]
600-
601586 # Run `nix-build` to "build" each dependency (which will likely reuse
602587 # the existing `/nix/store` copy, or at most download a pre-built copy).
603- # Importantly, we don't rely on `nix-build` printing the `/nix/store`
604- # path on stdout, but use `-o` to symlink it into `stage0/.nix-deps/$dep`,
605- # ensuring garbage collection will never remove the `/nix/store` path
606- # (which would break our patched binaries that hardcode those paths).
607- for dep in nix_deps :
608- try :
609- subprocess .check_output ([
610- "nix-build" , "<nixpkgs>" ,
611- "-A" , dep ,
612- "-o" , "{}/{}" .format (nix_deps_dir , dep ),
613- ])
614- except subprocess .CalledProcessError as reason :
615- print ("warning: failed to call nix-build:" , reason )
616- return
617-
588+ #
589+ # Importantly, we create a gc-root called `.nix-deps` in the `build/`
590+ # directory, but still reference the actual `/nix/store` path in the rpath
591+ # as it makes it significantly more robust against changes to the location of
592+ # the `.nix-deps` location.
593+ #
594+ # bintools: Needed for the path of `ld-linux.so` (via `nix-support/dynamic-linker`).
595+ # zlib: Needed as a system dependency of `libLLVM-*.so`.
596+ # patchelf: Needed for patching ELF binaries (see doc comment above).
597+ nix_deps_dir = "{}/{}" .format (self .build_dir , ".nix-deps" )
598+ nix_expr = '''
599+ with (import <nixpkgs> {});
600+ symlinkJoin {
601+ name = "rust-stage0-dependencies";
602+ paths = [
603+ zlib
604+ patchelf
605+ stdenv.cc.bintools
606+ ];
607+ }
608+ '''
609+ try :
610+ subprocess .check_output ([
611+ "nix-build" , "-E" , nix_expr , "-o" , nix_deps_dir ,
612+ ])
613+ except subprocess .CalledProcessError as reason :
614+ print ("warning: failed to call nix-build:" , reason )
615+ return
618616 self .nix_deps_dir = nix_deps_dir
619617
620- patchelf = "{}/patchelf/bin/patchelf" .format (nix_deps_dir )
621- patchelf_args = []
622-
623- if rpath_libz :
624- # Patch RPATH to add `zlib` dependency that stems from LLVM
625- dylib_deps = ["zlib" ]
626- rpath_entries = [
627- # Relative default, all binary and dynamic libraries we ship
628- # appear to have this (even when `../lib` is redundant).
629- "$ORIGIN/../lib" ,
630- ] + ["{}/{}/lib" .format (nix_deps_dir , dep ) for dep in dylib_deps ]
631- patchelf_args += ["--set-rpath" , ":" .join (rpath_entries )]
618+ patchelf = "{}/bin/patchelf" .format (nix_deps_dir )
619+ rpath_entries = [
620+ # Relative default, all binary and dynamic libraries we ship
621+ # appear to have this (even when `../lib` is redundant).
622+ "$ORIGIN/../lib" ,
623+ os .path .join (os .path .realpath (nix_deps_dir ), "lib" )
624+ ]
625+ patchelf_args = ["--set-rpath" , ":" .join (rpath_entries )]
632626 if not fname .endswith (".so" ):
633627 # Finally, set the corret .interp for binaries
634- bintools_dir = "{}/stdenv.cc.bintools" .format (nix_deps_dir )
635- with open ("{}/nix-support/dynamic-linker" .format (bintools_dir )) as dynamic_linker :
628+ with open ("{}/nix-support/dynamic-linker" .format (nix_deps_dir )) as dynamic_linker :
636629 patchelf_args += ["--set-interpreter" , dynamic_linker .read ().rstrip ()]
637630
638631 try :
0 commit comments