bottle: improve relocatable debugging.

* When Homebrew developer mode is enabled, if a bottle is not found to
  be relocatable attempt to explain why
* Print out paths of each file that still contains the string search for
* If the string searched for was found in an executable, check to see
  if `otool` can explain the string's appearance
* If otool can't explain, see if `strings` can explain

Closes Homebrew/homebrew#23824.

Signed-off-by: Mike McQuaid <mike@mikemcquaid.com>
This commit is contained in:
Elliot Saba 2013-10-31 01:20:28 -07:00 committed by Mike McQuaid
parent d311fe666c
commit c20f6395bb

View File

@ -5,6 +5,8 @@ require 'keg'
require 'cmd/versions'
require 'utils/inreplace'
require 'erb'
require 'open3'
require 'extend/pathname'
class BottleMerger < Formula
# This provides a URL and Version which are the only needed properties of
@ -42,7 +44,46 @@ module Homebrew extend self
end
def keg_contains string, keg
quiet_system 'fgrep', '--recursive', '--quiet', '--max-count=1', string, keg
if not ARGV.homebrew_developer?
return quiet_system 'fgrep', '--recursive', '--quiet', '--max-count=1', string, keg
end
# Find all files that still reference the keg via a string search
keg_ref_files = `/usr/bin/fgrep --files-with-matches --recursive "#{string}" "#{keg}" 2>/dev/null`
keg_ref_files = (keg_ref_files.map{ |file| Pathname.new(file.strip) }).reject(&:symlink?)
# If there are no files with that string found, return immediately
return false if keg_ref_files.empty?
# Start printing out each file and any extra information we can find
opoo "String '#{string}' still exists in these files:"
keg_ref_files.each do |file|
puts "#{Tty.red}#{file}#{Tty.reset}"
# If we can't use otool on this file, just skip to the next file
next if not file.mach_o_executable? and not file.mach_o_bundle? and not file.dylib? and not file.extname == '.a'
# Get all libraries this file links to, then display only links to libraries that contain string in the path
linked_libraries = `otool -L "#{file}"`.split("\n").drop(1)
linked_libraries.map!{ |lib| lib.strip.split()[0] }
linked_libraries = linked_libraries.select{ |lib| lib.include? string }
linked_libraries.each do |lib|
puts " #{Tty.gray}-->#{Tty.reset} links to #{lib}"
end
# Use strings to search through the file for each string
strings = `strings -t x - "#{file}"`.select{ |str| str.include? string }.map{ |s| s.strip }
# Don't bother reporting a string if it was found by otool
strings.reject!{ |str| linked_libraries.include? str.split[1] }
strings.each do |str|
offset, match = str.split
puts " #{Tty.gray}-->#{Tty.reset} match '#{match}' at offset #{Tty.em}0x#{offset}#{Tty.reset}"
end
end
puts
true
end
def bottle_output bottle