Permalink
Browse files

Merge pull request #146 from stefanha/fix-install-names-part-2

Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
  • Loading branch information...
stefanha committed Jan 2, 2017
2 parents d7b1652 + 050eaa4 commit 612c9e9a635a38c6e0fbf773167c8f4a5d62507f
Showing with 45 additions and 11 deletions.
  1. +45 −11 qtclient/installer/macosx/fix-install-names.py
@@ -25,45 +25,79 @@
import os
import re
DEPENDENCY_RE = re.compile(r'\s+(/usr/local/.+\.dylib) \(compatibility version [^,]+, current version [^)]+\)')
DEPENDENCY_RE = re.compile(r'\s+(/usr/local/[^\s]+) \(compatibility version [^,]+, current version [^)]+\)')
executable_paths = {}
processed = set()
def usage(argv):
print 'usage: %s APP_BUNDLE_PATH' % argv[0]
sys.exit(1)
def process_dylib(filename):
def get_executable_rel_path(filename):
components = filename.split(os.sep)
if 'lib' in components:
idx = components.index('lib')
libdir = 'Frameworks'
elif 'plugins' in components:
idx = components.index('plugins')
libdir = 'PlugIns'
else:
raise ValueError('get_bundle_path: unable to handle file %s' % filename)
return os.path.join('..', libdir, *components[idx + 1:])
def process_macho(filename):
if filename in processed:
return
processed.add(filename)
print 'Processing %s...' % filename
# Update shared library id
output = subprocess.check_output(['otool', '-D', filename], stderr=subprocess.STDOUT)
macho_id = output.splitlines()[-1]
if macho_id.startswith('/usr/local/'):
new_id = os.path.join('@executable_path', '..', get_executable_rel_path(macho_id))
print 'Updating shared library id %s to %s...' % (macho_id, new_id)
subprocess.check_call(['install_name_tool', '-id', new_id, filename])
# Change dependencies to bundle-relative paths
pending = set()
output = subprocess.check_output(['otool', '-L', filename], stderr=subprocess.STDOUT)
for line in output.splitlines():
m = DEPENDENCY_RE.match(line)
if not m:
continue
dependency = m.group(1)
new_path = executable_paths[os.path.basename(dependency)]
rel_path = get_executable_rel_path(dependency)
pending.add(os.path.join(executable_dir, rel_path))
new_path = os.path.join('@executable_path', rel_path)
print 'Changing %s to %s...' % (dependency, new_path)
subprocess.check_call(['install_name_tool', '-change', dependency, new_path, filename])
for path in pending:
process_macho(path)
def main(argv):
global executable_dir
if len(argv) != 2:
usage(argv)
executable_dir = os.path.join(argv[1], 'Contents', 'MacOS')
dylibs = []
for dirpath, dirnames, filenames in os.walk(executable_dir):
for filename in filenames:
path = os.path.join(dirpath, filename)
process_macho(path)
for dirpath, dirnames, filenames in os.walk(argv[1]):
for filename in filter(lambda s: s.endswith('.dylib'), filenames):
path = os.path.join(dirpath, filename)
rel_path = os.path.relpath(path, executable_dir)
executable_paths[filename] = os.path.join('@executable_path', rel_path)
dylibs.append(path)
for filename in dylibs:
process_dylib(filename)
process_macho(path)
return 0

0 comments on commit 612c9e9

Please sign in to comment.