From 60b97a2f3d6bd60edf7f9410ce04fd38e33a2192 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 22 Mar 2024 21:52:44 +0100 Subject: [PATCH] Fix nix patching for LLVM 18 LLVM 18 now ships `libLLVM*.so.*`, so `.so` is not the sole extension anymore, which breaks the dylib detection. Oops! Adjust it to only search for `.so` somewhere. --- src/bootstrap/bootstrap.py | 12 +++++++++--- src/bootstrap/src/core/download.rs | 15 ++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 6e49bcc974469..30d728aa23005 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -612,8 +612,14 @@ def download_toolchain(self): self.fix_bin_or_dylib("{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root)) lib_dir = "{}/lib".format(bin_root) for lib in os.listdir(lib_dir): - if lib.endswith(".so"): - self.fix_bin_or_dylib(os.path.join(lib_dir, lib)) + # .so is not necessarily the suffix, there can be version numbers afterwards. + if ".so" in lib: + elf_path = os.path.join(lib_dir, lib) + with open(elf_path, "rb") as f: + magic = f.read(4) + # Patchelf will skip non-ELF files, but issue a warning. + if magic == b"\x7fELF": + self.fix_bin_or_dylib(elf_path) with output(self.rustc_stamp()) as rust_stamp: rust_stamp.write(key) @@ -725,7 +731,7 @@ def fix_bin_or_dylib(self, fname): os.path.join(os.path.realpath(nix_deps_dir), "lib") ] patchelf_args = ["--set-rpath", ":".join(rpath_entries)] - if not fname.endswith(".so"): + if ".so" not in fname: # Finally, set the correct .interp for binaries with open("{}/nix-support/dynamic-linker".format(nix_deps_dir)) as dynamic_linker: patchelf_args += ["--set-interpreter", dynamic_linker.read().rstrip()] diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 251138388cafd..75e0f646da699 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -1,6 +1,6 @@ use std::{ env, - ffi::{OsStr, OsString}, + ffi::OsString, fs::{self, File}, io::{BufRead, BufReader, BufWriter, ErrorKind, Write}, path::{Path, PathBuf}, @@ -183,7 +183,7 @@ impl Config { entries }; patchelf.args(&[OsString::from("--set-rpath"), rpath_entries]); - if !fname.extension().map_or(false, |ext| ext == "so") { + if !path_is_dylib(fname) { // Finally, set the correct .interp for binaries let dynamic_linker_path = nix_deps_dir.join("nix-support/dynamic-linker"); // FIXME: can we support utf8 here? `args` doesn't accept Vec, only OsString ... @@ -440,7 +440,7 @@ impl Config { let lib_dir = bin_root.join("lib"); for lib in t!(fs::read_dir(&lib_dir), lib_dir.display().to_string()) { let lib = t!(lib); - if lib.path().extension() == Some(OsStr::new("so")) { + if path_is_dylib(&lib.path()) { self.fix_bin_or_dylib(&lib.path()); } } @@ -545,7 +545,7 @@ impl Config { let lib_dir = bin_root.join("lib"); for lib in t!(fs::read_dir(&lib_dir), lib_dir.display().to_string()) { let lib = t!(lib); - if lib.path().extension() == Some(OsStr::new("so")) { + if path_is_dylib(&lib.path()) { self.fix_bin_or_dylib(&lib.path()); } } @@ -697,7 +697,7 @@ download-rustc = false let llvm_lib = llvm_root.join("lib"); for entry in t!(fs::read_dir(llvm_lib)) { let lib = t!(entry).path(); - if lib.extension().map_or(false, |ext| ext == "so") { + if path_is_dylib(&lib) { self.fix_bin_or_dylib(&lib); } } @@ -743,3 +743,8 @@ download-rustc = false self.unpack(&tarball, &llvm_root, "rust-dev"); } } + +fn path_is_dylib(path: &Path) -> bool { + // The .so is not necessarily the extension, it might be libLLVM.so.18.1 + path.to_str().map_or(false, |path| path.contains(".so")) +}