symbian-qemu-0.9.1-12/python-2.6.1/Lib/distutils/msvccompiler.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """distutils.msvccompiler
       
     2 
       
     3 Contains MSVCCompiler, an implementation of the abstract CCompiler class
       
     4 for the Microsoft Visual Studio.
       
     5 """
       
     6 
       
     7 # Written by Perry Stoll
       
     8 # hacked by Robin Becker and Thomas Heller to do a better job of
       
     9 #   finding DevStudio (through the registry)
       
    10 
       
    11 # This module should be kept compatible with Python 2.1.
       
    12 
       
    13 __revision__ = "$Id: msvccompiler.py 62197 2008-04-07 01:53:39Z mark.hammond $"
       
    14 
       
    15 import sys, os, string
       
    16 from distutils.errors import \
       
    17      DistutilsExecError, DistutilsPlatformError, \
       
    18      CompileError, LibError, LinkError
       
    19 from distutils.ccompiler import \
       
    20      CCompiler, gen_preprocess_options, gen_lib_options
       
    21 from distutils import log
       
    22 
       
    23 _can_read_reg = 0
       
    24 try:
       
    25     import _winreg
       
    26 
       
    27     _can_read_reg = 1
       
    28     hkey_mod = _winreg
       
    29 
       
    30     RegOpenKeyEx = _winreg.OpenKeyEx
       
    31     RegEnumKey = _winreg.EnumKey
       
    32     RegEnumValue = _winreg.EnumValue
       
    33     RegError = _winreg.error
       
    34 
       
    35 except ImportError:
       
    36     try:
       
    37         import win32api
       
    38         import win32con
       
    39         _can_read_reg = 1
       
    40         hkey_mod = win32con
       
    41 
       
    42         RegOpenKeyEx = win32api.RegOpenKeyEx
       
    43         RegEnumKey = win32api.RegEnumKey
       
    44         RegEnumValue = win32api.RegEnumValue
       
    45         RegError = win32api.error
       
    46 
       
    47     except ImportError:
       
    48         log.info("Warning: Can't read registry to find the "
       
    49                  "necessary compiler setting\n"
       
    50                  "Make sure that Python modules _winreg, "
       
    51                  "win32api or win32con are installed.")
       
    52         pass
       
    53 
       
    54 if _can_read_reg:
       
    55     HKEYS = (hkey_mod.HKEY_USERS,
       
    56              hkey_mod.HKEY_CURRENT_USER,
       
    57              hkey_mod.HKEY_LOCAL_MACHINE,
       
    58              hkey_mod.HKEY_CLASSES_ROOT)
       
    59 
       
    60 def read_keys(base, key):
       
    61     """Return list of registry keys."""
       
    62 
       
    63     try:
       
    64         handle = RegOpenKeyEx(base, key)
       
    65     except RegError:
       
    66         return None
       
    67     L = []
       
    68     i = 0
       
    69     while 1:
       
    70         try:
       
    71             k = RegEnumKey(handle, i)
       
    72         except RegError:
       
    73             break
       
    74         L.append(k)
       
    75         i = i + 1
       
    76     return L
       
    77 
       
    78 def read_values(base, key):
       
    79     """Return dict of registry keys and values.
       
    80 
       
    81     All names are converted to lowercase.
       
    82     """
       
    83     try:
       
    84         handle = RegOpenKeyEx(base, key)
       
    85     except RegError:
       
    86         return None
       
    87     d = {}
       
    88     i = 0
       
    89     while 1:
       
    90         try:
       
    91             name, value, type = RegEnumValue(handle, i)
       
    92         except RegError:
       
    93             break
       
    94         name = name.lower()
       
    95         d[convert_mbcs(name)] = convert_mbcs(value)
       
    96         i = i + 1
       
    97     return d
       
    98 
       
    99 def convert_mbcs(s):
       
   100     enc = getattr(s, "encode", None)
       
   101     if enc is not None:
       
   102         try:
       
   103             s = enc("mbcs")
       
   104         except UnicodeError:
       
   105             pass
       
   106     return s
       
   107 
       
   108 class MacroExpander:
       
   109 
       
   110     def __init__(self, version):
       
   111         self.macros = {}
       
   112         self.load_macros(version)
       
   113 
       
   114     def set_macro(self, macro, path, key):
       
   115         for base in HKEYS:
       
   116             d = read_values(base, path)
       
   117             if d:
       
   118                 self.macros["$(%s)" % macro] = d[key]
       
   119                 break
       
   120 
       
   121     def load_macros(self, version):
       
   122         vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
       
   123         self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
       
   124         self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
       
   125         net = r"Software\Microsoft\.NETFramework"
       
   126         self.set_macro("FrameworkDir", net, "installroot")
       
   127         try:
       
   128             if version > 7.0:
       
   129                 self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
       
   130             else:
       
   131                 self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
       
   132         except KeyError, exc: #
       
   133             raise DistutilsPlatformError, \
       
   134                   ("""Python was built with Visual Studio 2003;
       
   135 extensions must be built with a compiler than can generate compatible binaries.
       
   136 Visual Studio 2003 was not found on this system. If you have Cygwin installed,
       
   137 you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
       
   138 
       
   139         p = r"Software\Microsoft\NET Framework Setup\Product"
       
   140         for base in HKEYS:
       
   141             try:
       
   142                 h = RegOpenKeyEx(base, p)
       
   143             except RegError:
       
   144                 continue
       
   145             key = RegEnumKey(h, 0)
       
   146             d = read_values(base, r"%s\%s" % (p, key))
       
   147             self.macros["$(FrameworkVersion)"] = d["version"]
       
   148 
       
   149     def sub(self, s):
       
   150         for k, v in self.macros.items():
       
   151             s = string.replace(s, k, v)
       
   152         return s
       
   153 
       
   154 def get_build_version():
       
   155     """Return the version of MSVC that was used to build Python.
       
   156 
       
   157     For Python 2.3 and up, the version number is included in
       
   158     sys.version.  For earlier versions, assume the compiler is MSVC 6.
       
   159     """
       
   160 
       
   161     prefix = "MSC v."
       
   162     i = string.find(sys.version, prefix)
       
   163     if i == -1:
       
   164         return 6
       
   165     i = i + len(prefix)
       
   166     s, rest = sys.version[i:].split(" ", 1)
       
   167     majorVersion = int(s[:-2]) - 6
       
   168     minorVersion = int(s[2:3]) / 10.0
       
   169     # I don't think paths are affected by minor version in version 6
       
   170     if majorVersion == 6:
       
   171         minorVersion = 0
       
   172     if majorVersion >= 6:
       
   173         return majorVersion + minorVersion
       
   174     # else we don't know what version of the compiler this is
       
   175     return None
       
   176 
       
   177 def get_build_architecture():
       
   178     """Return the processor architecture.
       
   179 
       
   180     Possible results are "Intel", "Itanium", or "AMD64".
       
   181     """
       
   182 
       
   183     prefix = " bit ("
       
   184     i = string.find(sys.version, prefix)
       
   185     if i == -1:
       
   186         return "Intel"
       
   187     j = string.find(sys.version, ")", i)
       
   188     return sys.version[i+len(prefix):j]
       
   189 
       
   190 def normalize_and_reduce_paths(paths):
       
   191     """Return a list of normalized paths with duplicates removed.
       
   192 
       
   193     The current order of paths is maintained.
       
   194     """
       
   195     # Paths are normalized so things like:  /a and /a/ aren't both preserved.
       
   196     reduced_paths = []
       
   197     for p in paths:
       
   198         np = os.path.normpath(p)
       
   199         # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
       
   200         if np not in reduced_paths:
       
   201             reduced_paths.append(np)
       
   202     return reduced_paths
       
   203 
       
   204 
       
   205 class MSVCCompiler (CCompiler) :
       
   206     """Concrete class that implements an interface to Microsoft Visual C++,
       
   207        as defined by the CCompiler abstract class."""
       
   208 
       
   209     compiler_type = 'msvc'
       
   210 
       
   211     # Just set this so CCompiler's constructor doesn't barf.  We currently
       
   212     # don't use the 'set_executables()' bureaucracy provided by CCompiler,
       
   213     # as it really isn't necessary for this sort of single-compiler class.
       
   214     # Would be nice to have a consistent interface with UnixCCompiler,
       
   215     # though, so it's worth thinking about.
       
   216     executables = {}
       
   217 
       
   218     # Private class data (need to distinguish C from C++ source for compiler)
       
   219     _c_extensions = ['.c']
       
   220     _cpp_extensions = ['.cc', '.cpp', '.cxx']
       
   221     _rc_extensions = ['.rc']
       
   222     _mc_extensions = ['.mc']
       
   223 
       
   224     # Needed for the filename generation methods provided by the
       
   225     # base class, CCompiler.
       
   226     src_extensions = (_c_extensions + _cpp_extensions +
       
   227                       _rc_extensions + _mc_extensions)
       
   228     res_extension = '.res'
       
   229     obj_extension = '.obj'
       
   230     static_lib_extension = '.lib'
       
   231     shared_lib_extension = '.dll'
       
   232     static_lib_format = shared_lib_format = '%s%s'
       
   233     exe_extension = '.exe'
       
   234 
       
   235     def __init__ (self, verbose=0, dry_run=0, force=0):
       
   236         CCompiler.__init__ (self, verbose, dry_run, force)
       
   237         self.__version = get_build_version()
       
   238         self.__arch = get_build_architecture()
       
   239         if self.__arch == "Intel":
       
   240             # x86
       
   241             if self.__version >= 7:
       
   242                 self.__root = r"Software\Microsoft\VisualStudio"
       
   243                 self.__macros = MacroExpander(self.__version)
       
   244             else:
       
   245                 self.__root = r"Software\Microsoft\Devstudio"
       
   246             self.__product = "Visual Studio version %s" % self.__version
       
   247         else:
       
   248             # Win64. Assume this was built with the platform SDK
       
   249             self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
       
   250 
       
   251         self.initialized = False
       
   252 
       
   253     def initialize(self):
       
   254         self.__paths = []
       
   255         if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
       
   256             # Assume that the SDK set up everything alright; don't try to be
       
   257             # smarter
       
   258             self.cc = "cl.exe"
       
   259             self.linker = "link.exe"
       
   260             self.lib = "lib.exe"
       
   261             self.rc = "rc.exe"
       
   262             self.mc = "mc.exe"
       
   263         else:
       
   264             self.__paths = self.get_msvc_paths("path")
       
   265 
       
   266             if len (self.__paths) == 0:
       
   267                 raise DistutilsPlatformError, \
       
   268                       ("Python was built with %s, "
       
   269                        "and extensions need to be built with the same "
       
   270                        "version of the compiler, but it isn't installed." % self.__product)
       
   271 
       
   272             self.cc = self.find_exe("cl.exe")
       
   273             self.linker = self.find_exe("link.exe")
       
   274             self.lib = self.find_exe("lib.exe")
       
   275             self.rc = self.find_exe("rc.exe")   # resource compiler
       
   276             self.mc = self.find_exe("mc.exe")   # message compiler
       
   277             self.set_path_env_var('lib')
       
   278             self.set_path_env_var('include')
       
   279 
       
   280         # extend the MSVC path with the current path
       
   281         try:
       
   282             for p in string.split(os.environ['path'], ';'):
       
   283                 self.__paths.append(p)
       
   284         except KeyError:
       
   285             pass
       
   286         self.__paths = normalize_and_reduce_paths(self.__paths)
       
   287         os.environ['path'] = string.join(self.__paths, ';')
       
   288 
       
   289         self.preprocess_options = None
       
   290         if self.__arch == "Intel":
       
   291             self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
       
   292                                      '/DNDEBUG']
       
   293             self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
       
   294                                           '/Z7', '/D_DEBUG']
       
   295         else:
       
   296             # Win64
       
   297             self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
       
   298                                      '/DNDEBUG']
       
   299             self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
       
   300                                           '/Z7', '/D_DEBUG']
       
   301 
       
   302         self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
       
   303         if self.__version >= 7:
       
   304             self.ldflags_shared_debug = [
       
   305                 '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
       
   306                 ]
       
   307         else:
       
   308             self.ldflags_shared_debug = [
       
   309                 '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
       
   310                 ]
       
   311         self.ldflags_static = [ '/nologo']
       
   312 
       
   313         self.initialized = True
       
   314 
       
   315     # -- Worker methods ------------------------------------------------
       
   316 
       
   317     def object_filenames (self,
       
   318                           source_filenames,
       
   319                           strip_dir=0,
       
   320                           output_dir=''):
       
   321         # Copied from ccompiler.py, extended to return .res as 'object'-file
       
   322         # for .rc input file
       
   323         if output_dir is None: output_dir = ''
       
   324         obj_names = []
       
   325         for src_name in source_filenames:
       
   326             (base, ext) = os.path.splitext (src_name)
       
   327             base = os.path.splitdrive(base)[1] # Chop off the drive
       
   328             base = base[os.path.isabs(base):]  # If abs, chop off leading /
       
   329             if ext not in self.src_extensions:
       
   330                 # Better to raise an exception instead of silently continuing
       
   331                 # and later complain about sources and targets having
       
   332                 # different lengths
       
   333                 raise CompileError ("Don't know how to compile %s" % src_name)
       
   334             if strip_dir:
       
   335                 base = os.path.basename (base)
       
   336             if ext in self._rc_extensions:
       
   337                 obj_names.append (os.path.join (output_dir,
       
   338                                                 base + self.res_extension))
       
   339             elif ext in self._mc_extensions:
       
   340                 obj_names.append (os.path.join (output_dir,
       
   341                                                 base + self.res_extension))
       
   342             else:
       
   343                 obj_names.append (os.path.join (output_dir,
       
   344                                                 base + self.obj_extension))
       
   345         return obj_names
       
   346 
       
   347     # object_filenames ()
       
   348 
       
   349 
       
   350     def compile(self, sources,
       
   351                 output_dir=None, macros=None, include_dirs=None, debug=0,
       
   352                 extra_preargs=None, extra_postargs=None, depends=None):
       
   353 
       
   354         if not self.initialized: self.initialize()
       
   355         macros, objects, extra_postargs, pp_opts, build = \
       
   356                 self._setup_compile(output_dir, macros, include_dirs, sources,
       
   357                                     depends, extra_postargs)
       
   358 
       
   359         compile_opts = extra_preargs or []
       
   360         compile_opts.append ('/c')
       
   361         if debug:
       
   362             compile_opts.extend(self.compile_options_debug)
       
   363         else:
       
   364             compile_opts.extend(self.compile_options)
       
   365 
       
   366         for obj in objects:
       
   367             try:
       
   368                 src, ext = build[obj]
       
   369             except KeyError:
       
   370                 continue
       
   371             if debug:
       
   372                 # pass the full pathname to MSVC in debug mode,
       
   373                 # this allows the debugger to find the source file
       
   374                 # without asking the user to browse for it
       
   375                 src = os.path.abspath(src)
       
   376 
       
   377             if ext in self._c_extensions:
       
   378                 input_opt = "/Tc" + src
       
   379             elif ext in self._cpp_extensions:
       
   380                 input_opt = "/Tp" + src
       
   381             elif ext in self._rc_extensions:
       
   382                 # compile .RC to .RES file
       
   383                 input_opt = src
       
   384                 output_opt = "/fo" + obj
       
   385                 try:
       
   386                     self.spawn ([self.rc] + pp_opts +
       
   387                                 [output_opt] + [input_opt])
       
   388                 except DistutilsExecError, msg:
       
   389                     raise CompileError, msg
       
   390                 continue
       
   391             elif ext in self._mc_extensions:
       
   392 
       
   393                 # Compile .MC to .RC file to .RES file.
       
   394                 #   * '-h dir' specifies the directory for the
       
   395                 #     generated include file
       
   396                 #   * '-r dir' specifies the target directory of the
       
   397                 #     generated RC file and the binary message resource
       
   398                 #     it includes
       
   399                 #
       
   400                 # For now (since there are no options to change this),
       
   401                 # we use the source-directory for the include file and
       
   402                 # the build directory for the RC file and message
       
   403                 # resources. This works at least for win32all.
       
   404 
       
   405                 h_dir = os.path.dirname (src)
       
   406                 rc_dir = os.path.dirname (obj)
       
   407                 try:
       
   408                     # first compile .MC to .RC and .H file
       
   409                     self.spawn ([self.mc] +
       
   410                                 ['-h', h_dir, '-r', rc_dir] + [src])
       
   411                     base, _ = os.path.splitext (os.path.basename (src))
       
   412                     rc_file = os.path.join (rc_dir, base + '.rc')
       
   413                     # then compile .RC to .RES file
       
   414                     self.spawn ([self.rc] +
       
   415                                 ["/fo" + obj] + [rc_file])
       
   416 
       
   417                 except DistutilsExecError, msg:
       
   418                     raise CompileError, msg
       
   419                 continue
       
   420             else:
       
   421                 # how to handle this file?
       
   422                 raise CompileError (
       
   423                     "Don't know how to compile %s to %s" % \
       
   424                     (src, obj))
       
   425 
       
   426             output_opt = "/Fo" + obj
       
   427             try:
       
   428                 self.spawn ([self.cc] + compile_opts + pp_opts +
       
   429                             [input_opt, output_opt] +
       
   430                             extra_postargs)
       
   431             except DistutilsExecError, msg:
       
   432                 raise CompileError, msg
       
   433 
       
   434         return objects
       
   435 
       
   436     # compile ()
       
   437 
       
   438 
       
   439     def create_static_lib (self,
       
   440                            objects,
       
   441                            output_libname,
       
   442                            output_dir=None,
       
   443                            debug=0,
       
   444                            target_lang=None):
       
   445 
       
   446         if not self.initialized: self.initialize()
       
   447         (objects, output_dir) = self._fix_object_args (objects, output_dir)
       
   448         output_filename = \
       
   449             self.library_filename (output_libname, output_dir=output_dir)
       
   450 
       
   451         if self._need_link (objects, output_filename):
       
   452             lib_args = objects + ['/OUT:' + output_filename]
       
   453             if debug:
       
   454                 pass                    # XXX what goes here?
       
   455             try:
       
   456                 self.spawn ([self.lib] + lib_args)
       
   457             except DistutilsExecError, msg:
       
   458                 raise LibError, msg
       
   459 
       
   460         else:
       
   461             log.debug("skipping %s (up-to-date)", output_filename)
       
   462 
       
   463     # create_static_lib ()
       
   464 
       
   465     def link (self,
       
   466               target_desc,
       
   467               objects,
       
   468               output_filename,
       
   469               output_dir=None,
       
   470               libraries=None,
       
   471               library_dirs=None,
       
   472               runtime_library_dirs=None,
       
   473               export_symbols=None,
       
   474               debug=0,
       
   475               extra_preargs=None,
       
   476               extra_postargs=None,
       
   477               build_temp=None,
       
   478               target_lang=None):
       
   479 
       
   480         if not self.initialized: self.initialize()
       
   481         (objects, output_dir) = self._fix_object_args (objects, output_dir)
       
   482         (libraries, library_dirs, runtime_library_dirs) = \
       
   483             self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
       
   484 
       
   485         if runtime_library_dirs:
       
   486             self.warn ("I don't know what to do with 'runtime_library_dirs': "
       
   487                        + str (runtime_library_dirs))
       
   488 
       
   489         lib_opts = gen_lib_options (self,
       
   490                                     library_dirs, runtime_library_dirs,
       
   491                                     libraries)
       
   492         if output_dir is not None:
       
   493             output_filename = os.path.join (output_dir, output_filename)
       
   494 
       
   495         if self._need_link (objects, output_filename):
       
   496 
       
   497             if target_desc == CCompiler.EXECUTABLE:
       
   498                 if debug:
       
   499                     ldflags = self.ldflags_shared_debug[1:]
       
   500                 else:
       
   501                     ldflags = self.ldflags_shared[1:]
       
   502             else:
       
   503                 if debug:
       
   504                     ldflags = self.ldflags_shared_debug
       
   505                 else:
       
   506                     ldflags = self.ldflags_shared
       
   507 
       
   508             export_opts = []
       
   509             for sym in (export_symbols or []):
       
   510                 export_opts.append("/EXPORT:" + sym)
       
   511 
       
   512             ld_args = (ldflags + lib_opts + export_opts +
       
   513                        objects + ['/OUT:' + output_filename])
       
   514 
       
   515             # The MSVC linker generates .lib and .exp files, which cannot be
       
   516             # suppressed by any linker switches. The .lib files may even be
       
   517             # needed! Make sure they are generated in the temporary build
       
   518             # directory. Since they have different names for debug and release
       
   519             # builds, they can go into the same directory.
       
   520             if export_symbols is not None:
       
   521                 (dll_name, dll_ext) = os.path.splitext(
       
   522                     os.path.basename(output_filename))
       
   523                 implib_file = os.path.join(
       
   524                     os.path.dirname(objects[0]),
       
   525                     self.library_filename(dll_name))
       
   526                 ld_args.append ('/IMPLIB:' + implib_file)
       
   527 
       
   528             if extra_preargs:
       
   529                 ld_args[:0] = extra_preargs
       
   530             if extra_postargs:
       
   531                 ld_args.extend(extra_postargs)
       
   532 
       
   533             self.mkpath (os.path.dirname (output_filename))
       
   534             try:
       
   535                 self.spawn ([self.linker] + ld_args)
       
   536             except DistutilsExecError, msg:
       
   537                 raise LinkError, msg
       
   538 
       
   539         else:
       
   540             log.debug("skipping %s (up-to-date)", output_filename)
       
   541 
       
   542     # link ()
       
   543 
       
   544 
       
   545     # -- Miscellaneous methods -----------------------------------------
       
   546     # These are all used by the 'gen_lib_options() function, in
       
   547     # ccompiler.py.
       
   548 
       
   549     def library_dir_option (self, dir):
       
   550         return "/LIBPATH:" + dir
       
   551 
       
   552     def runtime_library_dir_option (self, dir):
       
   553         raise DistutilsPlatformError, \
       
   554               "don't know how to set runtime library search path for MSVC++"
       
   555 
       
   556     def library_option (self, lib):
       
   557         return self.library_filename (lib)
       
   558 
       
   559 
       
   560     def find_library_file (self, dirs, lib, debug=0):
       
   561         # Prefer a debugging library if found (and requested), but deal
       
   562         # with it if we don't have one.
       
   563         if debug:
       
   564             try_names = [lib + "_d", lib]
       
   565         else:
       
   566             try_names = [lib]
       
   567         for dir in dirs:
       
   568             for name in try_names:
       
   569                 libfile = os.path.join(dir, self.library_filename (name))
       
   570                 if os.path.exists(libfile):
       
   571                     return libfile
       
   572         else:
       
   573             # Oops, didn't find it in *any* of 'dirs'
       
   574             return None
       
   575 
       
   576     # find_library_file ()
       
   577 
       
   578     # Helper methods for using the MSVC registry settings
       
   579 
       
   580     def find_exe(self, exe):
       
   581         """Return path to an MSVC executable program.
       
   582 
       
   583         Tries to find the program in several places: first, one of the
       
   584         MSVC program search paths from the registry; next, the directories
       
   585         in the PATH environment variable.  If any of those work, return an
       
   586         absolute path that is known to exist.  If none of them work, just
       
   587         return the original program name, 'exe'.
       
   588         """
       
   589 
       
   590         for p in self.__paths:
       
   591             fn = os.path.join(os.path.abspath(p), exe)
       
   592             if os.path.isfile(fn):
       
   593                 return fn
       
   594 
       
   595         # didn't find it; try existing path
       
   596         for p in string.split(os.environ['Path'],';'):
       
   597             fn = os.path.join(os.path.abspath(p),exe)
       
   598             if os.path.isfile(fn):
       
   599                 return fn
       
   600 
       
   601         return exe
       
   602 
       
   603     def get_msvc_paths(self, path, platform='x86'):
       
   604         """Get a list of devstudio directories (include, lib or path).
       
   605 
       
   606         Return a list of strings.  The list will be empty if unable to
       
   607         access the registry or appropriate registry keys not found.
       
   608         """
       
   609 
       
   610         if not _can_read_reg:
       
   611             return []
       
   612 
       
   613         path = path + " dirs"
       
   614         if self.__version >= 7:
       
   615             key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories"
       
   616                    % (self.__root, self.__version))
       
   617         else:
       
   618             key = (r"%s\6.0\Build System\Components\Platforms"
       
   619                    r"\Win32 (%s)\Directories" % (self.__root, platform))
       
   620 
       
   621         for base in HKEYS:
       
   622             d = read_values(base, key)
       
   623             if d:
       
   624                 if self.__version >= 7:
       
   625                     return string.split(self.__macros.sub(d[path]), ";")
       
   626                 else:
       
   627                     return string.split(d[path], ";")
       
   628         # MSVC 6 seems to create the registry entries we need only when
       
   629         # the GUI is run.
       
   630         if self.__version == 6:
       
   631             for base in HKEYS:
       
   632                 if read_values(base, r"%s\6.0" % self.__root) is not None:
       
   633                     self.warn("It seems you have Visual Studio 6 installed, "
       
   634                         "but the expected registry settings are not present.\n"
       
   635                         "You must at least run the Visual Studio GUI once "
       
   636                         "so that these entries are created.")
       
   637                     break
       
   638         return []
       
   639 
       
   640     def set_path_env_var(self, name):
       
   641         """Set environment variable 'name' to an MSVC path type value.
       
   642 
       
   643         This is equivalent to a SET command prior to execution of spawned
       
   644         commands.
       
   645         """
       
   646 
       
   647         if name == "lib":
       
   648             p = self.get_msvc_paths("library")
       
   649         else:
       
   650             p = self.get_msvc_paths(name)
       
   651         if p:
       
   652             os.environ[name] = string.join(p, ';')
       
   653 
       
   654 
       
   655 if get_build_version() >= 8.0:
       
   656     log.debug("Importing new compiler from distutils.msvc9compiler")
       
   657     OldMSVCCompiler = MSVCCompiler
       
   658     from distutils.msvc9compiler import MSVCCompiler
       
   659     # get_build_architecture not really relevant now we support cross-compile
       
   660     from distutils.msvc9compiler import MacroExpander