Module: OS::Linux::Keg Private
- Extended by:
- T::Helpers
- Included in:
- Keg
- Defined in:
- extend/os/linux/keg.rb,
extend/os/linux/keg_relocate.rb
This module is part of a private API. This module may only be used in the Homebrew/brew repository. Third parties should avoid using this module if possible, as it may be removed or changed without warning.
Instance Method Summary collapse
- #binary_executable_or_library_files ⇒ Array<ELFShim> private
- #change_rpath!(file, old_prefix, new_prefix, with_placeholders: false) ⇒ Boolean private
- #detect_cxx_stdlibs(options = {}) ⇒ Array<Symbol> private
- #elf_files ⇒ Array<ELFShim> private
- #relocate_dynamic_linkage(relocation, with_placeholders: false, files: nil) ⇒ Array<::Pathname> private
Instance Method Details
#binary_executable_or_library_files ⇒ Array<ELFShim>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
8 |
# File 'extend/os/linux/keg.rb', line 8 def binary_executable_or_library_files = elf_files |
#change_rpath!(file, old_prefix, new_prefix, with_placeholders: false) ⇒ Boolean
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'extend/os/linux/keg_relocate.rb', line 46 def change_rpath!(file, old_prefix, new_prefix, with_placeholders: false) return false if !file.elf? || !file.dynamic_elf? # Skip relocation of files with `protodesc_cold` sections because patchelf.rb seems to break them, # but only when bottling (as we don't want to break existing bottles that require relocation). # https://github.com/Homebrew/homebrew-core/pull/232490#issuecomment-3161362452 # Also skip relocation of files with `.bun` sections return false if with_placeholders && file.section_names.intersect?(["protodesc_cold", ".bun"]) updated = {} old_rpath = file.rpath new_rpath = if old_rpath rpath = old_rpath.split(":") .map { |x| x.sub(old_prefix, new_prefix) } .select { |x| x.start_with?(new_prefix, "$ORIGIN") } lib_path = "#{new_prefix}/lib" rpath << lib_path unless rpath.include? lib_path # Add GCC's lib directory (as of GCC 12+) to RPATH when there is existing versioned linkage. # This prevents broken linkage when pouring bottles built with an old GCC formula. unless name.match?(Version.formula_optionally_versioned_regex(:gcc)) rpath.map! { |rp| rp.sub(%r{lib/gcc/\d+$}, "lib/gcc/current") } end rpath.join(":") end updated[:rpath] = new_rpath if old_rpath != new_rpath old_interpreter = file.interpreter new_interpreter = if old_interpreter.nil? nil elsif File.readable? "#{new_prefix}/lib/ld.so" "#{new_prefix}/lib/ld.so" else old_interpreter.sub old_prefix, new_prefix end updated[:interpreter] = new_interpreter if old_interpreter != new_interpreter return false if updated.empty? file.patch!(interpreter: updated[:interpreter], rpath: updated[:rpath]) require_relocation! true end |
#detect_cxx_stdlibs(options = {}) ⇒ Array<Symbol>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'extend/os/linux/keg_relocate.rb', line 92 def detect_cxx_stdlibs( = {}) skip_executables = .fetch(:skip_executables, false) results = Set.new elf_files.each do |file| next unless file.dynamic_elf? next if file.binary_executable? && skip_executables dylibs = file.dynamically_linked_libraries results << :libcxx if dylibs.any? { |s| s.include? "libc++.so" } results << :libstdcxx if dylibs.any? { |s| s.include? "libstdc++.so" } end results.to_a end |
#elf_files ⇒ Array<ELFShim>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'extend/os/linux/keg_relocate.rb', line 107 def elf_files hardlinks = Set.new elf_files = [] path.find do |pn| next if pn.symlink? || pn.directory? pn = ELFPathname.wrap(pn) next if !pn.dylib? && !pn.binary_executable? # If we've already processed a file, ignore its hardlinks (which have the # same dev ID and inode). This prevents relocations from being performed # on a binary more than once. next unless hardlinks.add? [pn.stat.dev, pn.stat.ino] elf_files << pn end elf_files end |
#relocate_dynamic_linkage(relocation, with_placeholders: false, files: nil) ⇒ Array<::Pathname>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'extend/os/linux/keg_relocate.rb', line 17 def relocate_dynamic_linkage(relocation, with_placeholders: false, files: nil) # Patching the dynamic linker of glibc breaks it. return [] if name.match? Version.formula_optionally_versioned_regex(:glibc) old_prefix, new_prefix = relocation.replacement_pair_for(:prefix) candidates = if files # Metadata-driven pour: only the files recorded at bottle time carry # placeholdered linkage, so skip the whole-keg walk. keg_files(files).map { |file| ELFPathname.wrap(file) } else elf_files end linkage_files = [] candidates.each do |file| changed = T.let(false, T::Boolean) Utils::Path.ensure_writable(file.to_path) do changed = change_rpath!(file, old_prefix, new_prefix, with_placeholders:) end linkage_files << file.relative_path_from(path) if changed end linkage_files end |