Commit d034a5ec authored by Steve Dower's avatar Steve Dower

Issue #23970: Adds distutils._msvccompiler for new Visual Studio versions.

parent 37ec45e0
This diff is collapsed.
...@@ -959,7 +959,7 @@ def get_default_compiler(osname=None, platform=None): ...@@ -959,7 +959,7 @@ def get_default_compiler(osname=None, platform=None):
# is assumed to be in the 'distutils' package.) # is assumed to be in the 'distutils' package.)
compiler_class = { 'unix': ('unixccompiler', 'UnixCCompiler', compiler_class = { 'unix': ('unixccompiler', 'UnixCCompiler',
"standard UNIX-style compiler"), "standard UNIX-style compiler"),
'msvc': ('msvccompiler', 'MSVCCompiler', 'msvc': ('_msvccompiler', 'MSVCCompiler',
"Microsoft Visual C++"), "Microsoft Visual C++"),
'cygwin': ('cygwinccompiler', 'CygwinCCompiler', 'cygwin': ('cygwinccompiler', 'CygwinCCompiler',
"Cygwin port of GNU C Compiler for Win32"), "Cygwin port of GNU C Compiler for Win32"),
......
...@@ -303,7 +303,6 @@ class bdist_wininst(Command): ...@@ -303,7 +303,6 @@ class bdist_wininst(Command):
return installer_name return installer_name
def get_exe_bytes(self): def get_exe_bytes(self):
from distutils.msvccompiler import get_build_version
# If a target-version other than the current version has been # If a target-version other than the current version has been
# specified, then using the MSVC version from *this* build is no good. # specified, then using the MSVC version from *this* build is no good.
# Without actually finding and executing the target version and parsing # Without actually finding and executing the target version and parsing
...@@ -313,20 +312,28 @@ class bdist_wininst(Command): ...@@ -313,20 +312,28 @@ class bdist_wininst(Command):
# We can then execute this program to obtain any info we need, such # We can then execute this program to obtain any info we need, such
# as the real sys.version string for the build. # as the real sys.version string for the build.
cur_version = get_python_version() cur_version = get_python_version()
if self.target_version and self.target_version != cur_version:
# If the target version is *later* than us, then we assume they # If the target version is *later* than us, then we assume they
# use what we use # use what we use
# string compares seem wrong, but are what sysconfig.py itself uses # string compares seem wrong, but are what sysconfig.py itself uses
if self.target_version > cur_version: if self.target_version and self.target_version < cur_version:
bv = get_build_version() if self.target_version < "2.4":
bv = 6.0
elif self.target_version == "2.4":
bv = 7.1
elif self.target_version == "2.5":
bv = 8.0
elif self.target_version <= "3.2":
bv = 9.0
elif self.target_version <= "3.4":
bv = 10.0
else: else:
if self.target_version < "2.4": bv = 14.0
bv = 6.0
else:
bv = 7.1
else: else:
# for current version - use authoritative check. # for current version - use authoritative check.
bv = get_build_version() from msvcrt import CRT_ASSEMBLY_VERSION
bv = float('.'.join(CRT_ASSEMBLY_VERSION.split('.', 2)[:2]))
# wininst-x.y.exe is in the same directory as this file # wininst-x.y.exe is in the same directory as this file
directory = os.path.dirname(__file__) directory = os.path.dirname(__file__)
......
...@@ -19,10 +19,6 @@ from distutils import log ...@@ -19,10 +19,6 @@ from distutils import log
from site import USER_BASE from site import USER_BASE
if os.name == 'nt':
from distutils.msvccompiler import get_build_version
MSVC_VERSION = int(get_build_version())
# An extension name is just a dot-separated list of Python NAMEs (ie. # An extension name is just a dot-separated list of Python NAMEs (ie.
# the same as a fully-qualified module name). # the same as a fully-qualified module name).
extension_name_re = re.compile \ extension_name_re = re.compile \
...@@ -206,27 +202,17 @@ class build_ext(Command): ...@@ -206,27 +202,17 @@ class build_ext(Command):
_sys_home = getattr(sys, '_home', None) _sys_home = getattr(sys, '_home', None)
if _sys_home: if _sys_home:
self.library_dirs.append(_sys_home) self.library_dirs.append(_sys_home)
if MSVC_VERSION >= 9:
# Use the .lib files for the correct architecture # Use the .lib files for the correct architecture
if self.plat_name == 'win32': if self.plat_name == 'win32':
suffix = 'win32' suffix = 'win32'
else:
# win-amd64 or win-ia64
suffix = self.plat_name[4:]
new_lib = os.path.join(sys.exec_prefix, 'PCbuild')
if suffix:
new_lib = os.path.join(new_lib, suffix)
self.library_dirs.append(new_lib)
elif MSVC_VERSION == 8:
self.library_dirs.append(os.path.join(sys.exec_prefix,
'PC', 'VS8.0'))
elif MSVC_VERSION == 7:
self.library_dirs.append(os.path.join(sys.exec_prefix,
'PC', 'VS7.1'))
else: else:
self.library_dirs.append(os.path.join(sys.exec_prefix, # win-amd64 or win-ia64
'PC', 'VC6')) suffix = self.plat_name[4:]
new_lib = os.path.join(sys.exec_prefix, 'PCbuild')
if suffix:
new_lib = os.path.join(new_lib, suffix)
self.library_dirs.append(new_lib)
# for extensions under Cygwin and AtheOS Python's library directory must be # for extensions under Cygwin and AtheOS Python's library directory must be
# appended to library_dirs # appended to library_dirs
...@@ -716,7 +702,7 @@ class build_ext(Command): ...@@ -716,7 +702,7 @@ class build_ext(Command):
# to need it mentioned explicitly, though, so that's what we do. # to need it mentioned explicitly, though, so that's what we do.
# Append '_d' to the python import library on debug builds. # Append '_d' to the python import library on debug builds.
if sys.platform == "win32": if sys.platform == "win32":
from distutils.msvccompiler import MSVCCompiler from distutils._msvccompiler import MSVCCompiler
if not isinstance(self.compiler, MSVCCompiler): if not isinstance(self.compiler, MSVCCompiler):
template = "python%d%d" template = "python%d%d"
if self.debug: if self.debug:
......
"""Tests for distutils._msvccompiler."""
import sys
import unittest
import os
from distutils.errors import DistutilsPlatformError
from distutils.tests import support
from test.support import run_unittest
# A manifest with the only assembly reference being the msvcrt assembly, so
# should have the assembly completely stripped. Note that although the
# assembly has a <security> reference the assembly is removed - that is
# currently a "feature", not a bug :)
_MANIFEST_WITH_ONLY_MSVC_REFERENCE = """\
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false">
</requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT"
version="9.0.21022.8" processorArchitecture="x86"
publicKeyToken="XXXX">
</assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>
"""
# A manifest with references to assemblies other than msvcrt. When processed,
# this assembly should be returned with just the msvcrt part removed.
_MANIFEST_WITH_MULTIPLE_REFERENCES = """\
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false">
</requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT"
version="9.0.21022.8" processorArchitecture="x86"
publicKeyToken="XXXX">
</assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.MFC"
version="9.0.21022.8" processorArchitecture="x86"
publicKeyToken="XXXX"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>
"""
_CLEANED_MANIFEST = """\
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false">
</requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.MFC"
version="9.0.21022.8" processorArchitecture="x86"
publicKeyToken="XXXX"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>"""
SKIP_MESSAGE = (None if sys.platform == "win32" else
"These tests are only for win32")
@unittest.skipUnless(SKIP_MESSAGE is None, SKIP_MESSAGE)
class msvccompilerTestCase(support.TempdirManager,
unittest.TestCase):
def test_no_compiler(self):
# makes sure query_vcvarsall raises
# a DistutilsPlatformError if the compiler
# is not found
from distutils._msvccompiler import _get_vc_env
def _find_vcvarsall():
return None
import distutils._msvccompiler as _msvccompiler
old_find_vcvarsall = _msvccompiler._find_vcvarsall
_msvccompiler._find_vcvarsall = _find_vcvarsall
try:
self.assertRaises(DistutilsPlatformError, _get_vc_env,
'wont find this version')
finally:
_msvccompiler._find_vcvarsall = old_find_vcvarsall
def test_remove_visual_c_ref(self):
from distutils._msvccompiler import MSVCCompiler
tempdir = self.mkdtemp()
manifest = os.path.join(tempdir, 'manifest')
f = open(manifest, 'w')
try:
f.write(_MANIFEST_WITH_MULTIPLE_REFERENCES)
finally:
f.close()
compiler = MSVCCompiler()
compiler._remove_visual_c_ref(manifest)
# see what we got
f = open(manifest)
try:
# removing trailing spaces
content = '\n'.join([line.rstrip() for line in f.readlines()])
finally:
f.close()
# makes sure the manifest was properly cleaned
self.assertEqual(content, _CLEANED_MANIFEST)
def test_remove_entire_manifest(self):
from distutils._msvccompiler import MSVCCompiler
tempdir = self.mkdtemp()
manifest = os.path.join(tempdir, 'manifest')
f = open(manifest, 'w')
try:
f.write(_MANIFEST_WITH_ONLY_MSVC_REFERENCE)
finally:
f.close()
compiler = MSVCCompiler()
got = compiler._remove_visual_c_ref(manifest)
self.assertIsNone(got)
def test_suite():
return unittest.makeSuite(msvccompilerTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment