Manual py3k backport: [svn r74155] Issue #6242: Fix deallocator of io.StringIO and...
[python.git] / Lib / ctypes / util.py
blob8f6e3384db1c72317f6590ba52fb019b057693d5
1 ######################################################################
2 # This file should be kept compatible with Python 2.3, see PEP 291. #
3 ######################################################################
4 import sys, os
6 # find_library(name) returns the pathname of a library, or None.
7 if os.name == "nt":
9 def _get_build_version():
10 """Return the version of MSVC that was used to build Python.
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
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)
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'
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
64 if 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
74 if 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
87 elif os.name == "posix":
88 # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
89 import re, tempfile, errno
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 try:
100 trace = f.read()
101 finally:
102 rv = f.close()
103 finally:
104 try:
105 os.unlink(ccout)
106 except OSError, e:
107 if e.errno != errno.ENOENT:
108 raise
109 if rv == 10:
110 raise OSError, 'gcc or cc command not found'
111 res = re.search(expr, trace)
112 if not res:
113 return None
114 return res.group(0)
117 if sys.platform == "sunos5":
118 # use /usr/ccs/bin/dump on solaris
119 def _get_soname(f):
120 if not f:
121 return None
122 cmd = "/usr/ccs/bin/dump -Lpv 2>/dev/null " + f
123 f = os.popen(cmd)
124 try:
125 data = f.read()
126 finally:
127 f.close()
128 res = re.search(r'\[.*\]\sSONAME\s+([^\s]+)', data)
129 if not res:
130 return None
131 return res.group(1)
132 else:
133 def _get_soname(f):
134 # assuming GNU binutils / ELF
135 if not f:
136 return None
137 cmd = 'if ! type objdump >/dev/null 2>&1; then exit 10; fi;' \
138 "objdump -p -j .dynamic 2>/dev/null " + f
139 f = os.popen(cmd)
140 dump = f.read()
141 rv = f.close()
142 if rv == 10:
143 raise OSError, 'objdump command not found'
144 f = os.popen(cmd)
145 try:
146 data = f.read()
147 finally:
148 f.close()
149 res = re.search(r'\sSONAME\s+([^\s]+)', data)
150 if not res:
151 return None
152 return res.group(1)
154 if (sys.platform.startswith("freebsd")
155 or sys.platform.startswith("openbsd")
156 or sys.platform.startswith("dragonfly")):
158 def _num_version(libname):
159 # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ]
160 parts = libname.split(".")
161 nums = []
162 try:
163 while parts:
164 nums.insert(0, int(parts.pop()))
165 except ValueError:
166 pass
167 return nums or [ sys.maxint ]
169 def find_library(name):
170 ename = re.escape(name)
171 expr = r':-l%s\.\S+ => \S*/(lib%s\.\S+)' % (ename, ename)
172 f = os.popen('/sbin/ldconfig -r 2>/dev/null')
173 try:
174 data = f.read()
175 finally:
176 f.close()
177 res = re.findall(expr, data)
178 if not res:
179 return _get_soname(_findLib_gcc(name))
180 res.sort(cmp= lambda x,y: cmp(_num_version(x), _num_version(y)))
181 return res[-1]
183 else:
185 def _findLib_ldconfig(name):
186 # XXX assuming GLIBC's ldconfig (with option -p)
187 expr = r'/[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)
188 f = os.popen('/sbin/ldconfig -p 2>/dev/null')
189 try:
190 data = f.read()
191 finally:
192 f.close()
193 res = re.search(expr, data)
194 if not res:
195 # Hm, this works only for libs needed by the python executable.
196 cmd = 'ldd %s 2>/dev/null' % sys.executable
197 f = os.popen(cmd)
198 try:
199 data = f.read()
200 finally:
201 f.close()
202 res = re.search(expr, data)
203 if not res:
204 return None
205 return res.group(0)
207 def _findSoname_ldconfig(name):
208 import struct
209 if struct.calcsize('l') == 4:
210 machine = os.uname()[4] + '-32'
211 else:
212 machine = os.uname()[4] + '-64'
213 mach_map = {
214 'x86_64-64': 'libc6,x86-64',
215 'ppc64-64': 'libc6,64bit',
216 'sparc64-64': 'libc6,64bit',
217 's390x-64': 'libc6,64bit',
218 'ia64-64': 'libc6,IA-64',
220 abi_type = mach_map.get(machine, 'libc6')
222 # XXX assuming GLIBC's ldconfig (with option -p)
223 expr = r'(\S+)\s+\((%s(?:, OS ABI:[^\)]*)?)\)[^/]*(/[^\(\)\s]*lib%s\.[^\(\)\s]*)' \
224 % (abi_type, re.escape(name))
225 f = os.popen('/sbin/ldconfig -p 2>/dev/null')
226 try:
227 data = f.read()
228 finally:
229 f.close()
230 res = re.search(expr, data)
231 if not res:
232 return None
233 return res.group(1)
235 def find_library(name):
236 return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name))
238 ################################################################
239 # test code
241 def test():
242 from ctypes import cdll
243 if os.name == "nt":
244 print cdll.msvcrt
245 print cdll.load("msvcrt")
246 print find_library("msvcrt")
248 if os.name == "posix":
249 # find and load_version
250 print find_library("m")
251 print find_library("c")
252 print find_library("bz2")
254 # getattr
255 ## print cdll.m
256 ## print cdll.bz2
258 # load
259 if sys.platform == "darwin":
260 print cdll.LoadLibrary("libm.dylib")
261 print cdll.LoadLibrary("libcrypto.dylib")
262 print cdll.LoadLibrary("libSystem.dylib")
263 print cdll.LoadLibrary("System.framework/System")
264 else:
265 print cdll.LoadLibrary("libm.so")
266 print cdll.LoadLibrary("libcrypt.so")
267 print find_library("crypt")
269 if __name__ == "__main__":
270 test()