1""" 2dyld emulation 3""" 4 5__all__ = [ 6 'dyld_framework', 'dyld_library', 'dyld_find', 'pathForFramework', 7 'infoForFramework', 8] 9 10import os, sys 11from _framework import infoForFramework 12 13 14# These are the defaults as per man dyld(1) 15# 16DEFAULT_FRAMEWORK_FALLBACK = u':'.join([ 17 os.path.expanduser(u"~/Library/Frameworks"), 18 u"/Library/Frameworks", 19 u"/Network/Library/Frameworks", 20 u"/System/Library/Frameworks", 21]) 22 23DEFAULT_LIBRARY_FALLBACK = u':'.join([ 24 os.path.expanduser(u"~/lib"), 25 u"/usr/local/lib", 26 u"/lib", 27 u"/usr/lib", 28]) 29 30def ensure_unicode(s): 31 """Not all of PyObjC understands unicode paths very well yet""" 32 if isinstance(s, str): 33 return unicode(s, 'utf8') 34 return s 35 36def injectSuffixes(iterator): 37 suffix = ensure_unicode(os.environ.get('DYLD_IMAGE_SUFFIX', None)) 38 if suffix is None: 39 return iterator 40 def _inject(iterator=iterator,suffix=suffix): 41 for path in iterator: 42 if path.endswith(u'.dylib'): 43 yield path[:-6] + suffix + u'.dylib' 44 else: 45 yield path + suffix 46 yield path 47 return _inject() 48 49def dyld_framework(filename, framework_name, version=None): 50 """Find a framework using dyld semantics""" 51 filename = ensure_unicode(filename) 52 framework_name = ensure_unicode(framework_name) 53 version = ensure_unicode(version) 54 55 def _search(): 56 spath = ensure_unicode(os.environ.get('DYLD_FRAMEWORK_PATH', None)) 57 if spath is not None: 58 for path in spath.split(u':'): 59 if version: 60 yield os.path.join( 61 path, framework_name + u'.framework', 62 u'Versions', version, framework_name 63 ) 64 else: 65 yield os.path.join( 66 path, framework_name + u'.framework', framework_name 67 ) 68 yield filename 69 spath = ensure_unicode(os.environ.get( 70 'DYLD_FALLBACK_FRAMEWORK_PATH', DEFAULT_FRAMEWORK_FALLBACK 71 )) 72 for path in spath.split(u':'): 73 if version: 74 yield os.path.join( 75 path, framework_name + u'.framework', u'Versions', 76 version, framework_name 77 ) 78 else: 79 yield os.path.join( 80 path, framework_name + u'.framework', framework_name 81 ) 82 83 84 for f in injectSuffixes(_search()): 85 if os.path.exists(f): 86 return f 87 # raise .. 88 raise ImportError("Framework %s could not be found" % (framework_name,)) 89 90def dyld_library(filename, libname): 91 """Find a dylib using dyld semantics""" 92 filename = ensure_unicode(filename) 93 libname = ensure_unicode(libname) 94 def _search(): 95 spath = ensure_unicode(os.environ.get('DYLD_LIBRARY_PATH', None)) 96 if spath is not None: 97 for path in spath.split(u':'): 98 yield os.path.join(path, libname) 99 yield filename 100 spath = ensure_unicode(os.environ.get( 101 'DYLD_FALLBACK_LIBRARY_PATH', DEFAULT_LIBRARY_FALLBACK 102 )) 103 for path in spath.split(u':'): 104 yield os.path.join(path, libname) 105 for f in injectSuffixes(_search()): 106 if os.path.exists(f): 107 return f 108 raise ValueError, "dylib %s could not be found" % (filename,) 109 110# Python version upto (at least) 2.5 do not propertly convert unicode 111# arguments to os.readlink, the code below works around that. 112if sys.version_info[:3] >= (2,6,0): 113 _realpath = os.path.realpath 114 115else: 116 def _realpath(path): 117 """ 118 Unicode-safe version of os.path.realpath. 119 """ 120 if isinstance(path, unicode): 121 fsenc = sys.getfilesystemencoding() 122 return os.path.realpath(path.encode(fsenc)).decode(fsenc) 123 124 return os.path.realpath(path) 125 126 127def dyld_find(filename): 128 """Generic way to locate a dyld framework or dyld""" 129 # if they passed in a framework directory, not a mach-o file 130 # then go ahead and look where one would expect to find the mach-o 131# filename = ensure_unicode(filename) 132# if os.path.isdir(filename): 133# filename = os.path.join( 134# filename, 135# os.path.basename(filename)[:-len(os.path.splitext(filename)[-1])] 136# ) 137 filename = _realpath(filename) 138 res = infoForFramework(filename) 139 if res: 140 framework_loc, framework_name, version = res 141 return dyld_framework(filename, framework_name, version) 142 else: 143 return dyld_library(filename, os.path.basename(filename)) 144 145def pathForFramework(path): 146 fpath, name, version = infoForFramework(dyld_find(path)) 147 return os.path.join(fpath, name + u'.framework') 148