diff --git a/Library/Homebrew/extend/os/mac/keg_relocate.rb b/Library/Homebrew/extend/os/mac/keg_relocate.rb index 77c8a4ca31..5139d2494a 100644 --- a/Library/Homebrew/extend/os/mac/keg_relocate.rb +++ b/Library/Homebrew/extend/os/mac/keg_relocate.rb @@ -69,12 +69,32 @@ class Keg new_name = fixed_name(file, bad_name) change_install_name(bad_name, new_name, file) unless new_name == bad_name end + + # If none of the install names reference RPATH(s), then we can safely + # remove all RPATHs from the file. + if file.dynamically_linked_libraries.none? { |lib| lib.start_with?("@rpath") } + # Note: This could probably be made more efficient by reverse-sorting + # the RPATHs by offset and calling MachOFile#delete_command + # with repopulate: false. + file.rpaths.each { |r| file.delete_rpath(r) } + end end end generic_fix_dynamic_linkage end + def expand_rpath(file, bad_name) + suffix = bad_name.sub(/^@rpath/, "") + + file.rpaths.each do |rpath| + return rpath/suffix if (rpath/suffix).exist? + end + + opoo "Could not find library #{bad_name} for #{file}" + bad_name + end + # If file is a dylib or bundle itself, look for the dylib named by # bad_name relative to the lib directory, so that we can skip the more # expensive recursive search if possible. @@ -87,6 +107,8 @@ class Keg "@loader_path/#{bad_name}" elsif file.mach_o_executable? && (lib + bad_name).exist? "#{lib}/#{bad_name}" + elsif bad_name.start_with?("@rpath") && ENV["HOMEBREW_RELOCATE_METAVARS"] + expand_rpath file, bad_name elsif (abs_name = find_dylib(bad_name)) && abs_name.exist? abs_name.to_s else @@ -97,7 +119,7 @@ class Keg def each_install_name_for(file, &block) dylibs = file.dynamically_linked_libraries - dylibs.reject! { |fn| fn =~ /^@(loader_|executable_|r)path/ } + dylibs.reject! { |fn| fn =~ /^@(loader|executable)_path/ } dylibs.each(&block) end diff --git a/Library/Homebrew/os/mac/mach.rb b/Library/Homebrew/os/mac/mach.rb index 49e49cd702..4e7c86e98f 100644 --- a/Library/Homebrew/os/mac/mach.rb +++ b/Library/Homebrew/os/mac/mach.rb @@ -2,6 +2,10 @@ require "macho" require "os/mac/architecture_list" module MachOShim + extend Forwardable + + delegate [:dylib_id, :rpaths, :delete_rpath] => :macho + # @private def macho @macho ||= begin @@ -56,10 +60,6 @@ module MachOShim lcs.map(&:name).map(&:to_s).uniq end - def dylib_id - macho.dylib_id - end - def archs mach_data.map { |m| m.fetch :arch }.extend(ArchitectureListExtension) end