NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

msvccompiler.py (17164B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\distutils\msvccompiler.py
      2 __revision__ = '$Id: msvccompiler.py 82110 2010-06-20 13:38:51Z kristjan.jonsson $'
      3 import sys
      4 import os
      5 import string
      6 from distutils.errors import DistutilsExecError, DistutilsPlatformError, CompileError, LibError, LinkError
      7 from distutils.ccompiler import CCompiler, gen_lib_options
      8 from distutils import log
      9 _can_read_reg = 0
     10 try:
     11     import _winreg
     12     _can_read_reg = 1
     13     hkey_mod = _winreg
     14     RegOpenKeyEx = _winreg.OpenKeyEx
     15     RegEnumKey = _winreg.EnumKey
     16     RegEnumValue = _winreg.EnumValue
     17     RegError = _winreg.error
     18 except ImportError:
     19     try:
     20         import win32api
     21         import win32con
     22         _can_read_reg = 1
     23         hkey_mod = win32con
     24         RegOpenKeyEx = win32api.RegOpenKeyEx
     25         RegEnumKey = win32api.RegEnumKey
     26         RegEnumValue = win32api.RegEnumValue
     27         RegError = win32api.error
     28     except ImportError:
     29         log.info("Warning: Can't read registry to find the necessary compiler setting\nMake sure that Python modules _winreg, win32api or win32con are installed.")
     30 
     31 if _can_read_reg:
     32     HKEYS = (hkey_mod.HKEY_USERS,
     33      hkey_mod.HKEY_CURRENT_USER,
     34      hkey_mod.HKEY_LOCAL_MACHINE,
     35      hkey_mod.HKEY_CLASSES_ROOT)
     36 
     37 def read_keys(base, key):
     38     try:
     39         handle = RegOpenKeyEx(base, key)
     40     except RegError:
     41         return None
     42 
     43     L = []
     44     i = 0
     45     while 1:
     46         try:
     47             k = RegEnumKey(handle, i)
     48         except RegError:
     49             break
     50 
     51         L.append(k)
     52         i = i + 1
     53 
     54     return L
     55 
     56 
     57 def read_values(base, key):
     58     try:
     59         handle = RegOpenKeyEx(base, key)
     60     except RegError:
     61         return None
     62 
     63     d = {}
     64     i = 0
     65     while 1:
     66         try:
     67             name, value, type = RegEnumValue(handle, i)
     68         except RegError:
     69             break
     70 
     71         name = name.lower()
     72         d[convert_mbcs(name)] = convert_mbcs(value)
     73         i = i + 1
     74 
     75     return d
     76 
     77 
     78 def convert_mbcs(s):
     79     enc = getattr(s, 'encode', None)
     80     if enc is not None:
     81         try:
     82             s = enc('mbcs')
     83         except UnicodeError:
     84             pass
     85 
     86     return s
     87 
     88 
     89 class MacroExpander():
     90 
     91     def __init__(self, version):
     92         self.macros = {}
     93         self.load_macros(version)
     94 
     95     def set_macro(self, macro, path, key):
     96         for base in HKEYS:
     97             d = read_values(base, path)
     98             if d:
     99                 self.macros['$(%s)' % macro] = d[key]
    100                 break
    101 
    102     def load_macros(self, version):
    103         vsbase = 'Software\\Microsoft\\VisualStudio\\%0.1f' % version
    104         self.set_macro('VCInstallDir', vsbase + '\\Setup\\VC', 'productdir')
    105         self.set_macro('VSInstallDir', vsbase + '\\Setup\\VS', 'productdir')
    106         net = 'Software\\Microsoft\\.NETFramework'
    107         self.set_macro('FrameworkDir', net, 'installroot')
    108         try:
    109             if version > 7.0:
    110                 self.set_macro('FrameworkSDKDir', net, 'sdkinstallrootv1.1')
    111             else:
    112                 self.set_macro('FrameworkSDKDir', net, 'sdkinstallroot')
    113         except KeyError:
    114             raise DistutilsPlatformError, 'Python was built with Visual Studio 2003;\nextensions must be built with a compiler than can generate compatible binaries.\nVisual Studio 2003 was not found on this system. If you have Cygwin installed,\nyou can try compiling with MingW32, by passing "-c mingw32" to setup.py.'
    115 
    116         p = 'Software\\Microsoft\\NET Framework Setup\\Product'
    117         for base in HKEYS:
    118             try:
    119                 h = RegOpenKeyEx(base, p)
    120             except RegError:
    121                 continue
    122 
    123             key = RegEnumKey(h, 0)
    124             d = read_values(base, '%s\\%s' % (p, key))
    125             self.macros['$(FrameworkVersion)'] = d['version']
    126 
    127     def sub(self, s):
    128         for k, v in self.macros.items():
    129             s = string.replace(s, k, v)
    130 
    131         return s
    132 
    133 
    134 def get_build_version():
    135     prefix = 'MSC v.'
    136     i = string.find(sys.version, prefix)
    137     if i == -1:
    138         return 6
    139     i = i + len(prefix)
    140     s, rest = sys.version[i:].split(' ', 1)
    141     majorVersion = int(s[:-2]) - 6
    142     minorVersion = int(s[2:3]) / 10.0
    143     if majorVersion == 6:
    144         minorVersion = 0
    145     if majorVersion >= 6:
    146         return majorVersion + minorVersion
    147 
    148 
    149 def get_build_architecture():
    150     prefix = ' bit ('
    151     i = string.find(sys.version, prefix)
    152     if i == -1:
    153         return 'Intel'
    154     j = string.find(sys.version, ')', i)
    155     return sys.version[i + len(prefix):j]
    156 
    157 
    158 def normalize_and_reduce_paths(paths):
    159     reduced_paths = []
    160     for p in paths:
    161         np = os.path.normpath(p)
    162         if np not in reduced_paths:
    163             reduced_paths.append(np)
    164 
    165     return reduced_paths
    166 
    167 
    168 class MSVCCompiler(CCompiler):
    169     compiler_type = 'msvc'
    170     executables = {}
    171     _c_extensions = ['.c']
    172     _cpp_extensions = ['.cc', '.cpp', '.cxx']
    173     _rc_extensions = ['.rc']
    174     _mc_extensions = ['.mc']
    175     src_extensions = _c_extensions + _cpp_extensions + _rc_extensions + _mc_extensions
    176     res_extension = '.res'
    177     obj_extension = '.obj'
    178     static_lib_extension = '.lib'
    179     shared_lib_extension = '.dll'
    180     static_lib_format = shared_lib_format = '%s%s'
    181     exe_extension = '.exe'
    182 
    183     def __init__(self, verbose = 0, dry_run = 0, force = 0):
    184         CCompiler.__init__(self, verbose, dry_run, force)
    185         self.__version = get_build_version()
    186         self.__arch = get_build_architecture()
    187         if self.__arch == 'Intel':
    188             if self.__version >= 7:
    189                 self.__root = 'Software\\Microsoft\\VisualStudio'
    190                 self.__macros = MacroExpander(self.__version)
    191             else:
    192                 self.__root = 'Software\\Microsoft\\Devstudio'
    193             self.__product = 'Visual Studio version %s' % self.__version
    194         else:
    195             self.__product = 'Microsoft SDK compiler %s' % (self.__version + 6)
    196         self.initialized = False
    197 
    198     def initialize(self):
    199         self.__paths = []
    200         if 'DISTUTILS_USE_SDK' in os.environ and 'MSSdk' in os.environ and self.find_exe('cl.exe'):
    201             self.cc = 'cl.exe'
    202             self.linker = 'link.exe'
    203             self.lib = 'lib.exe'
    204             self.rc = 'rc.exe'
    205             self.mc = 'mc.exe'
    206         else:
    207             self.__paths = self.get_msvc_paths('path')
    208             if len(self.__paths) == 0:
    209                 raise DistutilsPlatformError, "Python was built with %s, and extensions need to be built with the same version of the compiler, but it isn't installed." % self.__product
    210             self.cc = self.find_exe('cl.exe')
    211             self.linker = self.find_exe('link.exe')
    212             self.lib = self.find_exe('lib.exe')
    213             self.rc = self.find_exe('rc.exe')
    214             self.mc = self.find_exe('mc.exe')
    215             self.set_path_env_var('lib')
    216             self.set_path_env_var('include')
    217         try:
    218             for p in string.split(os.environ['path'], ';'):
    219                 self.__paths.append(p)
    220 
    221         except KeyError:
    222             pass
    223 
    224         self.__paths = normalize_and_reduce_paths(self.__paths)
    225         os.environ['path'] = string.join(self.__paths, ';')
    226         self.preprocess_options = None
    227         if self.__arch == 'Intel':
    228             self.compile_options = ['/nologo',
    229              '/Ox',
    230              '/MD',
    231              '/W3',
    232              '/GX',
    233              '/DNDEBUG']
    234             self.compile_options_debug = ['/nologo',
    235              '/Od',
    236              '/MDd',
    237              '/W3',
    238              '/GX',
    239              '/Z7',
    240              '/D_DEBUG']
    241         else:
    242             self.compile_options = ['/nologo',
    243              '/Ox',
    244              '/MD',
    245              '/W3',
    246              '/GS-',
    247              '/DNDEBUG']
    248             self.compile_options_debug = ['/nologo',
    249              '/Od',
    250              '/MDd',
    251              '/W3',
    252              '/GS-',
    253              '/Z7',
    254              '/D_DEBUG']
    255         self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
    256         if self.__version >= 7:
    257             self.ldflags_shared_debug = ['/DLL',
    258              '/nologo',
    259              '/INCREMENTAL:no',
    260              '/DEBUG']
    261         else:
    262             self.ldflags_shared_debug = ['/DLL',
    263              '/nologo',
    264              '/INCREMENTAL:no',
    265              '/pdb:None',
    266              '/DEBUG']
    267         self.ldflags_static = ['/nologo']
    268         self.initialized = True
    269 
    270     def object_filenames(self, source_filenames, strip_dir = 0, output_dir = ''):
    271         if output_dir is None:
    272             output_dir = ''
    273         obj_names = []
    274         for src_name in source_filenames:
    275             base, ext = os.path.splitext(src_name)
    276             base = os.path.splitdrive(base)[1]
    277             base = base[os.path.isabs(base):]
    278             if ext not in self.src_extensions:
    279                 raise CompileError("Don't know how to compile %s" % src_name)
    280             if strip_dir:
    281                 base = os.path.basename(base)
    282             if ext in self._rc_extensions:
    283                 obj_names.append(os.path.join(output_dir, base + self.res_extension))
    284             elif ext in self._mc_extensions:
    285                 obj_names.append(os.path.join(output_dir, base + self.res_extension))
    286             else:
    287                 obj_names.append(os.path.join(output_dir, base + self.obj_extension))
    288 
    289         return obj_names
    290 
    291     def compile(self, sources, output_dir = None, macros = None, include_dirs = None, debug = 0, extra_preargs = None, extra_postargs = None, depends = None):
    292         if not self.initialized:
    293             self.initialize()
    294         macros, objects, extra_postargs, pp_opts, build = self._setup_compile(output_dir, macros, include_dirs, sources, depends, extra_postargs)
    295         compile_opts = extra_preargs or []
    296         compile_opts.append('/c')
    297         if debug:
    298             compile_opts.extend(self.compile_options_debug)
    299         else:
    300             compile_opts.extend(self.compile_options)
    301         for obj in objects:
    302             try:
    303                 src, ext = build[obj]
    304             except KeyError:
    305                 continue
    306 
    307             if debug:
    308                 src = os.path.abspath(src)
    309             if ext in self._c_extensions:
    310                 input_opt = '/Tc' + src
    311             elif ext in self._cpp_extensions:
    312                 input_opt = '/Tp' + src
    313             elif ext in self._rc_extensions:
    314                 input_opt = src
    315                 output_opt = '/fo' + obj
    316                 try:
    317                     self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt])
    318                 except DistutilsExecError as msg:
    319                     raise CompileError, msg
    320 
    321                 continue
    322             elif ext in self._mc_extensions:
    323                 h_dir = os.path.dirname(src)
    324                 rc_dir = os.path.dirname(obj)
    325                 try:
    326                     self.spawn([self.mc] + ['-h',
    327                      h_dir,
    328                      '-r',
    329                      rc_dir] + [src])
    330                     base, _ = os.path.splitext(os.path.basename(src))
    331                     rc_file = os.path.join(rc_dir, base + '.rc')
    332                     self.spawn([self.rc] + ['/fo' + obj] + [rc_file])
    333                 except DistutilsExecError as msg:
    334                     raise CompileError, msg
    335 
    336                 continue
    337             else:
    338                 raise CompileError("Don't know how to compile %s to %s" % (src, obj))
    339             output_opt = '/Fo' + obj
    340             try:
    341                 self.spawn([self.cc] + compile_opts + pp_opts + [input_opt, output_opt] + extra_postargs)
    342             except DistutilsExecError as msg:
    343                 raise CompileError, msg
    344 
    345         return objects
    346 
    347     def create_static_lib(self, objects, output_libname, output_dir = None, debug = 0, target_lang = None):
    348         if not self.initialized:
    349             self.initialize()
    350         objects, output_dir = self._fix_object_args(objects, output_dir)
    351         output_filename = self.library_filename(output_libname, output_dir=output_dir)
    352         if self._need_link(objects, output_filename):
    353             lib_args = objects + ['/OUT:' + output_filename]
    354             if debug:
    355                 pass
    356             try:
    357                 self.spawn([self.lib] + lib_args)
    358             except DistutilsExecError as msg:
    359                 raise LibError, msg
    360 
    361         else:
    362             log.debug('skipping %s (up-to-date)', output_filename)
    363 
    364     def link(self, target_desc, objects, output_filename, output_dir = None, libraries = None, library_dirs = None, runtime_library_dirs = None, export_symbols = None, debug = 0, extra_preargs = None, extra_postargs = None, build_temp = None, target_lang = None):
    365         if not self.initialized:
    366             self.initialize()
    367         objects, output_dir = self._fix_object_args(objects, output_dir)
    368         libraries, library_dirs, runtime_library_dirs = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
    369         if runtime_library_dirs:
    370             self.warn("I don't know what to do with 'runtime_library_dirs': " + str(runtime_library_dirs))
    371         lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries)
    372         if output_dir is not None:
    373             output_filename = os.path.join(output_dir, output_filename)
    374         if self._need_link(objects, output_filename):
    375             if target_desc == CCompiler.EXECUTABLE:
    376                 if debug:
    377                     ldflags = self.ldflags_shared_debug[1:]
    378                 else:
    379                     ldflags = self.ldflags_shared[1:]
    380             elif debug:
    381                 ldflags = self.ldflags_shared_debug
    382             else:
    383                 ldflags = self.ldflags_shared
    384             export_opts = []
    385             for sym in export_symbols or []:
    386                 export_opts.append('/EXPORT:' + sym)
    387 
    388             ld_args = ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]
    389             if export_symbols is not None:
    390                 dll_name, dll_ext = os.path.splitext(os.path.basename(output_filename))
    391                 implib_file = os.path.join(os.path.dirname(objects[0]), self.library_filename(dll_name))
    392                 ld_args.append('/IMPLIB:' + implib_file)
    393             if extra_preargs:
    394                 ld_args[:0] = extra_preargs
    395             if extra_postargs:
    396                 ld_args.extend(extra_postargs)
    397             self.mkpath(os.path.dirname(output_filename))
    398             try:
    399                 self.spawn([self.linker] + ld_args)
    400             except DistutilsExecError as msg:
    401                 raise LinkError, msg
    402 
    403         else:
    404             log.debug('skipping %s (up-to-date)', output_filename)
    405 
    406     def library_dir_option(self, dir):
    407         return '/LIBPATH:' + dir
    408 
    409     def runtime_library_dir_option(self, dir):
    410         raise DistutilsPlatformError, "don't know how to set runtime library search path for MSVC++"
    411 
    412     def library_option(self, lib):
    413         return self.library_filename(lib)
    414 
    415     def find_library_file(self, dirs, lib, debug = 0):
    416         if debug:
    417             try_names = [lib + '_d', lib]
    418         else:
    419             try_names = [lib]
    420         for dir in dirs:
    421             for name in try_names:
    422                 libfile = os.path.join(dir, self.library_filename(name))
    423                 if os.path.exists(libfile):
    424                     return libfile
    425 
    426         else:
    427             return None
    428 
    429     def find_exe(self, exe):
    430         for p in self.__paths:
    431             fn = os.path.join(os.path.abspath(p), exe)
    432             if os.path.isfile(fn):
    433                 return fn
    434 
    435         for p in string.split(os.environ['Path'], ';'):
    436             fn = os.path.join(os.path.abspath(p), exe)
    437             if os.path.isfile(fn):
    438                 return fn
    439 
    440         return exe
    441 
    442     def get_msvc_paths(self, path, platform = 'x86'):
    443         if not _can_read_reg:
    444             return []
    445         path = path + ' dirs'
    446         if self.__version >= 7:
    447             key = '%s\\%0.1f\\VC\\VC_OBJECTS_PLATFORM_INFO\\Win32\\Directories' % (self.__root, self.__version)
    448         else:
    449             key = '%s\\6.0\\Build System\\Components\\Platforms\\Win32 (%s)\\Directories' % (self.__root, platform)
    450         for base in HKEYS:
    451             d = read_values(base, key)
    452             if d:
    453                 if self.__version >= 7:
    454                     return string.split(self.__macros.sub(d[path]), ';')
    455                 else:
    456                     return string.split(d[path], ';')
    457 
    458         if self.__version == 6:
    459             for base in HKEYS:
    460                 if read_values(base, '%s\\6.0' % self.__root) is not None:
    461                     self.warn('It seems you have Visual Studio 6 installed, but the expected registry settings are not present.\nYou must at least run the Visual Studio GUI once so that these entries are created.')
    462                     break
    463 
    464         return []
    465 
    466     def set_path_env_var(self, name):
    467         if name == 'lib':
    468             p = self.get_msvc_paths('library')
    469         else:
    470             p = self.get_msvc_paths(name)
    471         if p:
    472             os.environ[name] = string.join(p, ';')
    473 
    474 
    475 if get_build_version() >= 8.0:
    476     log.debug('Importing new compiler from distutils.msvc9compiler')
    477     OldMSVCCompiler = MSVCCompiler
    478     from distutils.msvc9compiler import MSVCCompiler
    479     from distutils.msvc9compiler import MacroExpander