brew/Library/Homebrew/keg_fix_install_names.rb
Max Howell 215fcd3292 Fix upgrading libdeps breaking stuff after cleanups
Fixes Homebrew/homebrew#2709.

By forcing dylibs to have an install_name id that is the HOMEBREW_PREFIX path, ie. the symlink’s path. Stuff that links to these dylibs will use this id and thus by immune to upgrades of underlying libraries.

Thus whatever keg is "current" ie. linked, will be the library that is used by the tool.

This fix is not retroactive. So there will still be breakage for existing installations of stuff.

The fix_install step in install is moved after the link step as the symlinking
is required to determine the eventual ids for each dylib.
2011-06-17 09:30:25 +01:00

51 lines
1.6 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class Keg
def fix_install_names
dylibs.each do |dylib|
bad_install_names_for dylib do |id, bad_names|
# avoid the chmod change if unecessary—I'm not convinced it reverses right
next if bad_names.empty? and id.to_s == dylib.to_s
dylib.ensure_writable do
system "install_name_tool", "-id", id, dylib
bad_names.each do |bad_name|
# we should be more careful here, check the path we point to exists etc.
system "install_name_tool", "-change", bad_name, "@loader_path/#{bad_name}", dylib
end
end
end
end
end
private
OTOOL_RX = /\t(.*) \(compatibility version (\d+\.)*\d+, current version (\d+\.)*\d+\)/
def bad_install_names_for dylib
dylib = dylib.to_s
ENV['HOMEBREW_DYLIB'] = dylib # solves all shell escaping problems
install_names = `otool -L "$HOMEBREW_DYLIB"`.split "\n"
install_names.shift # first line is fluff
install_names.map!{ |s| OTOOL_RX =~ s && $1 }
id = install_names.shift
install_names.compact!
install_names.reject!{ |fn| fn =~ /^@(loader|executable)_path/ }
install_names.reject!{ |fn| fn[0,1] == '/' }
# the shortpath ensures that library upgrades dont break installed tools
shortpath = HOMEBREW_PREFIX + Pathname.new(dylib).relative_path_from(self)
id = if shortpath.exist? then shortpath else dylib end
yield id, install_names
end
def dylibs
if (lib = join 'lib').directory?
lib.children.select{ |pn| pn.extname == '.dylib' and not pn.symlink? }
else
[]
end
end
end