"""utils for patching libraries""" # Copyright (c) PyZMQ Developers. # Distributed under the terms of the Modified BSD License. import logging import os import re import sys from .misc import get_output_error pjoin = os.path.join # LIB_PAT from delocate LIB_PAT = re.compile( r"\s*(.*) \(compatibility version (\d+\.\d+\.\d+), " r"current version (\d+\.\d+\.\d+)\)" ) def _get_libs(fname): rc, so, se = get_output_error(['otool', '-L', fname]) if rc: logging.error(f"otool -L {fname} failed: {se!r}") return for line in so.splitlines()[1:]: m = LIB_PAT.match(line) if m: yield m.group(1) def _find_library(lib, path): """Find a library""" for d in path[::-1]: real_lib = os.path.join(d, lib) if os.path.exists(real_lib): return real_lib def _install_name_change(fname, lib, real_lib): rc, so, se = get_output_error( ['install_name_tool', '-change', lib, real_lib, fname] ) if rc: logging.error("Couldn't update load path: %s", se) def patch_lib_paths(fname, library_dirs): """Load any weakly-defined libraries from their real location (only on OS X) - Find libraries with `otool -L` - Update with `install_name_tool -change` """ if sys.platform != 'darwin': return libs = _get_libs(fname) for lib in libs: if not lib.startswith(('@', '/')): real_lib = _find_library(lib, library_dirs) if real_lib: _install_name_change(fname, lib, real_lib) __all__ = ['patch_lib_paths']