Switch to setuptools.msvc for getting setup info for the Windows compiler, reducing dependence on distutils.

This commit is contained in:
Robin Dunn
2022-05-14 20:31:11 -07:00
parent 3e6be81d6d
commit cadd91697c
4 changed files with 80 additions and 57 deletions

View File

@@ -45,7 +45,7 @@ from buildtools.config import Config, msg, opj, posixjoin, loadETG, etg2sip, fi
macSetLoaderNames, \
getVcsRev, runcmd, textfile_open, getSipFiles, \
getVisCVersion, getToolsPlatformName, updateLicenseFiles, \
TemporaryDirectory
TemporaryDirectory, getMSVCInfo
from buildtools.wxpysip import sip_runner
import buildtools.version as version
@@ -785,37 +785,30 @@ def uploadTree(srcPath, destPath, options, days=30):
def checkCompiler(quiet=False):
if isWindows:
# Make sure that the compiler that Python wants to use can be found.
# It will terminate if the compiler is not found or other exceptions
# are raised.
cmd = "import setuptools, distutils.msvc9compiler as msvc; " \
"mc = msvc.MSVCCompiler(); " \
"mc.initialize(); " \
"print(mc.cc)"
CC = runcmd('"%s" -c "%s"' % (PYTHON, cmd), getOutput=True, echoCmd=False)
# Make sure that the compiler that Python wants to use can be found. It
# will terminate if the compiler is not found or other exceptions are
# raised. Note that we execute these checks using the target Python in
# case the one running this script is different. (TODO: It's probably
# about time to do away with this...)
arch = 'x64' if PYTHON_ARCH == '64bit' else 'x86'
info = getMSVCInfo(PYTHON, arch)
os.environ['PATH'] = info.path
os.environ['INCLUDE'] = info.include
os.environ['LIB'] = info.lib
os.environ['LIBPATH'] = info.libpath
# Make sure there is now a cl.exe on the PATH
CL = 'NOT FOUND'
for d in os.environ['PATH'].split(os.pathsep):
p = pathlib.Path(d, 'cl.exe')
if p.exists():
CL = p
break
if not quiet:
msg("MSVC: %s" % CC)
msg(f"CL.exe: {CL}")
# Now get the environment variables which that compiler needs from
# its vcvarsall.bat command and load them into this process's
# environment.
cmd = "import setuptools, distutils.msvc9compiler as msvc; " \
"arch = msvc.PLAT_TO_VCVARS[msvc.get_platform()]; " \
"env = msvc.query_vcvarsall(msvc.VERSION, arch); " \
"print(env)"
env = eval(runcmd('"%s" -c "%s"' % (PYTHON, cmd), getOutput=True, echoCmd=False))
def _b(v):
return str(v)
#if PY2:
# return bytes(v)
#else:
# return bytes(v, 'utf8')
os.environ['PATH'] = _b(env['path'])
os.environ['INCLUDE'] = _b(env['include'])
os.environ['LIB'] = _b(env['lib'])
os.environ['LIBPATH'] = _b(env['libpath'])
# NOTE: SIP is now generating code with scoped-enums. Older linux
# platforms like what we're using for builds, and also TravisCI for

View File

@@ -16,6 +16,7 @@ import types
import subprocess
from buildtools import builder
from buildtools.config import getVisCVersion
PY3 = sys.version_info[0] == 3
@@ -63,20 +64,6 @@ def getXcodePaths():
return [base, base+"/Platforms/MacOSX.platform/Developer"]
def getVisCVersion():
text = getoutput("cl.exe")
if 'Version 13' in text:
return '71'
if 'Version 15' in text:
return '90'
if 'Version 16' in text:
return '100'
if 'Version 19' in text:
return '140'
# TODO: Add more tests to get the other versions...
else:
return 'FIXME'
def exitIfError(code, msg):
if code != 0:

View File

@@ -27,6 +27,8 @@ from distutils.dep_util import newer
import distutils.sysconfig
from attrdict import AttrDict
runSilently = False
#----------------------------------------------------------------------
@@ -951,20 +953,60 @@ def getSipFiles(names):
def getVisCVersion():
text = runcmd("cl.exe", getOutput=True, echoCmd=False)
if 'Version 13' in text:
return '71'
if 'Version 15' in text:
return '90'
if 'Version 16' in text:
return '100'
if 'Version 18' in text:
return '120'
if 'Version 19' in text:
return '140'
# TODO: Add more tests to get the other versions...
if MSVCinfo is None:
raise RuntimeError('getMSVCInfo has not been called yet.')
# Convert a float like 14.28 to 140, for historical reasons
# TODO: decide on switching to 142, 143, etc.??
ver = str(int(MSVCinfo.vc_ver)) + '0'
return ver
def getExpectedVisCVersion():
"""
Returns the Visual C version that Python is expecting, based on the usual
version that stock Python was built with.
"""
if MSVCinfo is None:
raise RuntimeError('getMSVCInfo has not been called yet.')
py_ver = MSVCinfo.py_ver
if py_ver in ((3, 4),):
min_ver = 10.0
elif py_ver in ((3, 5), (3, 6), (3, 7), (3, 8)):
min_ver = 14.0
elif py_ver in ((3, 9), (3, 10)):
min_ver = 14.2
else:
return 'FIXME'
raise RuntimeError('This library does not support python version %d.%d' % py_version)
return min_ver
MSVCinfo = None
def getMSVCInfo(PYTHON, arch):
"""
Fetch info from the system about MSVC, such as versions, paths, etc.
"""
global MSVCinfo
if MSVCinfo is not None:
return MSVCinfo
# Note that it starts with a monkey-patch in setuptools.msvc to
# workaround this issue: pypa/setuptools#1902
cmd = \
"import os, sys, setuptools.msvc; " \
"setuptools.msvc.isfile = lambda path: path is not None and os.path.isfile(path); " \
"ei = setuptools.msvc.EnvironmentInfo('{}'); " \
"env = ei.return_env(); " \
"env['vc_ver'] = ei.vc_ver; " \
"env['vs_ver'] = ei.vs_ver; " \
"env['arch'] = ei.pi.arch; " \
"env['py_ver'] = sys.version_info[:2]; " \
"print(env)"
cmd = cmd.format(arch)
env = eval(runcmd('"%s" -c "%s"' % (PYTHON, cmd), getOutput=True, echoCmd=False))
info = AttrDict(env)
MSVCinfo = info
return info
_haveObjDump = None

View File

@@ -19,3 +19,4 @@ sphinx==2.2.0 ; python_version >= '3.0'
sphinx==1.8.5 ; python_version < '3.0'
doc2dash==2.3.0
beautifulsoup4
attrdict3