diff --git a/Library/Homebrew/extend/os/linux/keg_relocate.rb b/Library/Homebrew/extend/os/linux/keg_relocate.rb index 2866373b91..5d25692fd1 100644 --- a/Library/Homebrew/extend/os/linux/keg_relocate.rb +++ b/Library/Homebrew/extend/os/linux/keg_relocate.rb @@ -18,10 +18,7 @@ class Keg def change_rpath(file, old_prefix, new_prefix) return if !file.elf? || !file.dynamic_elf? - patchelf = DevelopmentTools.locate "patchelf" - odie "Could not locate patchelf, please: brew install patchelf." if patchelf.nil? - cmd = [patchelf] - + updated = {} old_rpath = file.rpath new_rpath = if old_rpath rpath = old_rpath.split(":") @@ -30,11 +27,10 @@ class Keg lib_path = "#{new_prefix}/lib" rpath << lib_path unless rpath.include? lib_path - new_rpath = rpath.join(":") - cmd.push "--force-rpath", "--set-rpath", new_rpath - new_rpath + rpath.join(":") end + updated[:rpath] = new_rpath if old_rpath != new_rpath old_interpreter = file.interpreter new_interpreter = if old_interpreter.nil? @@ -44,11 +40,9 @@ class Keg else old_interpreter.sub old_prefix, new_prefix end - cmd << "--set-interpreter" << new_interpreter if old_interpreter != new_interpreter + updated[:interpreter] = new_interpreter if old_interpreter != new_interpreter - return if old_rpath == new_rpath && old_interpreter == new_interpreter - - safe_system(*cmd, file) + file.patch!(interpreter: updated[:interpreter], rpath: updated[:rpath]) end def detect_cxx_stdlibs(options = {}) diff --git a/Library/Homebrew/os/linux/elf.rb b/Library/Homebrew/os/linux/elf.rb index a0d84e7d4f..c4d8dae4cd 100644 --- a/Library/Homebrew/os/linux/elf.rb +++ b/Library/Homebrew/os/linux/elf.rb @@ -98,6 +98,16 @@ module ELFShim @interpreter = patchelf_patcher.interpreter end + def patch!(interpreter: nil, rpath: nil) + return if interpreter.blank? && rpath.blank? + + if HOMEBREW_PATCHELF_RB_WRITE + save_using_patchelf_rb interpreter, rpath + else + save_using_patchelf interpreter, rpath + end + end + def dynamic_elf? return @dynamic_elf if defined? @dynamic_elf @@ -148,13 +158,30 @@ module ELFShim end private_constant :Metadata + def save_using_patchelf(new_interpreter, new_rpath) + patchelf = DevelopmentTools.locate "patchelf" + odie "Could not locate patchelf, please: brew install patchelf." if patchelf.blank? + args = [] + args << "--set-interpreter" << new_interpreter if new_interpreter.present? + args << "--force-rpath" << "--set-rpath" << new_rpath if new_rpath.present? + + Homebrew.safe_system(patchelf, *args, to_s) + end + + def save_using_patchelf_rb(new_interpreter, new_rpath) + patcher = patchelf_patcher + patcher.interpreter = new_interpreter if new_interpreter.present? + patcher.rpath = new_rpath if new_rpath.present? + patcher.save(patchelf_compatible: true) + end + def rpath_using_patchelf_rb patchelf_patcher.runpath || patchelf_patcher.rpath end def patchelf_patcher require "patchelf" - @patchelf_patcher ||= PatchELF::Patcher.new to_s, on_error: :silent + @patchelf_patcher ||= ::PatchELF::Patcher.new to_s, on_error: :silent end def metadata diff --git a/Library/Homebrew/os/linux/global.rb b/Library/Homebrew/os/linux/global.rb index e0b8724930..32dd99c2fb 100644 --- a/Library/Homebrew/os/linux/global.rb +++ b/Library/Homebrew/os/linux/global.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +# enables experimental patchelf.rb write support. +HOMEBREW_PATCHELF_RB_WRITE = ENV["HOMEBREW_PATCHELF_RB_WRITE"].present?.freeze + module Homebrew DEFAULT_PREFIX ||= if Homebrew::EnvConfig.force_homebrew_on_linux? HOMEBREW_DEFAULT_PREFIX