def __init__(self, otool_output): self.data = otool_output.split('\n') self._library_path = self.data[0][0:-1] self._library_name = self._library_path.split('/')[-1] useless_data = re.compile(r' \(.*\)') libs = [useless_data.sub('',x.lstrip()) for x in self.data[1:-1] if x.count('framework') == 0] self.base_libs = [x for x in libs if x.startswith('/usr/') and self.third_libs = [x for x in libs if x not in self.base_libs and def built_in_shlib_deps(self): return self._library_path return self._library_name def third_party_shlib_deps(self): def otool_library(path, arch = None): command_str = 'otool -L ' command_str += '-arch ' + arch + ' ' otool_file = os.popen(command_str) otool_data = otool_file.read() parser = OtoolParser(otool_data) '''Runs otool on the library at lib. Returns an otool_parse.OtoolParser. otool_file = os.popen('otool -L "' + lib +'"') otool_data = otool_file.read() return OtoolParser(otool_data) def discover_all_dependencies(lib): '''Find all dependencies for library at path in lib. dep_parser = otool_library(lib) return dep_parser.third_party_shlib_deps() def lib_path_to_framework_and_version(library_path): library_name = library_path.split('/')[-1] # check to see if it's a "versionless" library name match = re.match(r'[A-Za-z]*\.dylib', library_name) library_name = library_name.replace('.dylib','') return (library_name, 'A') # Note: these styles are named after where I noticed them, not necessarily # where they originate. -RAF regexes = [r'([A-Za-z0-9_-]*)-([0-9\.]*)$', #apr style r'([A-Za-z0-9_-]*[a-zA-Z])\.([0-9\.]*)$', #gnu style r'([A-Za-z0-9_-]*[a-zA-Z])([0-9\.]*)$', #sqlite style match = re.match(regex, library_name) # If we get here, we need a new regex. Throw an exception. raise ValueError, ('Library ' + library_path + ' with name ' + library_name + ' did not match any known format, please update the' if __name__ == '__main__': print 'Usage:', sys.argv[0], '/paths/to/libraries', 'output_plugin_dir' plugins_dir = sys.argv[1] known_frameworks = [d[0:len(d)-len(".subproj")] for d in dircache.listdir("Frameworks/") if d.endswith(".subproj")] plugins = [plugins_dir+'/'+d for d in dircache.listdir(plugins_dir) if d.endswith('.so')] libs_to_convert = discover_all_dependencies(library) for l in libs_to_convert: for known_framework in known_frameworks: if l.find(known_framework + "-") != -1 or l.find(known_framework + ".") != -1: new_path = lib_path_to_framework_and_version(l) new_path = '@executable_path/../Frameworks/' + new_path[0] + '.framework/Versions/' + new_path[1] + '/' + new_path[0] pos = output_dir.find(".subproj/") + len(".subproj/") new_path = l.replace(plugins_dir, "@executable_path/../Frameworks/" + output_dir[pos:-1]) args = ['install_name_tool', '-change', l, new_path, library] status = os.spawnvp(os.P_WAIT, 'install_name_tool', args) print 'Something went wrong. install_name_tool failed for ', l, print ' with status ', status