Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/distutils/msvc9compiler.py

    r2 r391  
    1313# ported to VS2005 and VS 2008 by Christian Heimes
    1414
    15 __revision__ = "$Id: msvc9compiler.py 76652 2009-12-03 20:56:15Z martin.v.loewis $"
     15__revision__ = "$Id$"
    1616
    1717import os
     
    1919import sys
    2020import re
     21
    2122from distutils.errors import (DistutilsExecError, DistutilsPlatformError,
    22     CompileError, LibError, LinkError)
    23 from distutils.ccompiler import (CCompiler, gen_preprocess_options,
    24     gen_lib_options)
     23                              CompileError, LibError, LinkError)
     24from distutils.ccompiler import CCompiler, gen_lib_options
    2525from distutils import log
    2626from distutils.util import get_platform
     
    3838         _winreg.HKEY_CLASSES_ROOT)
    3939
    40 VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
    41 WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
    42 NET_BASE = r"Software\Microsoft\.NETFramework"
     40NATIVE_WIN64 = (sys.platform == 'win32' and sys.maxsize > 2**32)
     41if NATIVE_WIN64:
     42    # Visual C++ is a 32-bit application, so we need to look in
     43    # the corresponding registry branch, if we're running a
     44    # 64-bit Python on Win64
     45    VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f"
     46    VSEXPRESS_BASE = r"Software\Wow6432Node\Microsoft\VCExpress\%0.1f"
     47    WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows"
     48    NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework"
     49else:
     50    VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
     51    VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f"
     52    WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
     53    NET_BASE = r"Software\Microsoft\.NETFramework"
    4354
    4455# A map keyed by get_platform() return values to values accepted by
     
    5566    """
    5667
    57     @classmethod
    5868    def get_value(cls, path, key):
    5969        for base in HKEYS:
     
    6272                return d[key]
    6373        raise KeyError(key)
    64 
    65     @classmethod
     74    get_value = classmethod(get_value)
     75
    6676    def read_keys(cls, base, key):
    6777        """Return list of registry keys."""
     
    8090            i += 1
    8191        return L
    82 
    83     @classmethod
     92    read_keys = classmethod(read_keys)
     93
    8494    def read_values(cls, base, key):
    8595        """Return dict of registry keys and values.
     
    102112            i += 1
    103113        return d
    104 
    105     @staticmethod
     114    read_values = classmethod(read_values)
     115
    106116    def convert_mbcs(s):
    107117        dec = getattr(s, "decode", None)
     
    112122                pass
    113123        return s
     124    convert_mbcs = staticmethod(convert_mbcs)
    114125
    115126class MacroExpander:
     
    133144            else:
    134145                raise KeyError("sdkinstallrootv2.0")
    135         except KeyError as exc: #
     146        except KeyError:
    136147            raise DistutilsPlatformError(
    137148            """Python was built with Visual Studio 2008;
     
    217228                                   "productdir")
    218229    except KeyError:
    219         log.debug("Unable to find productdir in registry")
    220230        productdir = None
     231
     232    # trying Express edition
     233    if productdir is None:
     234        vsbase = VSEXPRESS_BASE % version
     235        try:
     236            productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
     237                                       "productdir")
     238        except KeyError:
     239            productdir = None
     240            log.debug("Unable to find productdir in registry")
    221241
    222242    if not productdir or not os.path.isdir(productdir):
     
    254274                             stdout=subprocess.PIPE,
    255275                             stderr=subprocess.PIPE)
    256 
    257     stdout, stderr = popen.communicate()
    258     if popen.wait() != 0:
    259         raise DistutilsPlatformError(stderr.decode("mbcs"))
    260 
    261     stdout = stdout.decode("mbcs")
    262     for line in stdout.split("\n"):
    263         line = Reg.convert_mbcs(line)
    264         if '=' not in line:
    265             continue
    266         line = line.strip()
    267         key, value = line.split('=', 1)
    268         key = key.lower()
    269         if key in interesting:
    270             if value.endswith(os.pathsep):
    271                 value = value[:-1]
    272             result[key] = removeDuplicates(value)
     276    try:
     277        stdout, stderr = popen.communicate()
     278        if popen.wait() != 0:
     279            raise DistutilsPlatformError(stderr.decode("mbcs"))
     280
     281        stdout = stdout.decode("mbcs")
     282        for line in stdout.split("\n"):
     283            line = Reg.convert_mbcs(line)
     284            if '=' not in line:
     285                continue
     286            line = line.strip()
     287            key, value = line.split('=', 1)
     288            key = key.lower()
     289            if key in interesting:
     290                if value.endswith(os.pathsep):
     291                    value = value[:-1]
     292                result[key] = removeDuplicates(value)
     293
     294    finally:
     295        popen.stdout.close()
     296        popen.stderr.close()
    273297
    274298    if len(result) != len(interesting):
     
    481505                    self.spawn([self.rc] + pp_opts +
    482506                               [output_opt] + [input_opt])
    483                 except DistutilsExecError as msg:
     507                except DistutilsExecError, msg:
    484508                    raise CompileError(msg)
    485509                continue
     
    508532                               ["/fo" + obj] + [rc_file])
    509533
    510                 except DistutilsExecError as msg:
     534                except DistutilsExecError, msg:
    511535                    raise CompileError(msg)
    512536                continue
     
    521545                           [input_opt, output_opt] +
    522546                           extra_postargs)
    523             except DistutilsExecError as msg:
     547            except DistutilsExecError, msg:
    524548                raise CompileError(msg)
    525549
     
    546570            try:
    547571                self.spawn([self.lib] + lib_args)
    548             except DistutilsExecError as msg:
     572            except DistutilsExecError, msg:
    549573                raise LibError(msg)
    550574        else:
     
    617641                ld_args.append ('/IMPLIB:' + implib_file)
    618642
    619             # Embedded manifests are recommended - see MSDN article titled
    620             # "How to: Embed a Manifest Inside a C/C++ Application"
    621             # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx)
    622             # Ask the linker to generate the manifest in the temp dir, so
    623             # we can embed it later.
    624             temp_manifest = os.path.join(
    625                     build_temp,
    626                     os.path.basename(output_filename) + ".manifest")
    627             ld_args.append('/MANIFESTFILE:' + temp_manifest)
     643            self.manifest_setup_ldargs(output_filename, build_temp, ld_args)
    628644
    629645            if extra_preargs:
     
    635651            try:
    636652                self.spawn([self.linker] + ld_args)
    637             except DistutilsExecError as msg:
     653            except DistutilsExecError, msg:
    638654                raise LinkError(msg)
    639655
     
    643659            # manifest.  Maybe we should link to a temp file?  OTOH, that
    644660            # implies a build environment error that shouldn't go undetected.
    645             if target_desc == CCompiler.EXECUTABLE:
    646                 mfid = 1
    647             else:
    648                 mfid = 2
     661            mfinfo = self.manifest_get_embed_info(target_desc, ld_args)
     662            if mfinfo is not None:
     663                mffilename, mfid = mfinfo
     664                out_arg = '-outputresource:%s;%s' % (output_filename, mfid)
    649665                try:
    650                     # Remove references to the Visual C runtime, so they will
    651                     # fall through to the Visual C dependency of Python.exe.
    652                     # This way, when installed for a restricted user (e.g.
    653                     # runtimes are not in WinSxS folder, but in Python's own
    654                     # folder), the runtimes do not need to be in every folder
    655                     # with .pyd's.
    656                     manifest_f = open(temp_manifest, "rb")
    657                     manifest_buf = manifest_f.read()
    658                     manifest_f.close()
    659                     pattern = re.compile(
    660                         r"""<assemblyIdentity.*?name=("|')Microsoft\."""\
    661                         r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
    662                         re.DOTALL)
    663                     manifest_buf = re.sub(pattern, "", manifest_buf)
    664                     pattern = "<dependentAssembly>\s*</dependentAssembly>"
    665                     manifest_buf = re.sub(pattern, "", manifest_buf)
    666                     manifest_f = open(temp_manifest, "wb")
    667                     manifest_f.write(manifest_buf)
    668                     manifest_f.close()
    669                 except IOError:
    670                     pass
    671             out_arg = '-outputresource:%s;%s' % (output_filename, mfid)
     666                    self.spawn(['mt.exe', '-nologo', '-manifest',
     667                                mffilename, out_arg])
     668                except DistutilsExecError, msg:
     669                    raise LinkError(msg)
     670        else:
     671            log.debug("skipping %s (up-to-date)", output_filename)
     672
     673    def manifest_setup_ldargs(self, output_filename, build_temp, ld_args):
     674        # If we need a manifest at all, an embedded manifest is recommended.
     675        # See MSDN article titled
     676        # "How to: Embed a Manifest Inside a C/C++ Application"
     677        # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx)
     678        # Ask the linker to generate the manifest in the temp dir, so
     679        # we can check it, and possibly embed it, later.
     680        temp_manifest = os.path.join(
     681                build_temp,
     682                os.path.basename(output_filename) + ".manifest")
     683        ld_args.append('/MANIFESTFILE:' + temp_manifest)
     684
     685    def manifest_get_embed_info(self, target_desc, ld_args):
     686        # If a manifest should be embedded, return a tuple of
     687        # (manifest_filename, resource_id).  Returns None if no manifest
     688        # should be embedded.  See http://bugs.python.org/issue7833 for why
     689        # we want to avoid any manifest for extension modules if we can)
     690        for arg in ld_args:
     691            if arg.startswith("/MANIFESTFILE:"):
     692                temp_manifest = arg.split(":", 1)[1]
     693                break
     694        else:
     695            # no /MANIFESTFILE so nothing to do.
     696            return None
     697        if target_desc == CCompiler.EXECUTABLE:
     698            # by default, executables always get the manifest with the
     699            # CRT referenced.
     700            mfid = 1
     701        else:
     702            # Extension modules try and avoid any manifest if possible.
     703            mfid = 2
     704            temp_manifest = self._remove_visual_c_ref(temp_manifest)
     705        if temp_manifest is None:
     706            return None
     707        return temp_manifest, mfid
     708
     709    def _remove_visual_c_ref(self, manifest_file):
     710        try:
     711            # Remove references to the Visual C runtime, so they will
     712            # fall through to the Visual C dependency of Python.exe.
     713            # This way, when installed for a restricted user (e.g.
     714            # runtimes are not in WinSxS folder, but in Python's own
     715            # folder), the runtimes do not need to be in every folder
     716            # with .pyd's.
     717            # Returns either the filename of the modified manifest or
     718            # None if no manifest should be embedded.
     719            manifest_f = open(manifest_file)
    672720            try:
    673                 self.spawn(['mt.exe', '-nologo', '-manifest',
    674                             temp_manifest, out_arg])
    675             except DistutilsExecError as msg:
    676                 raise LinkError(msg)
    677         else:
    678             log.debug("skipping %s (up-to-date)", output_filename)
    679 
     721                manifest_buf = manifest_f.read()
     722            finally:
     723                manifest_f.close()
     724            pattern = re.compile(
     725                r"""<assemblyIdentity.*?name=("|')Microsoft\."""\
     726                r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
     727                re.DOTALL)
     728            manifest_buf = re.sub(pattern, "", manifest_buf)
     729            pattern = "<dependentAssembly>\s*</dependentAssembly>"
     730            manifest_buf = re.sub(pattern, "", manifest_buf)
     731            # Now see if any other assemblies are referenced - if not, we
     732            # don't want a manifest embedded.
     733            pattern = re.compile(
     734                r"""<assemblyIdentity.*?name=(?:"|')(.+?)(?:"|')"""
     735                r""".*?(?:/>|</assemblyIdentity>)""", re.DOTALL)
     736            if re.search(pattern, manifest_buf) is None:
     737                return None
     738
     739            manifest_f = open(manifest_file, 'w')
     740            try:
     741                manifest_f.write(manifest_buf)
     742                return manifest_file
     743            finally:
     744                manifest_f.close()
     745        except IOError:
     746            pass
    680747
    681748    # -- Miscellaneous methods -----------------------------------------
Note: See TracChangeset for help on using the changeset viewer.