PageRenderTime 285ms CodeModel.GetById 110ms app.highlight 84ms RepoModel.GetById 88ms app.codeStats 0ms

/Lib/ctypes/util.py

http://unladen-swallow.googlecode.com/
Python | 241 lines | 180 code | 25 blank | 36 comment | 52 complexity | 0bab2412b6e9c7da8d6330397759f92c MD5 | raw file
  1######################################################################
  2#  This file should be kept compatible with Python 2.3, see PEP 291. #
  3######################################################################
  4import sys, os
  5
  6# find_library(name) returns the pathname of a library, or None.
  7if os.name == "nt":
  8
  9    def _get_build_version():
 10        """Return the version of MSVC that was used to build Python.
 11
 12        For Python 2.3 and up, the version number is included in
 13        sys.version.  For earlier versions, assume the compiler is MSVC 6.
 14        """
 15        # This function was copied from Lib/distutils/msvccompiler.py
 16        prefix = "MSC v."
 17        i = sys.version.find(prefix)
 18        if i == -1:
 19            return 6
 20        i = i + len(prefix)
 21        s, rest = sys.version[i:].split(" ", 1)
 22        majorVersion = int(s[:-2]) - 6
 23        minorVersion = int(s[2:3]) / 10.0
 24        # I don't think paths are affected by minor version in version 6
 25        if majorVersion == 6:
 26            minorVersion = 0
 27        if majorVersion >= 6:
 28            return majorVersion + minorVersion
 29        # else we don't know what version of the compiler this is
 30        return None
 31
 32    def find_msvcrt():
 33        """Return the name of the VC runtime dll"""
 34        version = _get_build_version()
 35        if version is None:
 36            # better be safe than sorry
 37            return None
 38        if version <= 6:
 39            clibname = 'msvcrt'
 40        else:
 41            clibname = 'msvcr%d' % (version * 10)
 42
 43        # If python was built with in debug mode
 44        import imp
 45        if imp.get_suffixes()[0][0] == '_d.pyd':
 46            clibname += 'd'
 47        return clibname+'.dll'
 48
 49    def find_library(name):
 50        if name in ('c', 'm'):
 51            return find_msvcrt()
 52        # See MSDN for the REAL search order.
 53        for directory in os.environ['PATH'].split(os.pathsep):
 54            fname = os.path.join(directory, name)
 55            if os.path.isfile(fname):
 56                return fname
 57            if fname.lower().endswith(".dll"):
 58                continue
 59            fname = fname + ".dll"
 60            if os.path.isfile(fname):
 61                return fname
 62        return None
 63
 64if os.name == "ce":
 65    # search path according to MSDN:
 66    # - absolute path specified by filename
 67    # - The .exe launch directory
 68    # - the Windows directory
 69    # - ROM dll files (where are they?)
 70    # - OEM specified search path: HKLM\Loader\SystemPath
 71    def find_library(name):
 72        return name
 73
 74if os.name == "posix" and sys.platform == "darwin":
 75    from ctypes.macholib.dyld import dyld_find as _dyld_find
 76    def find_library(name):
 77        possible = ['lib%s.dylib' % name,
 78                    '%s.dylib' % name,
 79                    '%s.framework/%s' % (name, name)]
 80        for name in possible:
 81            try:
 82                return _dyld_find(name)
 83            except ValueError:
 84                continue
 85        return None
 86
 87elif os.name == "posix":
 88    # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
 89    import re, tempfile, errno
 90
 91    def _findLib_gcc(name):
 92        expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)
 93        fdout, ccout = tempfile.mkstemp()
 94        os.close(fdout)
 95        cmd = 'if type gcc >/dev/null 2>&1; then CC=gcc; elif type cc >/dev/null 2>&1; then CC=cc;else exit 10; fi;' \
 96              '$CC -Wl,-t -o ' + ccout + ' 2>&1 -l' + name
 97        try:
 98            f = os.popen(cmd)
 99            trace = f.read()
100            rv = f.close()
101        finally:
102            try:
103                os.unlink(ccout)
104            except OSError, e:
105                if e.errno != errno.ENOENT:
106                    raise
107        if rv == 10:
108            raise OSError, 'gcc or cc command not found'
109        res = re.search(expr, trace)
110        if not res:
111            return None
112        return res.group(0)
113
114
115    if sys.platform == "sunos5":
116        # use /usr/ccs/bin/dump on solaris
117        def _get_soname(f):
118            if not f:
119                return None
120            cmd = "/usr/ccs/bin/dump -Lpv 2>/dev/null " + f
121            res = re.search(r'\[.*\]\sSONAME\s+([^\s]+)', os.popen(cmd).read())
122            if not res:
123                return None
124            return res.group(1)
125    else:
126        def _get_soname(f):
127            # assuming GNU binutils / ELF
128            if not f:
129                return None
130            cmd = 'if ! type objdump >/dev/null 2>&1; then exit 10; fi;' \
131                  "objdump -p -j .dynamic 2>/dev/null " + f
132            f = os.popen(cmd)
133            dump = f.read()
134            rv = f.close()
135            if rv == 10:
136                raise OSError, 'objdump command not found'
137            res = re.search(r'\sSONAME\s+([^\s]+)', os.popen(cmd).read())
138            if not res:
139                return None
140            return res.group(1)
141
142    if (sys.platform.startswith("freebsd")
143        or sys.platform.startswith("openbsd")
144        or sys.platform.startswith("dragonfly")):
145
146        def _num_version(libname):
147            # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ]
148            parts = libname.split(".")
149            nums = []
150            try:
151                while parts:
152                    nums.insert(0, int(parts.pop()))
153            except ValueError:
154                pass
155            return nums or [ sys.maxint ]
156
157        def find_library(name):
158            ename = re.escape(name)
159            expr = r':-l%s\.\S+ => \S*/(lib%s\.\S+)' % (ename, ename)
160            res = re.findall(expr,
161                             os.popen('/sbin/ldconfig -r 2>/dev/null').read())
162            if not res:
163                return _get_soname(_findLib_gcc(name))
164            res.sort(cmp= lambda x,y: cmp(_num_version(x), _num_version(y)))
165            return res[-1]
166
167    else:
168
169        def _findLib_ldconfig(name):
170            # XXX assuming GLIBC's ldconfig (with option -p)
171            expr = r'/[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)
172            res = re.search(expr,
173                            os.popen('/sbin/ldconfig -p 2>/dev/null').read())
174            if not res:
175                # Hm, this works only for libs needed by the python executable.
176                cmd = 'ldd %s 2>/dev/null' % sys.executable
177                res = re.search(expr, os.popen(cmd).read())
178                if not res:
179                    return None
180            return res.group(0)
181
182        def _findSoname_ldconfig(name):
183            import struct
184            if struct.calcsize('l') == 4:
185                machine = os.uname()[4] + '-32'
186            else:
187                machine = os.uname()[4] + '-64'
188            mach_map = {
189                'x86_64-64': 'libc6,x86-64',
190                'ppc64-64': 'libc6,64bit',
191                'sparc64-64': 'libc6,64bit',
192                's390x-64': 'libc6,64bit',
193                'ia64-64': 'libc6,IA-64',
194                }
195            abi_type = mach_map.get(machine, 'libc6')
196
197            # XXX assuming GLIBC's ldconfig (with option -p)
198            expr = r'(\S+)\s+\((%s(?:, OS ABI:[^\)]*)?)\)[^/]*(/[^\(\)\s]*lib%s\.[^\(\)\s]*)' \
199                   % (abi_type, re.escape(name))
200            res = re.search(expr,
201                            os.popen('/sbin/ldconfig -p 2>/dev/null').read())
202            if not res:
203                return None
204            return res.group(1)
205
206        def find_library(name):
207            return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name))
208
209################################################################
210# test code
211
212def test():
213    from ctypes import cdll
214    if os.name == "nt":
215        print cdll.msvcrt
216        print cdll.load("msvcrt")
217        print find_library("msvcrt")
218
219    if os.name == "posix":
220        # find and load_version
221        print find_library("m")
222        print find_library("c")
223        print find_library("bz2")
224
225        # getattr
226##        print cdll.m
227##        print cdll.bz2
228
229        # load
230        if sys.platform == "darwin":
231            print cdll.LoadLibrary("libm.dylib")
232            print cdll.LoadLibrary("libcrypto.dylib")
233            print cdll.LoadLibrary("libSystem.dylib")
234            print cdll.LoadLibrary("System.framework/System")
235        else:
236            print cdll.LoadLibrary("libm.so")
237            print cdll.LoadLibrary("libcrypt.so")
238            print find_library("crypt")
239
240if __name__ == "__main__":
241    test()