[Python-checkins] bpo-38597: Never statically link extension initialization code on Windows (GH-18724)

Miss Islington (bot) webhook-mailer at python.org
Mon Mar 2 19:30:26 EST 2020


https://github.com/python/cpython/commit/0d20364b132014eec609b900997c34779a4d548c
commit: 0d20364b132014eec609b900997c34779a4d548c
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2020年03月02日T16:30:18-08:00
summary:
bpo-38597: Never statically link extension initialization code on Windows (GH-18724)
(cherry picked from commit ce3a4984089b8e0ce5422ca32d75ad057b008074)
Co-authored-by: Steve Dower <steve.dower at python.org>
files:
A Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst
M Lib/distutils/_msvccompiler.py
M Lib/distutils/tests/test_msvccompiler.py
M PCbuild/pythoncore.vcxproj
diff --git a/Lib/distutils/_msvccompiler.py b/Lib/distutils/_msvccompiler.py
index e8e4b717b9736..03a5986d984dc 100644
--- a/Lib/distutils/_msvccompiler.py
+++ b/Lib/distutils/_msvccompiler.py
@@ -97,28 +97,11 @@ def _find_vc2017():
 }
 
 def _find_vcvarsall(plat_spec):
+ # bpo-38597: Removed vcruntime return value
 _, best_dir = _find_vc2017()
- vcruntime = None
-
- if plat_spec in PLAT_SPEC_TO_RUNTIME:
- vcruntime_plat = PLAT_SPEC_TO_RUNTIME[plat_spec]
- else:
- vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86'
-
- if best_dir:
- vcredist = os.path.join(best_dir, "..", "..", "redist", "MSVC", "**",
- vcruntime_plat, "Microsoft.VC14*.CRT", "vcruntime140.dll")
- try:
- import glob
- vcruntime = glob.glob(vcredist, recursive=True)[-1]
- except (ImportError, OSError, LookupError):
- vcruntime = None
 
 if not best_dir:
 best_version, best_dir = _find_vc2015()
- if best_version:
- vcruntime = os.path.join(best_dir, 'redist', vcruntime_plat,
- "Microsoft.VC140.CRT", "vcruntime140.dll")
 
 if not best_dir:
 log.debug("No suitable Visual C++ version found")
@@ -129,11 +112,7 @@ def _find_vcvarsall(plat_spec):
 log.debug("%s cannot be found", vcvarsall)
 return None, None
 
- if not vcruntime or not os.path.isfile(vcruntime):
- log.debug("%s cannot be found", vcruntime)
- vcruntime = None
-
- return vcvarsall, vcruntime
+ return vcvarsall, None
 
 def _get_vc_env(plat_spec):
 if os.getenv("DISTUTILS_USE_SDK"):
@@ -142,7 +121,7 @@ def _get_vc_env(plat_spec):
 for key, value in os.environ.items()
 }
 
- vcvarsall, vcruntime = _find_vcvarsall(plat_spec)
+ vcvarsall, _ = _find_vcvarsall(plat_spec)
 if not vcvarsall:
 raise DistutilsPlatformError("Unable to find vcvarsall.bat")
 
@@ -163,8 +142,6 @@ def _get_vc_env(plat_spec):
 if key and value
 }
 
- if vcruntime:
- env['py_vcruntime_redist'] = vcruntime
 return env
 
 def _find_exe(exe, paths=None):
@@ -194,12 +171,6 @@ def _find_exe(exe, paths=None):
 'win-arm64' : 'x86_arm64'
 }
 
-# A set containing the DLLs that are guaranteed to be available for
-# all micro versions of this Python version. Known extension
-# dependencies that are not in this set will be copied to the output
-# path.
-_BUNDLED_DLLS = frozenset(['vcruntime140.dll'])
-
 class MSVCCompiler(CCompiler) :
 """Concrete class that implements an interface to Microsoft Visual C++,
 as defined by the CCompiler abstract class."""
@@ -263,7 +234,6 @@ def initialize(self, plat_name=None):
 self.rc = _find_exe("rc.exe", paths) # resource compiler
 self.mc = _find_exe("mc.exe", paths) # message compiler
 self.mt = _find_exe("mt.exe", paths) # message compiler
- self._vcruntime_redist = vc_env.get('py_vcruntime_redist', '')
 
 for dir in vc_env.get('include', '').split(os.pathsep):
 if dir:
@@ -274,13 +244,12 @@ def initialize(self, plat_name=None):
 self.add_library_dir(dir.rstrip(os.sep))
 
 self.preprocess_options = None
- # If vcruntime_redist is available, link against it dynamically. Otherwise,
- # use /MT[d] to build statically, then switch from libucrt[d].lib to ucrt[d].lib
- # later to dynamically link to ucrtbase but not vcruntime.
+ # bpo-38597: Always compile with dynamic linking
+ # Future releases of Python 3.x will include all past
+ # versions of vcruntime*.dll for compatibility.
 self.compile_options = [
- '/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG'
+ '/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG', '/MD'
 ]
- self.compile_options.append('/MD' if self._vcruntime_redist else '/MT')
 
 self.compile_options_debug = [
 '/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG'
@@ -289,8 +258,6 @@ def initialize(self, plat_name=None):
 ldflags = [
 '/nologo', '/INCREMENTAL:NO', '/LTCG'
 ]
- if not self._vcruntime_redist:
- ldflags.extend(('/nodefaultlib:libucrt.lib', 'ucrt.lib'))
 
 ldflags_debug = [
 '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL'
@@ -532,24 +499,11 @@ def link(self,
 try:
 log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args))
 self.spawn([self.linker] + ld_args)
- self._copy_vcruntime(output_dir)
 except DistutilsExecError as msg:
 raise LinkError(msg)
 else:
 log.debug("skipping %s (up-to-date)", output_filename)
 
- def _copy_vcruntime(self, output_dir):
- vcruntime = self._vcruntime_redist
- if not vcruntime or not os.path.isfile(vcruntime):
- return
-
- if os.path.basename(vcruntime).lower() in _BUNDLED_DLLS:
- return
-
- log.debug('Copying "%s"', vcruntime)
- vcruntime = shutil.copy(vcruntime, output_dir)
- os.chmod(vcruntime, stat.S_IWRITE)
-
 def spawn(self, cmd):
 old_path = os.getenv('path')
 try:
diff --git a/Lib/distutils/tests/test_msvccompiler.py b/Lib/distutils/tests/test_msvccompiler.py
index 70a9c93a4e880..b518d6a78b332 100644
--- a/Lib/distutils/tests/test_msvccompiler.py
+++ b/Lib/distutils/tests/test_msvccompiler.py
@@ -32,57 +32,6 @@ def _find_vcvarsall(plat_spec):
 finally:
 _msvccompiler._find_vcvarsall = old_find_vcvarsall
 
- def test_compiler_options(self):
- import distutils._msvccompiler as _msvccompiler
- # suppress path to vcruntime from _find_vcvarsall to
- # check that /MT is added to compile options
- old_find_vcvarsall = _msvccompiler._find_vcvarsall
- def _find_vcvarsall(plat_spec):
- return old_find_vcvarsall(plat_spec)[0], None
- _msvccompiler._find_vcvarsall = _find_vcvarsall
- try:
- compiler = _msvccompiler.MSVCCompiler()
- compiler.initialize()
-
- self.assertIn('/MT', compiler.compile_options)
- self.assertNotIn('/MD', compiler.compile_options)
- finally:
- _msvccompiler._find_vcvarsall = old_find_vcvarsall
-
- def test_vcruntime_copy(self):
- import distutils._msvccompiler as _msvccompiler
- # force path to a known file - it doesn't matter
- # what we copy as long as its name is not in
- # _msvccompiler._BUNDLED_DLLS
- old_find_vcvarsall = _msvccompiler._find_vcvarsall
- def _find_vcvarsall(plat_spec):
- return old_find_vcvarsall(plat_spec)[0], __file__
- _msvccompiler._find_vcvarsall = _find_vcvarsall
- try:
- tempdir = self.mkdtemp()
- compiler = _msvccompiler.MSVCCompiler()
- compiler.initialize()
- compiler._copy_vcruntime(tempdir)
-
- self.assertTrue(os.path.isfile(os.path.join(
- tempdir, os.path.basename(__file__))))
- finally:
- _msvccompiler._find_vcvarsall = old_find_vcvarsall
-
- def test_vcruntime_skip_copy(self):
- import distutils._msvccompiler as _msvccompiler
-
- tempdir = self.mkdtemp()
- compiler = _msvccompiler.MSVCCompiler()
- compiler.initialize()
- dll = compiler._vcruntime_redist
- self.assertTrue(os.path.isfile(dll), dll or "<None>")
-
- compiler._copy_vcruntime(tempdir)
-
- self.assertFalse(os.path.isfile(os.path.join(
- tempdir, os.path.basename(dll))), dll or "<None>")
-
 def test_get_vc_env_unicode(self):
 import distutils._msvccompiler as _msvccompiler
 
diff --git a/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst b/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst
new file mode 100644
index 0000000000000..7f3a2e756c5a1
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst
@@ -0,0 +1,4 @@
+:mod:`distutils` will no longer statically link :file:`vcruntime140.dll`
+when a redistributable version is unavailable. All future releases of
+CPython will include a copy of this DLL to ensure distributed extensions can
+continue to load.
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 13c3b594e4431..bd16c1e070bc2 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -528,6 +528,8 @@
 <VCRuntimeDLL Include="$(VCRedistDir)\**\vcruntime*.dll" />
 </ItemGroup>
 <Target Name="_CopyVCRuntime" AfterTargets="Build" Inputs="@(VCRuntimeDLL)" Outputs="$(OutDir)%(Filename)%(Extension)">
+ <!-- bpo-38597: When we switch to another VCRuntime DLL, include vcruntime140.dll as well -->
+ <Warning Text="A copy of vcruntime140.dll is also required" Condition="!$(VCToolsRedistVersion.StartsWith(`14.`))" />
 <Copy SourceFiles="%(VCRuntimeDLL.FullPath)" DestinationFolder="$(OutDir)" />
 </Target>
 <Target Name="_CleanVCRuntime" AfterTargets="Clean">


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /