diff options
| author | Jack Nagel | 2012-06-16 16:14:47 -0500 |
|---|---|---|
| committer | Jack Nagel | 2012-06-17 16:22:08 -0500 |
| commit | 58d4a95ea71eef583ad1ceb938113ff7773b437e (patch) | |
| tree | 4bf71762e3e7de9ac6375b6c0c4b9b142151a365 /Library/Homebrew | |
| parent | 6229a20db7a8345b61b4a86484e55825f6ff5e86 (diff) | |
| download | brew-58d4a95ea71eef583ad1ceb938113ff7773b437e.tar.bz2 | |
fix_install_names: try harder to find referenced dylibs
Keg#fix_install_names punts if bad install names reference dylibs that
aren't "nearby". Enable this machinery to fix more complex directory
hierarchies by searching everything under 'lib' for the bad name's
basename.
Additionally, teach it to correctly handle Mach-O bundle files.
Fixes Homebrew/homebrew#12810.
Signed-off-by: Jack Nagel <jacknagel@gmail.com>
Diffstat (limited to 'Library/Homebrew')
| -rw-r--r-- | Library/Homebrew/keg_fix_install_names.rb | 69 |
1 files changed, 42 insertions, 27 deletions
diff --git a/Library/Homebrew/keg_fix_install_names.rb b/Library/Homebrew/keg_fix_install_names.rb index a4385d752..e2582c688 100644 --- a/Library/Homebrew/keg_fix_install_names.rb +++ b/Library/Homebrew/keg_fix_install_names.rb @@ -1,21 +1,31 @@ +require 'find' + class Keg def fix_install_names - dylibs.each do |dylib| - bad_install_names_for dylib do |id, bad_names| - dylib.ensure_writable do - system "install_name_tool", "-id", id, dylib + mach_o_files.each do |file| + bad_install_names_for file do |id, bad_names| + file.ensure_writable do + system "install_name_tool", "-id", id, file if file.dylib? + bad_names.each do |bad_name| new_name = bad_name - new_name = Pathname.new(bad_name).basename unless (dylib.parent + new_name).exist? - # this fixes some problems, maybe not all. opencv seems to have badnames of the type - # "lib/libblah.dylib" - if (dylib.parent + new_name).exist? - system "install_name_tool", "-change", bad_name, "@loader_path/#{new_name}", dylib + new_name = Pathname.new(bad_name).basename unless (file.parent + new_name).exist? + + # First check to see if the dylib is present in the current + # directory, so we can skip the more expensive search. + if (file.parent + new_name).exist? + system "install_name_tool", "-change", bad_name, "@loader_path/#{new_name}", file else - opoo "Could not fix install names for #{dylib}" - if ARGV.debug? - puts "bad_name: #{bad_name}" - puts "new_name: #{new_name}" + # Otherwise, try and locate the appropriate dylib by walking + # the entire 'lib' tree recursively. + abs_name = (self+'lib').find do |pn| + break pn if pn.basename == Pathname.new(new_name) + end + + if abs_name and abs_name.exist? + system "install_name_tool", "-change", bad_name, abs_name, file + else + opoo "Could not fix install names for #{file}" end end end @@ -28,35 +38,40 @@ class Keg 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" + def bad_install_names_for file + ENV['HOMEBREW_MACH_O_FILE'] = file.to_s # solves all shell escaping problems + install_names = `otool -L "$HOMEBREW_MACH_O_FILE"`.split "\n" install_names.shift # first line is fluff install_names.map!{ |s| OTOOL_RX =~ s && $1 } - id = install_names.shift + + # Bundles don't have an ID + id = install_names.shift unless file.mach_o_bundle? + install_names.compact! install_names.reject!{ |fn| fn =~ /^@(loader|executable)_path/ } - install_names.reject!{ |fn| fn[0,1] == '/' } + + # Don't fix absolute paths unless they are rooted in the build directory + install_names.reject! do |fn| + tmp = ENV['HOMEBREW_TEMP'] ? Regexp.escape(ENV['HOMEBREW_TEMP']) : '/tmp' + fn[0,1] == '/' and not %r[^#{tmp}] === fn + end # the shortpath ensures that library upgrades don’t break installed tools - shortpath = HOMEBREW_PREFIX + Pathname.new(dylib).relative_path_from(self) - id = if shortpath.exist? then shortpath else dylib end + shortpath = HOMEBREW_PREFIX + Pathname.new(file).relative_path_from(self) + id = if shortpath.exist? then shortpath else file end yield id, install_names end - def dylibs - require 'find' - dylibs = [] + def mach_o_files + mach_o_files = [] if (lib = join 'lib').directory? lib.find do |pn| next if pn.symlink? or pn.directory? - dylibs << pn if pn.dylib? + mach_o_files << pn if pn.dylib? or pn.mach_o_bundle? end end - dylibs + mach_o_files end end |
