util.py revision 1b7f891f416830d0c46ca1c9e1bfe62f05cda655
1477c8d5e70240744d24631b18341ad892c8a8e1cThomas Woutersimport sys, os
2477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
3477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters# find_library(name) returns the pathname of a library, or None.
4477c8d5e70240744d24631b18341ad892c8a8e1cThomas Woutersif os.name == "nt":
5477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    def find_library(name):
6477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        # See MSDN for the REAL search order.
7477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        for directory in os.environ['PATH'].split(os.pathsep):
8477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters            fname = os.path.join(directory, name)
9477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters            if os.path.exists(fname):
10477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters                return fname
11477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters            if fname.lower().endswith(".dll"):
12477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters                continue
13477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters            fname = fname + ".dll"
14477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters            if os.path.exists(fname):
15477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters                return fname
16477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        return None
17477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
18477c8d5e70240744d24631b18341ad892c8a8e1cThomas Woutersif os.name == "ce":
19477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    # search path according to MSDN:
20477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    # - absolute path specified by filename
21477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    # - The .exe launch directory
22477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    # - the Windows directory
23477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    # - ROM dll files (where are they?)
24477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    # - OEM specified search path: HKLM\Loader\SystemPath
25477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    def find_library(name):
26477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        return name
27477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
28477c8d5e70240744d24631b18341ad892c8a8e1cThomas Woutersif os.name == "posix" and sys.platform == "darwin":
29477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    from ctypes.macholib.dyld import dyld_find as _dyld_find
30477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    def find_library(name):
31477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        possible = ['lib%s.dylib' % name,
32477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters                    '%s.dylib' % name,
33477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters                    '%s.framework/%s' % (name, name)]
34477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        for name in possible:
35477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters            try:
36477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters                return _dyld_find(name)
37477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters            except ValueError:
38477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters                continue
39477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        return None
40477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
41477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouterselif os.name == "posix":
42477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
430e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters    import re, tempfile, errno
44477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
45477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    def _findLib_gcc(name):
46fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)
470e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters        fdout, ccout = tempfile.mkstemp()
480e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters        os.close(fdout)
49fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        cmd = 'if type gcc >/dev/null 2>&1; then CC=gcc; else CC=cc; fi;' \
500e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters              '$CC -Wl,-t -o ' + ccout + ' 2>&1 -l' + name
51477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        try:
52fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            f = os.popen(cmd)
53fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            trace = f.read()
54fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            f.close()
55477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        finally:
56477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters            try:
570e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters                os.unlink(ccout)
58b940e113bf90ff71b0ef57414ea2beea9d2a4bc0Guido van Rossum            except OSError as e:
590e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters                if e.errno != errno.ENOENT:
600e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters                    raise
61477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        res = re.search(expr, trace)
62477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        if not res:
63477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters            return None
64477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        return res.group(0)
65477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
661b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters
671b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters    if sys.platform == "sunos5":
681b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters        # use /usr/ccs/bin/dump on solaris
691b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters        def _get_soname(f):
701b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters            if not f:
711b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters                return None
721b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters            cmd = "/usr/ccs/bin/dump -Lpv 2>/dev/null " + f
731b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters            res = re.search(r'\[.*\]\sSONAME\s+([^\s]+)', os.popen(cmd).read())
741b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters            if not res:
751b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters                return None
761b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters            return res.group(1)
771b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters    else:
781b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters        def _get_soname(f):
791b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters            # assuming GNU binutils / ELF
801b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters            if not f:
811b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters                return None
821b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters            cmd = "objdump -p -j .dynamic 2>/dev/null " + f
831b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters            res = re.search(r'\sSONAME\s+([^\s]+)', os.popen(cmd).read())
841b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters            if not res:
851b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters                return None
861b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters            return res.group(1)
87477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
88fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if (sys.platform.startswith("freebsd")
89fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        or sys.platform.startswith("openbsd")
90fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        or sys.platform.startswith("dragonfly")):
91fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
92fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        def _num_version(libname):
93fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ]
94fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            parts = libname.split(".")
95fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            nums = []
96fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            try:
97fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                while parts:
98fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                    nums.insert(0, int(parts.pop()))
99fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            except ValueError:
100fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                pass
101fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            return nums or [ sys.maxint ]
102fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
103fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        def find_library(name):
104fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            ename = re.escape(name)
105fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            expr = r':-l%s\.\S+ => \S*/(lib%s\.\S+)' % (ename, ename)
106fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            res = re.findall(expr,
107fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                             os.popen('/sbin/ldconfig -r 2>/dev/null').read())
108fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            if not res:
109fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                return _get_soname(_findLib_gcc(name))
110fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            res.sort(cmp= lambda x,y: cmp(_num_version(x), _num_version(y)))
111fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            return res[-1]
112fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
113fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    else:
114fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
115fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        def _findLib_ldconfig(name):
116fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            # XXX assuming GLIBC's ldconfig (with option -p)
117fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            expr = r'/[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)
118fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            res = re.search(expr,
119fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                            os.popen('/sbin/ldconfig -p 2>/dev/null').read())
120fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            if not res:
121fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                # Hm, this works only for libs needed by the python executable.
122fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                cmd = 'ldd %s 2>/dev/null' % sys.executable
123fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                res = re.search(expr, os.popen(cmd).read())
124fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                if not res:
125fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                    return None
126fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            return res.group(0)
127fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
128fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        def find_library(name):
129fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            return _get_soname(_findLib_ldconfig(name) or _findLib_gcc(name))
130477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
131477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters################################################################
132477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters# test code
133477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
134477c8d5e70240744d24631b18341ad892c8a8e1cThomas Woutersdef test():
135477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    from ctypes import cdll
136477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    if os.name == "nt":
137be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum        print(cdll.msvcrt)
138be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum        print(cdll.load("msvcrt"))
139be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum        print(find_library("msvcrt"))
140477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
141477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    if os.name == "posix":
142477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        # find and load_version
143be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum        print(find_library("m"))
144be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum        print(find_library("c"))
145be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum        print(find_library("bz2"))
146477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
147477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        # getattr
148477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters##        print cdll.m
149477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters##        print cdll.bz2
150477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
151477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        # load
152477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        if sys.platform == "darwin":
153be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum            print(cdll.LoadLibrary("libm.dylib"))
154be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum            print(cdll.LoadLibrary("libcrypto.dylib"))
155be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum            print(cdll.LoadLibrary("libSystem.dylib"))
156be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum            print(cdll.LoadLibrary("System.framework/System"))
157477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters        else:
158be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum            print(cdll.LoadLibrary("libm.so"))
159be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum            print(cdll.LoadLibrary("libcrypt.so"))
160be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum            print(find_library("crypt"))
161477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters
162477c8d5e70240744d24631b18341ad892c8a8e1cThomas Woutersif __name__ == "__main__":
163477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters    test()
164