Skip to content

Instantly share code, notes, and snippets.

@vitawasalreadytaken
Last active August 29, 2015 14:02
Show Gist options
  • Save vitawasalreadytaken/486b0c03dc38f327bef0 to your computer and use it in GitHub Desktop.
Save vitawasalreadytaken/486b0c03dc38f327bef0 to your computer and use it in GitHub Desktop.
Check that the Quickfix Python module is able to find the dynamically linked libraries it requires, and suggest how to fix incorrect paths.
import logging, os, subprocess
def checkQuickfixDylibs(soPath):
'''
Verify that _quickfix.so's required dylibs exist, and suggest how to fix incorrect paths.
It is assumed that missing libs (most likely just libquickfix.14.dylib) should be present
in the same directory as _quickfix.so.
:param soPath: path/to/_quickfix.so (or path/to/libquickfix_python.10.dylib).
'''
system = subprocess.check_output(('uname', '-s')).strip()
if system == 'Darwin':
# Mac OS X. Use otool.
otool = subprocess.check_output(('otool', '-L', soPath)).strip()
# Possible output:
# path/to/_quickfix.so:
# /tmp/quickfix/prefix/lib/libquickfix_python.10.dylib (compatibility version 11.0.0, current version 11.0.0)
# /tmp/quickfix/src/C++/.libs/libquickfix.14.dylib (compatibility version 15.0.0, current version 15.0.0)
# /usr/lib/libxml2.2.dylib (compatibility version 10.0.0, current version 10.9.0)
# /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
# /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
libs = [ L.strip().split(' ', 1)[0] for L in otool.split('\n')[1:] ]
logging.debug('Quickfix at path = %s requires shared libs = %r.', soPath, libs)
for path in libs:
if os.path.basename(path) != 'libquickfix_python.10.dylib':
# libquickfix_python.10.dylib refers to the Python module itself and can be safely ignored.
if not os.path.exists(path):
possiblePath = os.path.abspath(os.path.join(os.path.dirname(soPath), os.path.basename(path)))
fix = 'install_name_tool -change {missing} {correct} {so}'.format(missing = path, correct = possiblePath, so = soPath)
raise RuntimeError('Shared library = {0} does not exist. Run `{1}` to fix the path.'.format(path, fix))
elif system == 'Linux':
# Linux. Use ldd.
ldd = subprocess.check_output(('ldd', soPath)).strip()
# Possible output:
# linux-vdso.so.1 => (0x00007fffa8dfe000)
# libquickfix.so.14 => not found
# libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f74a1bbb000)
# libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f74a18b7000)
# libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f74a14f1000)
# libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f74a12da000)
# /lib64/ld-linux-x86-64.so.2 (0x00007f74a296e000)
# libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f74a0fd4000)
lines = [ L.strip() for L in ldd.split('\n') ]
logging.debug('Quickfix at path = %s requires shared libs = %r.', soPath, lines)
for line in lines:
if '=>' in line:
name, details = line.split(' => ')
if details == 'not found':
possibleRpath = os.path.abspath(os.path.join(os.path.dirname(soPath)))
fix = 'patchelf --set-rpath {rpath} {so}'.format(rpath = possibleRpath, so = soPath)
raise RuntimeError('Shared library = {0} does not exist. Run `{1}` to fix the rpath (http://nixos.org/patchelf.html).'.format(name, fix))
else:
raise RuntimeError('Unknown operating system: {}'.format(system))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment