144 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Python
		
	
	
	
"""
 | 
						|
dyld emulation
 | 
						|
"""
 | 
						|
 | 
						|
__all__ = [
 | 
						|
    "dyld_framework",
 | 
						|
    "dyld_library",
 | 
						|
    "dyld_find",
 | 
						|
    "pathForFramework",
 | 
						|
    "infoForFramework",
 | 
						|
]
 | 
						|
 | 
						|
import os
 | 
						|
 | 
						|
from objc._framework import infoForFramework
 | 
						|
from objc._objc import _dyld_shared_cache_contains_path
 | 
						|
 | 
						|
# These are the defaults as per man dyld(1)
 | 
						|
#
 | 
						|
DEFAULT_FRAMEWORK_FALLBACK = ":".join(
 | 
						|
    [
 | 
						|
        os.path.expanduser("~/Library/Frameworks"),
 | 
						|
        "/Library/Frameworks",
 | 
						|
        "/Network/Library/Frameworks",
 | 
						|
        "/System/Library/Frameworks",
 | 
						|
    ]
 | 
						|
)
 | 
						|
 | 
						|
DEFAULT_LIBRARY_FALLBACK = ":".join(
 | 
						|
    [os.path.expanduser("~/lib"), "/usr/local/lib", "/lib", "/usr/lib"]
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
def ensure_unicode(s):
 | 
						|
    """Not all of PyObjC understands unicode paths very well yet"""
 | 
						|
    if isinstance(s, bytes):
 | 
						|
        return s.decode("utf-8")
 | 
						|
    return s
 | 
						|
 | 
						|
 | 
						|
def inject_suffixes(iterator):
 | 
						|
    suffix = ensure_unicode(os.environ.get("DYLD_IMAGE_SUFFIX", None))
 | 
						|
    if suffix is None:
 | 
						|
        return iterator
 | 
						|
 | 
						|
    def _inject(iterator=iterator, suffix=suffix):
 | 
						|
        for path in iterator:
 | 
						|
            if path.endswith(".dylib"):
 | 
						|
                yield path[:-6] + suffix + ".dylib"
 | 
						|
            else:
 | 
						|
                yield path + suffix
 | 
						|
            yield path
 | 
						|
 | 
						|
    return _inject()
 | 
						|
 | 
						|
 | 
						|
def dyld_framework(filename, framework_name, version=None):
 | 
						|
    """Find a framework using dyld semantics"""
 | 
						|
    filename = ensure_unicode(filename)
 | 
						|
    framework_name = ensure_unicode(framework_name)
 | 
						|
    version = ensure_unicode(version)
 | 
						|
 | 
						|
    def _search():
 | 
						|
        spath = ensure_unicode(os.environ.get("DYLD_FRAMEWORK_PATH", None))
 | 
						|
        if spath is not None:
 | 
						|
            for path in spath.split(":"):
 | 
						|
                if version:
 | 
						|
                    yield os.path.join(
 | 
						|
                        path,
 | 
						|
                        framework_name + ".framework",
 | 
						|
                        "Versions",
 | 
						|
                        version,
 | 
						|
                        framework_name,
 | 
						|
                    )
 | 
						|
                else:
 | 
						|
                    yield os.path.join(
 | 
						|
                        path, framework_name + ".framework", framework_name
 | 
						|
                    )
 | 
						|
        yield filename
 | 
						|
        spath = ensure_unicode(
 | 
						|
            os.environ.get("DYLD_FALLBACK_FRAMEWORK_PATH", DEFAULT_FRAMEWORK_FALLBACK)
 | 
						|
        )
 | 
						|
        for path in spath.split(":"):
 | 
						|
            if version:
 | 
						|
                yield os.path.join(
 | 
						|
                    path,
 | 
						|
                    framework_name + ".framework",
 | 
						|
                    "Versions",
 | 
						|
                    version,
 | 
						|
                    framework_name,
 | 
						|
                )
 | 
						|
            else:
 | 
						|
                yield os.path.join(path, framework_name + ".framework", framework_name)
 | 
						|
 | 
						|
    for f in inject_suffixes(_search()):
 | 
						|
        if _dyld_shared_cache_contains_path(f):
 | 
						|
            return f
 | 
						|
 | 
						|
        if os.path.exists(f):
 | 
						|
            return f
 | 
						|
    # raise ..
 | 
						|
    raise ImportError(f"Framework {framework_name} could not be found")
 | 
						|
 | 
						|
 | 
						|
def dyld_library(filename, libname):
 | 
						|
    """Find a dylib using dyld semantics"""
 | 
						|
    filename = ensure_unicode(filename)
 | 
						|
    libname = ensure_unicode(libname)
 | 
						|
 | 
						|
    def _search():
 | 
						|
        spath = ensure_unicode(os.environ.get("DYLD_LIBRARY_PATH", None))
 | 
						|
        if spath is not None:
 | 
						|
            for path in spath.split(":"):
 | 
						|
                yield os.path.join(path, libname)
 | 
						|
        yield filename
 | 
						|
        spath = ensure_unicode(
 | 
						|
            os.environ.get("DYLD_FALLBACK_LIBRARY_PATH", DEFAULT_LIBRARY_FALLBACK)
 | 
						|
        )
 | 
						|
        for path in spath.split(":"):
 | 
						|
            yield os.path.join(path, libname)
 | 
						|
 | 
						|
    for f in inject_suffixes(_search()):
 | 
						|
        if _dyld_shared_cache_contains_path(f):
 | 
						|
            return f
 | 
						|
        if os.path.exists(f):
 | 
						|
            return f
 | 
						|
    raise ValueError(f"dylib {filename} could not be found")
 | 
						|
 | 
						|
 | 
						|
def dyld_find(filename):
 | 
						|
    """Generic way to locate a dyld framework or dyld"""
 | 
						|
    filename = os.path.realpath(filename)
 | 
						|
    res = infoForFramework(filename)
 | 
						|
    if res:
 | 
						|
        framework_loc, framework_name, version = res
 | 
						|
        return dyld_framework(filename, framework_name, version)
 | 
						|
    else:
 | 
						|
        return dyld_library(filename, os.path.basename(filename))
 | 
						|
 | 
						|
 | 
						|
def pathForFramework(path):
 | 
						|
    fpath, name, version = infoForFramework(dyld_find(path))
 | 
						|
    return os.path.join(fpath, name + ".framework")
 |