dyld emulation these are the defaults as per man dyld1 for a potential path iterator add dyldimagesuffix semantics suffix dyldimagesuffixenv if suffix is none return iterator def injectiteratoriterator suffixsuffix for path in iterator if path endswith dylib yield path len dylib suffix dylib else yield path suffix yield path return inject def dyldoverridesearchname envnone if dyldframeworkpath is set and this dylibname is a framework name use the first file that exists in the framework path if any if there is none go on to search the dyldlibrarypath if any framework frameworkinfoname if framework is not none for path in dyldframeworkpathenv yield os path joinpath framework name if dyldlibrarypath is set then use the first file that exists in the path if none use the original name for path in dyldlibrarypathenv yield os path joinpath os path basenamename def dyldexecutablepathsearchname executablepathnone if we haven t done any searching and found a library and the dylibname starts with executablepath then construct the library name if name startswith executablepath and executablepath is not none yield os path joinexecutablepath namelen executablepath def dylddefaultsearchname envnone yield name framework frameworkinfoname if framework is not none fallbackframeworkpath dyldfallbackframeworkpathenv for path in fallbackframeworkpath yield os path joinpath framework name fallbacklibrarypath dyldfallbacklibrarypathenv for path in fallbacklibrarypath yield os path joinpath os path basenamename if framework is not none and not fallbackframeworkpath for path in defaultframeworkfallback yield os path joinpath framework name if not fallbacklibrarypath for path in defaultlibraryfallback yield os path joinpath os path basenamename def dyldfindname executablepathnone envnone for path in dyldimagesuffixsearchchain dyldoverridesearchname env dyldexecutablepathsearchname executablepath dylddefaultsearchname env env if os path isfilepath return path try if dyldsharedcachecontainspathpath return path except notimplementederror pass raise valueerrordylib s could not be found name def frameworkfindfn executablepathnone envnone error none try return dyldfindfn executablepathexecutablepath envenv except valueerror as e error e fmwkindex fn rfind framework if fmwkindex 1 fmwkindex lenfn fn framework fn os path joinfn os path basenamefn fmwkindex try return dyldfindfn executablepathexecutablepath envenv except valueerror raise error finally error none these are the defaults as per man dyld 1 for a potential path iterator add dyld_image_suffix semantics if dyld_framework_path is set and this dylib_name is a framework name use the first file that exists in the framework path if any if there is none go on to search the dyld_library_path if any if dyld_library_path is set then use the first file that exists in the path if none use the original name if we haven t done any searching and found a library and the dylib_name starts with executable_path then construct the library name find a library or framework using dyld semantics find a framework using dyld semantics in a very loose manner will take input such as python python framework python framework versions current
import os
from ctypes.macholib.framework import framework_info
from ctypes.macholib.dylib import dylib_info
from itertools import *
try:
    from _ctypes import _dyld_shared_cache_contains_path
except ImportError:
    def _dyld_shared_cache_contains_path(*args):
        raise NotImplementedError

__all__ = [
    'dyld_find', 'framework_find',
    'framework_info', 'dylib_info',
]



DEFAULT_FRAMEWORK_FALLBACK = [
    os.path.expanduser("~/Library/Frameworks"),
    "/Library/Frameworks",
    "/Network/Library/Frameworks",
    "/System/Library/Frameworks",
]

DEFAULT_LIBRARY_FALLBACK = [
    os.path.expanduser("~/lib"),
    "/usr/local/lib",
    "/lib",
    "/usr/lib",
]

def dyld_env(env, var):
    if env is None:
        env = os.environ
    rval = env.get(var)
    if rval is None:
        return []
    return rval.split(':')

def dyld_image_suffix(env=None):
    if env is None:
        env = os.environ
    return env.get('DYLD_IMAGE_SUFFIX')

def dyld_framework_path(env=None):
    return dyld_env(env, 'DYLD_FRAMEWORK_PATH')

def dyld_library_path(env=None):
    return dyld_env(env, 'DYLD_LIBRARY_PATH')

def dyld_fallback_framework_path(env=None):
    return dyld_env(env, 'DYLD_FALLBACK_FRAMEWORK_PATH')

def dyld_fallback_library_path(env=None):
    return dyld_env(env, 'DYLD_FALLBACK_LIBRARY_PATH')

def dyld_image_suffix_search(iterator, env=None):
    
    suffix = dyld_image_suffix(env)
    if suffix is None:
        return iterator
    def _inject(iterator=iterator, suffix=suffix):
        for path in iterator:
            if path.endswith('.dylib'):
                yield path[:-len('.dylib')] + suffix + '.dylib'
            else:
                yield path + suffix
            yield path
    return _inject()

def dyld_override_search(name, env=None):
    
    
    
    

    framework = framework_info(name)

    if framework is not None:
        for path in dyld_framework_path(env):
            yield os.path.join(path, framework['name'])

    
    
    for path in dyld_library_path(env):
        yield os.path.join(path, os.path.basename(name))

def dyld_executable_path_search(name, executable_path=None):
    
    
    
    if name.startswith('@executable_path/') and executable_path is not None:
        yield os.path.join(executable_path, name[len('@executable_path/'):])

def dyld_default_search(name, env=None):
    yield name

    framework = framework_info(name)

    if framework is not None:
        fallback_framework_path = dyld_fallback_framework_path(env)
        for path in fallback_framework_path:
            yield os.path.join(path, framework['name'])

    fallback_library_path = dyld_fallback_library_path(env)
    for path in fallback_library_path:
        yield os.path.join(path, os.path.basename(name))

    if framework is not None and not fallback_framework_path:
        for path in DEFAULT_FRAMEWORK_FALLBACK:
            yield os.path.join(path, framework['name'])

    if not fallback_library_path:
        for path in DEFAULT_LIBRARY_FALLBACK:
            yield os.path.join(path, os.path.basename(name))

def dyld_find(name, executable_path=None, env=None):
    
    for path in dyld_image_suffix_search(chain(
                dyld_override_search(name, env),
                dyld_executable_path_search(name, executable_path),
                dyld_default_search(name, env),
            ), env):

        if os.path.isfile(path):
            return path
        try:
            if _dyld_shared_cache_contains_path(path):
                return path
        except NotImplementedError:
            pass

    raise ValueError("dylib %s could not be found" % (name,))

def framework_find(fn, executable_path=None, env=None):
    
    error = None
    try:
        return dyld_find(fn, executable_path=executable_path, env=env)
    except ValueError as e:
        error = e
    fmwk_index = fn.rfind('.framework')
    if fmwk_index == -1:
        fmwk_index = len(fn)
        fn += '.framework'
    fn = os.path.join(fn, os.path.basename(fn[:fmwk_index]))
    try:
        return dyld_find(fn, executable_path=executable_path, env=env)
    except ValueError:
        raise error
    finally:
        error = None