blob: b120273fe9e37e5a1dddee7aa96777946b96e65d [file] [log] [blame]
Steve Dowerfd3664b2015-05-23 09:02:50 -07001"""distutils._msvccompiler
2
3Contains MSVCCompiler, an implementation of the abstract CCompiler class
4for Microsoft Visual Studio 2015.
5
6The module is compatible with VS 2015 and later. You can find legacy support
7for older versions in distutils.msvc9compiler and distutils.msvccompiler.
8"""
9
10# Written by Perry Stoll
11# hacked by Robin Becker and Thomas Heller to do a better job of
12# finding DevStudio (through the registry)
13# ported to VS 2005 and VS 2008 by Christian Heimes
14# ported to VS 2015 by Steve Dower
15
16import os
Steve Dowerfcbe1df2015-09-08 21:39:01 -070017import shutil
18import stat
Steve Dowerfd3664b2015-05-23 09:02:50 -070019import subprocess
Steve Dowerfd3664b2015-05-23 09:02:50 -070020
21from distutils.errors import DistutilsExecError, DistutilsPlatformError, \
22 CompileError, LibError, LinkError
23from distutils.ccompiler import CCompiler, gen_lib_options
24from distutils import log
25from distutils.util import get_platform
26
27import winreg
28from itertools import count
29
Steve Dowerfcbe1df2015-09-08 21:39:01 -070030def _find_vcvarsall(plat_spec):
Steve Dowerf0ccf022015-10-05 10:35:00 -070031 try:
32 key = winreg.OpenKeyEx(
33 winreg.HKEY_LOCAL_MACHINE,
34 r"Software\Microsoft\VisualStudio\SxS\VC7",
35 access=winreg.KEY_READ | winreg.KEY_WOW64_32KEY
36 )
37 except OSError:
38 log.debug("Visual C++ is not registered")
39 return None, None
Steve Dowerfd3664b2015-05-23 09:02:50 -070040
Steve Dowerf0ccf022015-10-05 10:35:00 -070041 with key:
Steve Dowerfd3664b2015-05-23 09:02:50 -070042 best_version = 0
43 best_dir = None
44 for i in count():
45 try:
46 v, vc_dir, vt = winreg.EnumValue(key, i)
47 except OSError:
48 break
49 if v and vt == winreg.REG_SZ and os.path.isdir(vc_dir):
50 try:
51 version = int(float(v))
52 except (ValueError, TypeError):
53 continue
54 if version >= 14 and version > best_version:
55 best_version, best_dir = version, vc_dir
56 if not best_version:
57 log.debug("No suitable Visual C++ version found")
Steve Dowerfcbe1df2015-09-08 21:39:01 -070058 return None, None
Steve Dowerfd3664b2015-05-23 09:02:50 -070059
60 vcvarsall = os.path.join(best_dir, "vcvarsall.bat")
61 if not os.path.isfile(vcvarsall):
62 log.debug("%s cannot be found", vcvarsall)
Steve Dowerfcbe1df2015-09-08 21:39:01 -070063 return None, None
Steve Dowerfd3664b2015-05-23 09:02:50 -070064
Steve Dowerfcbe1df2015-09-08 21:39:01 -070065 vcruntime = None
66 vcruntime_spec = _VCVARS_PLAT_TO_VCRUNTIME_REDIST.get(plat_spec)
67 if vcruntime_spec:
68 vcruntime = os.path.join(best_dir,
69 vcruntime_spec.format(best_version))
70 if not os.path.isfile(vcruntime):
71 log.debug("%s cannot be found", vcruntime)
72 vcruntime = None
73
74 return vcvarsall, vcruntime
Steve Dowerfd3664b2015-05-23 09:02:50 -070075
76def _get_vc_env(plat_spec):
77 if os.getenv("DISTUTILS_USE_SDK"):
78 return {
79 key.lower(): value
80 for key, value in os.environ.items()
81 }
82
Steve Dowerfcbe1df2015-09-08 21:39:01 -070083 vcvarsall, vcruntime = _find_vcvarsall(plat_spec)
Steve Dowerfd3664b2015-05-23 09:02:50 -070084 if not vcvarsall:
85 raise DistutilsPlatformError("Unable to find vcvarsall.bat")
86
87 try:
88 out = subprocess.check_output(
Steve Dower08bb8a42016-06-17 09:32:38 -070089 'cmd /u /c "{}" {} && set'.format(vcvarsall, plat_spec),
Steve Dowerfd3664b2015-05-23 09:02:50 -070090 stderr=subprocess.STDOUT,
Steve Dower08bb8a42016-06-17 09:32:38 -070091 ).decode('utf-16le', errors='replace')
Steve Dowerfd3664b2015-05-23 09:02:50 -070092 except subprocess.CalledProcessError as exc:
93 log.error(exc.output)
94 raise DistutilsPlatformError("Error executing {}"
95 .format(exc.cmd))
96
Steve Dowerfcbe1df2015-09-08 21:39:01 -070097 env = {
Steve Dowerfd3664b2015-05-23 09:02:50 -070098 key.lower(): value
99 for key, _, value in
100 (line.partition('=') for line in out.splitlines())
101 if key and value
102 }
Larry Hastings52e40cd2015-09-09 06:54:57 -0700103
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700104 if vcruntime:
105 env['py_vcruntime_redist'] = vcruntime
106 return env
Steve Dowerfd3664b2015-05-23 09:02:50 -0700107
108def _find_exe(exe, paths=None):
109 """Return path to an MSVC executable program.
110
111 Tries to find the program in several places: first, one of the
112 MSVC program search paths from the registry; next, the directories
113 in the PATH environment variable. If any of those work, return an
114 absolute path that is known to exist. If none of them work, just
115 return the original program name, 'exe'.
116 """
117 if not paths:
118 paths = os.getenv('path').split(os.pathsep)
119 for p in paths:
120 fn = os.path.join(os.path.abspath(p), exe)
121 if os.path.isfile(fn):
122 return fn
123 return exe
124
125# A map keyed by get_platform() return values to values accepted by
Steve Dower1d329412016-01-16 12:39:10 -0800126# 'vcvarsall.bat'. Always cross-compile from x86 to work with the
127# lighter-weight MSVC installs that do not include native 64-bit tools.
Steve Dowerfd3664b2015-05-23 09:02:50 -0700128PLAT_TO_VCVARS = {
129 'win32' : 'x86',
Steve Dower1d329412016-01-16 12:39:10 -0800130 'win-amd64' : 'x86_amd64',
Steve Dowerfd3664b2015-05-23 09:02:50 -0700131}
132
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700133# A map keyed by get_platform() return values to the file under
134# the VC install directory containing the vcruntime redistributable.
135_VCVARS_PLAT_TO_VCRUNTIME_REDIST = {
136 'x86' : 'redist\\x86\\Microsoft.VC{0}0.CRT\\vcruntime{0}0.dll',
137 'amd64' : 'redist\\x64\\Microsoft.VC{0}0.CRT\\vcruntime{0}0.dll',
138 'x86_amd64' : 'redist\\x64\\Microsoft.VC{0}0.CRT\\vcruntime{0}0.dll',
139}
140
141# A set containing the DLLs that are guaranteed to be available for
142# all micro versions of this Python version. Known extension
143# dependencies that are not in this set will be copied to the output
144# path.
145_BUNDLED_DLLS = frozenset(['vcruntime140.dll'])
146
Steve Dowerfd3664b2015-05-23 09:02:50 -0700147class MSVCCompiler(CCompiler) :
148 """Concrete class that implements an interface to Microsoft Visual C++,
149 as defined by the CCompiler abstract class."""
150
151 compiler_type = 'msvc'
152
153 # Just set this so CCompiler's constructor doesn't barf. We currently
154 # don't use the 'set_executables()' bureaucracy provided by CCompiler,
155 # as it really isn't necessary for this sort of single-compiler class.
156 # Would be nice to have a consistent interface with UnixCCompiler,
157 # though, so it's worth thinking about.
158 executables = {}
159
160 # Private class data (need to distinguish C from C++ source for compiler)
161 _c_extensions = ['.c']
162 _cpp_extensions = ['.cc', '.cpp', '.cxx']
163 _rc_extensions = ['.rc']
164 _mc_extensions = ['.mc']
165
166 # Needed for the filename generation methods provided by the
167 # base class, CCompiler.
168 src_extensions = (_c_extensions + _cpp_extensions +
169 _rc_extensions + _mc_extensions)
170 res_extension = '.res'
171 obj_extension = '.obj'
172 static_lib_extension = '.lib'
173 shared_lib_extension = '.dll'
174 static_lib_format = shared_lib_format = '%s%s'
175 exe_extension = '.exe'
176
177
178 def __init__(self, verbose=0, dry_run=0, force=0):
179 CCompiler.__init__ (self, verbose, dry_run, force)
180 # target platform (.plat_name is consistent with 'bdist')
181 self.plat_name = None
182 self.initialized = False
183
184 def initialize(self, plat_name=None):
185 # multi-init means we would need to check platform same each time...
186 assert not self.initialized, "don't init multiple times"
187 if plat_name is None:
188 plat_name = get_platform()
189 # sanity check for platforms to prevent obscure errors later.
190 if plat_name not in PLAT_TO_VCVARS:
191 raise DistutilsPlatformError("--plat-name must be one of {}"
192 .format(tuple(PLAT_TO_VCVARS)))
193
Steve Dower1d329412016-01-16 12:39:10 -0800194 # Get the vcvarsall.bat spec for the requested platform.
195 plat_spec = PLAT_TO_VCVARS[plat_name]
Steve Dowerfd3664b2015-05-23 09:02:50 -0700196
197 vc_env = _get_vc_env(plat_spec)
198 if not vc_env:
199 raise DistutilsPlatformError("Unable to find a compatible "
200 "Visual Studio installation.")
201
Steve Dower31202ea2015-08-05 11:39:19 -0700202 self._paths = vc_env.get('path', '')
203 paths = self._paths.split(os.pathsep)
Steve Dowerfd3664b2015-05-23 09:02:50 -0700204 self.cc = _find_exe("cl.exe", paths)
205 self.linker = _find_exe("link.exe", paths)
206 self.lib = _find_exe("lib.exe", paths)
207 self.rc = _find_exe("rc.exe", paths) # resource compiler
208 self.mc = _find_exe("mc.exe", paths) # message compiler
209 self.mt = _find_exe("mt.exe", paths) # message compiler
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700210 self._vcruntime_redist = vc_env.get('py_vcruntime_redist', '')
Steve Dowerfd3664b2015-05-23 09:02:50 -0700211
212 for dir in vc_env.get('include', '').split(os.pathsep):
213 if dir:
214 self.add_include_dir(dir)
215
216 for dir in vc_env.get('lib', '').split(os.pathsep):
217 if dir:
218 self.add_library_dir(dir)
219
220 self.preprocess_options = None
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700221 # If vcruntime_redist is available, link against it dynamically. Otherwise,
222 # use /MT[d] to build statically, then switch from libucrt[d].lib to ucrt[d].lib
Steve Dower31202ea2015-08-05 11:39:19 -0700223 # later to dynamically link to ucrtbase but not vcruntime.
Steve Dowerfd3664b2015-05-23 09:02:50 -0700224 self.compile_options = [
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700225 '/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG'
Steve Dowerfd3664b2015-05-23 09:02:50 -0700226 ]
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700227 self.compile_options.append('/MD' if self._vcruntime_redist else '/MT')
Larry Hastings52e40cd2015-09-09 06:54:57 -0700228
Steve Dowerfd3664b2015-05-23 09:02:50 -0700229 self.compile_options_debug = [
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700230 '/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG'
Steve Dowerfd3664b2015-05-23 09:02:50 -0700231 ]
232
Steve Dower31202ea2015-08-05 11:39:19 -0700233 ldflags = [
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700234 '/nologo', '/INCREMENTAL:NO', '/LTCG'
Steve Dowerfd3664b2015-05-23 09:02:50 -0700235 ]
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700236 if not self._vcruntime_redist:
237 ldflags.extend(('/nodefaultlib:libucrt.lib', 'ucrt.lib'))
238
Steve Dower31202ea2015-08-05 11:39:19 -0700239 ldflags_debug = [
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700240 '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL'
Steve Dowerfd3664b2015-05-23 09:02:50 -0700241 ]
Steve Dower31202ea2015-08-05 11:39:19 -0700242
243 self.ldflags_exe = [*ldflags, '/MANIFEST:EMBED,ID=1']
244 self.ldflags_exe_debug = [*ldflags_debug, '/MANIFEST:EMBED,ID=1']
245 self.ldflags_shared = [*ldflags, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO']
246 self.ldflags_shared_debug = [*ldflags_debug, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO']
247 self.ldflags_static = [*ldflags]
248 self.ldflags_static_debug = [*ldflags_debug]
249
250 self._ldflags = {
251 (CCompiler.EXECUTABLE, None): self.ldflags_exe,
252 (CCompiler.EXECUTABLE, False): self.ldflags_exe,
253 (CCompiler.EXECUTABLE, True): self.ldflags_exe_debug,
254 (CCompiler.SHARED_OBJECT, None): self.ldflags_shared,
255 (CCompiler.SHARED_OBJECT, False): self.ldflags_shared,
256 (CCompiler.SHARED_OBJECT, True): self.ldflags_shared_debug,
257 (CCompiler.SHARED_LIBRARY, None): self.ldflags_static,
258 (CCompiler.SHARED_LIBRARY, False): self.ldflags_static,
259 (CCompiler.SHARED_LIBRARY, True): self.ldflags_static_debug,
260 }
Steve Dowerfd3664b2015-05-23 09:02:50 -0700261
262 self.initialized = True
263
264 # -- Worker methods ------------------------------------------------
265
266 def object_filenames(self,
267 source_filenames,
268 strip_dir=0,
269 output_dir=''):
Steve Dower31202ea2015-08-05 11:39:19 -0700270 ext_map = {
271 **{ext: self.obj_extension for ext in self.src_extensions},
272 **{ext: self.res_extension for ext in self._rc_extensions + self._mc_extensions},
273 }
274
275 output_dir = output_dir or ''
Steve Dowerfd3664b2015-05-23 09:02:50 -0700276
277 def make_out_path(p):
278 base, ext = os.path.splitext(p)
279 if strip_dir:
280 base = os.path.basename(base)
281 else:
282 _, base = os.path.splitdrive(base)
283 if base.startswith((os.path.sep, os.path.altsep)):
284 base = base[1:]
285 try:
Steve Dower31202ea2015-08-05 11:39:19 -0700286 # XXX: This may produce absurdly long paths. We should check
287 # the length of the result and trim base until we fit within
288 # 260 characters.
289 return os.path.join(output_dir, base + ext_map[ext])
Steve Dowerfd3664b2015-05-23 09:02:50 -0700290 except LookupError:
291 # Better to raise an exception instead of silently continuing
292 # and later complain about sources and targets having
293 # different lengths
294 raise CompileError("Don't know how to compile {}".format(p))
295
Steve Dower31202ea2015-08-05 11:39:19 -0700296 return list(map(make_out_path, source_filenames))
Steve Dowerfd3664b2015-05-23 09:02:50 -0700297
298
299 def compile(self, sources,
300 output_dir=None, macros=None, include_dirs=None, debug=0,
301 extra_preargs=None, extra_postargs=None, depends=None):
302
303 if not self.initialized:
304 self.initialize()
305 compile_info = self._setup_compile(output_dir, macros, include_dirs,
306 sources, depends, extra_postargs)
307 macros, objects, extra_postargs, pp_opts, build = compile_info
308
309 compile_opts = extra_preargs or []
310 compile_opts.append('/c')
311 if debug:
312 compile_opts.extend(self.compile_options_debug)
313 else:
314 compile_opts.extend(self.compile_options)
315
316
317 add_cpp_opts = False
318
319 for obj in objects:
320 try:
321 src, ext = build[obj]
322 except KeyError:
323 continue
324 if debug:
325 # pass the full pathname to MSVC in debug mode,
326 # this allows the debugger to find the source file
327 # without asking the user to browse for it
328 src = os.path.abspath(src)
329
330 if ext in self._c_extensions:
331 input_opt = "/Tc" + src
332 elif ext in self._cpp_extensions:
333 input_opt = "/Tp" + src
334 add_cpp_opts = True
335 elif ext in self._rc_extensions:
336 # compile .RC to .RES file
337 input_opt = src
338 output_opt = "/fo" + obj
339 try:
340 self.spawn([self.rc] + pp_opts + [output_opt, input_opt])
341 except DistutilsExecError as msg:
342 raise CompileError(msg)
343 continue
344 elif ext in self._mc_extensions:
345 # Compile .MC to .RC file to .RES file.
346 # * '-h dir' specifies the directory for the
347 # generated include file
348 # * '-r dir' specifies the target directory of the
349 # generated RC file and the binary message resource
350 # it includes
351 #
352 # For now (since there are no options to change this),
353 # we use the source-directory for the include file and
354 # the build directory for the RC file and message
355 # resources. This works at least for win32all.
356 h_dir = os.path.dirname(src)
357 rc_dir = os.path.dirname(obj)
358 try:
359 # first compile .MC to .RC and .H file
360 self.spawn([self.mc, '-h', h_dir, '-r', rc_dir, src])
361 base, _ = os.path.splitext(os.path.basename (src))
362 rc_file = os.path.join(rc_dir, base + '.rc')
363 # then compile .RC to .RES file
364 self.spawn([self.rc, "/fo" + obj, rc_file])
365
366 except DistutilsExecError as msg:
367 raise CompileError(msg)
368 continue
369 else:
370 # how to handle this file?
371 raise CompileError("Don't know how to compile {} to {}"
372 .format(src, obj))
373
374 args = [self.cc] + compile_opts + pp_opts
375 if add_cpp_opts:
376 args.append('/EHsc')
377 args.append(input_opt)
378 args.append("/Fo" + obj)
379 args.extend(extra_postargs)
380
381 try:
382 self.spawn(args)
383 except DistutilsExecError as msg:
384 raise CompileError(msg)
385
386 return objects
387
388
389 def create_static_lib(self,
390 objects,
391 output_libname,
392 output_dir=None,
393 debug=0,
394 target_lang=None):
395
396 if not self.initialized:
397 self.initialize()
398 objects, output_dir = self._fix_object_args(objects, output_dir)
399 output_filename = self.library_filename(output_libname,
400 output_dir=output_dir)
401
402 if self._need_link(objects, output_filename):
403 lib_args = objects + ['/OUT:' + output_filename]
404 if debug:
405 pass # XXX what goes here?
406 try:
Steve Dower31202ea2015-08-05 11:39:19 -0700407 log.debug('Executing "%s" %s', self.lib, ' '.join(lib_args))
Steve Dowerfd3664b2015-05-23 09:02:50 -0700408 self.spawn([self.lib] + lib_args)
409 except DistutilsExecError as msg:
410 raise LibError(msg)
411 else:
412 log.debug("skipping %s (up-to-date)", output_filename)
413
414
415 def link(self,
416 target_desc,
417 objects,
418 output_filename,
419 output_dir=None,
420 libraries=None,
421 library_dirs=None,
422 runtime_library_dirs=None,
423 export_symbols=None,
424 debug=0,
425 extra_preargs=None,
426 extra_postargs=None,
427 build_temp=None,
428 target_lang=None):
429
430 if not self.initialized:
431 self.initialize()
432 objects, output_dir = self._fix_object_args(objects, output_dir)
433 fixed_args = self._fix_lib_args(libraries, library_dirs,
434 runtime_library_dirs)
435 libraries, library_dirs, runtime_library_dirs = fixed_args
436
437 if runtime_library_dirs:
438 self.warn("I don't know what to do with 'runtime_library_dirs': "
439 + str(runtime_library_dirs))
440
441 lib_opts = gen_lib_options(self,
442 library_dirs, runtime_library_dirs,
443 libraries)
444 if output_dir is not None:
445 output_filename = os.path.join(output_dir, output_filename)
446
447 if self._need_link(objects, output_filename):
Steve Dower31202ea2015-08-05 11:39:19 -0700448 ldflags = self._ldflags[target_desc, debug]
Steve Dowerfd3664b2015-05-23 09:02:50 -0700449
Steve Dower31202ea2015-08-05 11:39:19 -0700450 export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])]
Steve Dowerfd3664b2015-05-23 09:02:50 -0700451
452 ld_args = (ldflags + lib_opts + export_opts +
453 objects + ['/OUT:' + output_filename])
454
455 # The MSVC linker generates .lib and .exp files, which cannot be
456 # suppressed by any linker switches. The .lib files may even be
457 # needed! Make sure they are generated in the temporary build
458 # directory. Since they have different names for debug and release
459 # builds, they can go into the same directory.
460 build_temp = os.path.dirname(objects[0])
461 if export_symbols is not None:
462 (dll_name, dll_ext) = os.path.splitext(
463 os.path.basename(output_filename))
464 implib_file = os.path.join(
465 build_temp,
466 self.library_filename(dll_name))
467 ld_args.append ('/IMPLIB:' + implib_file)
468
Steve Dowerfd3664b2015-05-23 09:02:50 -0700469 if extra_preargs:
470 ld_args[:0] = extra_preargs
471 if extra_postargs:
472 ld_args.extend(extra_postargs)
473
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700474 output_dir = os.path.dirname(os.path.abspath(output_filename))
475 self.mkpath(output_dir)
Steve Dowerfd3664b2015-05-23 09:02:50 -0700476 try:
Steve Dower31202ea2015-08-05 11:39:19 -0700477 log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args))
Steve Dowerfd3664b2015-05-23 09:02:50 -0700478 self.spawn([self.linker] + ld_args)
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700479 self._copy_vcruntime(output_dir)
Steve Dowerfd3664b2015-05-23 09:02:50 -0700480 except DistutilsExecError as msg:
481 raise LinkError(msg)
Steve Dowerfd3664b2015-05-23 09:02:50 -0700482 else:
483 log.debug("skipping %s (up-to-date)", output_filename)
484
Steve Dowerfcbe1df2015-09-08 21:39:01 -0700485 def _copy_vcruntime(self, output_dir):
486 vcruntime = self._vcruntime_redist
487 if not vcruntime or not os.path.isfile(vcruntime):
488 return
489
490 if os.path.basename(vcruntime).lower() in _BUNDLED_DLLS:
491 return
492
493 log.debug('Copying "%s"', vcruntime)
494 vcruntime = shutil.copy(vcruntime, output_dir)
495 os.chmod(vcruntime, stat.S_IWRITE)
496
Steve Dower31202ea2015-08-05 11:39:19 -0700497 def spawn(self, cmd):
498 old_path = os.getenv('path')
Steve Dowerfd3664b2015-05-23 09:02:50 -0700499 try:
Steve Dower31202ea2015-08-05 11:39:19 -0700500 os.environ['path'] = self._paths
501 return super().spawn(cmd)
502 finally:
503 os.environ['path'] = old_path
Steve Dowerfd3664b2015-05-23 09:02:50 -0700504
505 # -- Miscellaneous methods -----------------------------------------
506 # These are all used by the 'gen_lib_options() function, in
507 # ccompiler.py.
508
509 def library_dir_option(self, dir):
510 return "/LIBPATH:" + dir
511
512 def runtime_library_dir_option(self, dir):
513 raise DistutilsPlatformError(
514 "don't know how to set runtime library search path for MSVC")
515
516 def library_option(self, lib):
517 return self.library_filename(lib)
518
519 def find_library_file(self, dirs, lib, debug=0):
520 # Prefer a debugging library if found (and requested), but deal
521 # with it if we don't have one.
522 if debug:
523 try_names = [lib + "_d", lib]
524 else:
525 try_names = [lib]
526 for dir in dirs:
527 for name in try_names:
528 libfile = os.path.join(dir, self.library_filename(name))
529 if os.path.isfile(libfile):
530 return libfile
531 else:
532 # Oops, didn't find it in *any* of 'dirs'
533 return None