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