#!/usr/bin/ruby # Wrapper around the information provided by 'otool -L' # and the editing capabilities of 'install_name_tool'. class Dylib def initialize(path) @path = path end def libraries lines = %x[otool -arch all -L '#{@path}'].split("\n") libraries = lines.reject { |line| line =~ /:$/ } libraries.map! { |line| line.split[0] } libraries.uniq end def install_name %x[otool -D '#{@path}'].split("\n")[1] end def install_name=(name) system "install_name_tool", "-id", name, @path end def change_library(old_path, new_path) system "install_name_tool", "-change", old_path, new_path, @path end end if __FILE__ == $0 then # Command line tool to change a shared library prefix referenced # in a library. require 'optparse' require 'ostruct' $config = config = OpenStruct.new config.verbose = false ARGV.options do |opts| opts.banner = "usage: #{File.basename(__FILE__)} [options] FILES" opts.on('--old PREFIX') { |config.old_prefix| } opts.on('--new PREFIX') { |config.new_prefix| } opts.on('-v', '--verbose') { config.verbose = true } opts.parse! end if not config.old_prefix or not config.old_prefix then $stderr.puts "Need old and new prefix" exit 1 end def msg(msg) $stderr.puts msg if $config.verbose end old_re = /^#{config.old_prefix}/ ARGV.each do |file| msg "Working on #{file}" d = Dylib.new(file) install_name = d.install_name if install_name =~ old_re then new_install_name = install_name.sub(old_re) { config.new_prefix } msg " Changing install name from #{install_name} to #{new_install_name}" d.install_name = new_install_name end d.libraries.each do |library| if library =~ old_re then new_library = library.sub(old_re) { config.new_prefix } msg " Changing library ref from #{library} to #{new_library}" d.change_library(library, new_library) end end end end