From 9c4dc4955c2a81891e96cfef97692e80dcf4f563 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 16 Aug 2022 18:46:26 -0400 Subject: [PATCH 01/14] Suppress warnings in deprecated msvc compilers --- pytest.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pytest.ini b/pytest.ini index 56dcdec426..3fdd11cc9d 100644 --- a/pytest.ini +++ b/pytest.ini @@ -21,3 +21,6 @@ filterwarnings= # ignore spurious and unactionable warnings ignore:The frontend.OptionParser class will be replaced by a subclass of argparse.ArgumentParser in Docutils 0.21 or later.:DeprecationWarning: ignore: The frontend.Option class will be removed in Docutils 0.21 or later.:DeprecationWarning: + + # suppress warnings in deprecated msvc compilers + ignore:msvc9?compiler is deprecated From 9079e77d4ca8fedc62c2040f691dfd2e7205217d Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Sun, 21 Aug 2022 16:18:20 +0200 Subject: [PATCH 02/14] Fix, again, finding headers during cross compiling --- distutils/sysconfig.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/distutils/sysconfig.py b/distutils/sysconfig.py index aae9c1b320..4b72204389 100644 --- a/distutils/sysconfig.py +++ b/distutils/sysconfig.py @@ -165,9 +165,8 @@ def _get_python_inc_from_config(plat_specific, spec_prefix): platform Python installation, while the current Python executable is from the build platform installation. """ - if not spec_prefix: - return - return get_config_var('CONF' * plat_specific + 'INCLUDEPY') + if spec_prefix is None: + return get_config_var('CONF' * plat_specific + 'INCLUDEPY') def _get_python_inc_posix_prefix(prefix): From ea04533962eb5ac86630b9cc65e4a5d5c6cfef55 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 13:28:05 -0400 Subject: [PATCH 03/14] Rename _mangle_base to _make_relative and add documentation about its purpose. Ref pypa/distutils#169. --- conftest.py | 2 +- distutils/ccompiler.py | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/conftest.py b/conftest.py index feac1b60a6..018e1075bc 100644 --- a/conftest.py +++ b/conftest.py @@ -154,5 +154,5 @@ def suppress_path_mangle(monkeysession): from distutils import ccompiler monkeysession.setattr( - ccompiler.CCompiler, '_mangle_base', staticmethod(lambda x: x) + ccompiler.CCompiler, '_make_relative', staticmethod(lambda x: x) ) diff --git a/distutils/ccompiler.py b/distutils/ccompiler.py index c8d3b24bc0..6b16879258 100644 --- a/distutils/ccompiler.py +++ b/distutils/ccompiler.py @@ -927,7 +927,7 @@ def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): obj_names = [] for src_name in source_filenames: base, ext = os.path.splitext(src_name) - base = self._mangle_base(base) + base = self._make_relative(base) if ext not in self.src_extensions: raise UnknownFileError( "unknown file type '{}' (from '{}')".format(ext, src_name) @@ -938,9 +938,11 @@ def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): return obj_names @staticmethod - def _mangle_base(base): + def _make_relative(base): """ - For unknown reasons, absolute paths are mangled. + In order to ensure that a filename always honors the + indicated output_dir, make sure it's relative. + Ref python/cpython#37775. """ # Chop off the drive no_drive = os.path.splitdrive(base)[1] From 66c7e69716bed08f5404ac401da508c97b16aa8a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 13:28:38 -0400 Subject: [PATCH 04/14] In _make_relative, remove deprecation warning. Ref pypa/distutils#169. --- distutils/ccompiler.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/distutils/ccompiler.py b/distutils/ccompiler.py index 6b16879258..1c52965eed 100644 --- a/distutils/ccompiler.py +++ b/distutils/ccompiler.py @@ -6,7 +6,6 @@ import sys import os import re -import warnings from distutils.errors import ( CompileError, @@ -947,16 +946,7 @@ def _make_relative(base): # Chop off the drive no_drive = os.path.splitdrive(base)[1] # If abs, chop off leading / - rel = no_drive[os.path.isabs(no_drive) :] - if rel != base: - msg = ( - f"Absolute path {base!r} is being replaced with a " - f"relative path {rel!r} for outputs. This behavior is " - "deprecated. If this behavior is desired, please " - "comment in pypa/distutils#169." - ) - warnings.warn(msg, DeprecationWarning) - return rel + return no_drive[os.path.isabs(no_drive) :] def shared_object_filename(self, basename, strip_dir=0, output_dir=''): assert output_dir is not None From b4839e908ede7aa91821958d7aee83b769dc2ed5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 13:56:49 -0400 Subject: [PATCH 05/14] Extract method for _make_out_path. --- distutils/ccompiler.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/distutils/ccompiler.py b/distutils/ccompiler.py index 1c52965eed..a1346440bc 100644 --- a/distutils/ccompiler.py +++ b/distutils/ccompiler.py @@ -923,18 +923,21 @@ def find_library_file(self, dirs, lib, debug=0): def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): if output_dir is None: output_dir = '' - obj_names = [] - for src_name in source_filenames: - base, ext = os.path.splitext(src_name) - base = self._make_relative(base) - if ext not in self.src_extensions: - raise UnknownFileError( - "unknown file type '{}' (from '{}')".format(ext, src_name) - ) - if strip_dir: - base = os.path.basename(base) - obj_names.append(os.path.join(output_dir, base + self.obj_extension)) - return obj_names + return list( + self._make_out_path(output_dir, strip_dir, src_name) + for src_name in source_filenames + ) + + def _make_out_path(self, output_dir, strip_dir, src_name): + base, ext = os.path.splitext(src_name) + base = self._make_relative(base) + if ext not in self.src_extensions: + raise UnknownFileError( + "unknown file type '{}' (from '{}')".format(ext, src_name) + ) + if strip_dir: + base = os.path.basename(base) + return os.path.join(output_dir, base + self.obj_extension) @staticmethod def _make_relative(base): From ffcf934626d051512de89402124d445d60d23372 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 13:59:47 -0400 Subject: [PATCH 06/14] In _msvccompiler, only override _make_out_path --- distutils/_msvccompiler.py | 42 ++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/distutils/_msvccompiler.py b/distutils/_msvccompiler.py index ade80056e9..785164e240 100644 --- a/distutils/_msvccompiler.py +++ b/distutils/_msvccompiler.py @@ -318,7 +318,7 @@ def initialize(self, plat_name=None): # -- Worker methods ------------------------------------------------ - def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): + def _make_out_path(self, output_dir, strip_dir, src_name): ext_map = { **{ext: self.obj_extension for ext in self.src_extensions}, **{ @@ -326,29 +326,23 @@ def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): for ext in self._rc_extensions + self._mc_extensions }, } - - output_dir = output_dir or '' - - def make_out_path(p): - base, ext = os.path.splitext(p) - if strip_dir: - base = os.path.basename(base) - else: - _, base = os.path.splitdrive(base) - if base.startswith((os.path.sep, os.path.altsep)): - base = base[1:] - try: - # XXX: This may produce absurdly long paths. We should check - # the length of the result and trim base until we fit within - # 260 characters. - return os.path.join(output_dir, base + ext_map[ext]) - except LookupError: - # Better to raise an exception instead of silently continuing - # and later complain about sources and targets having - # different lengths - raise CompileError(f"Don't know how to compile {p}") - - return list(map(make_out_path, source_filenames)) + base, ext = os.path.splitext(src_name) + if strip_dir: + base = os.path.basename(base) + else: + _, base = os.path.splitdrive(base) + if base.startswith((os.path.sep, os.path.altsep)): + base = base[1:] + try: + # XXX: This may produce absurdly long paths. We should check + # the length of the result and trim base until we fit within + # 260 characters. + return os.path.join(output_dir, base + ext_map[ext]) + except LookupError: + # Better to raise an exception instead of silently continuing + # and later complain about sources and targets having + # different lengths + raise CompileError(f"Don't know how to compile {src_name}") def compile( # noqa: C901 self, From d14faf0d29c61373570de9a7d82185752b56e37e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 14:02:34 -0400 Subject: [PATCH 07/14] In _msvccompiler, re-use _make_relative. --- distutils/_msvccompiler.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/distutils/_msvccompiler.py b/distutils/_msvccompiler.py index 785164e240..4d270025bd 100644 --- a/distutils/_msvccompiler.py +++ b/distutils/_msvccompiler.py @@ -330,9 +330,7 @@ def _make_out_path(self, output_dir, strip_dir, src_name): if strip_dir: base = os.path.basename(base) else: - _, base = os.path.splitdrive(base) - if base.startswith((os.path.sep, os.path.altsep)): - base = base[1:] + base = self._make_relative(base) try: # XXX: This may produce absurdly long paths. We should check # the length of the result and trim base until we fit within From e982d51b755c004397303e33df7d2fa2eb09b4d3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 14:15:00 -0400 Subject: [PATCH 08/14] Extract property for mapping src extensions to out extensions. --- distutils/ccompiler.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/distutils/ccompiler.py b/distutils/ccompiler.py index a1346440bc..97551c99fe 100644 --- a/distutils/ccompiler.py +++ b/distutils/ccompiler.py @@ -928,16 +928,22 @@ def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): for src_name in source_filenames ) + @property + def out_extensions(self): + return dict.fromkeys(self.src_extensions, self.obj_extension) + def _make_out_path(self, output_dir, strip_dir, src_name): base, ext = os.path.splitext(src_name) base = self._make_relative(base) - if ext not in self.src_extensions: + try: + new_ext = self.out_extensions[ext] + except LookupError: raise UnknownFileError( "unknown file type '{}' (from '{}')".format(ext, src_name) ) if strip_dir: base = os.path.basename(base) - return os.path.join(output_dir, base + self.obj_extension) + return os.path.join(output_dir, base + new_ext) @staticmethod def _make_relative(base): From c2d2d4b7577fed9f0eb3a45af4a99a7a7b159651 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 14:18:35 -0400 Subject: [PATCH 09/14] Extract property for out_extensions in _msvccompiler --- distutils/_msvccompiler.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/distutils/_msvccompiler.py b/distutils/_msvccompiler.py index 4d270025bd..3da23ede89 100644 --- a/distutils/_msvccompiler.py +++ b/distutils/_msvccompiler.py @@ -318,14 +318,17 @@ def initialize(self, plat_name=None): # -- Worker methods ------------------------------------------------ - def _make_out_path(self, output_dir, strip_dir, src_name): - ext_map = { - **{ext: self.obj_extension for ext in self.src_extensions}, + @property + def out_extensions(self): + return { + **super().out_extensions, **{ ext: self.res_extension for ext in self._rc_extensions + self._mc_extensions }, } + + def _make_out_path(self, output_dir, strip_dir, src_name): base, ext = os.path.splitext(src_name) if strip_dir: base = os.path.basename(base) @@ -335,7 +338,7 @@ def _make_out_path(self, output_dir, strip_dir, src_name): # XXX: This may produce absurdly long paths. We should check # the length of the result and trim base until we fit within # 260 characters. - return os.path.join(output_dir, base + ext_map[ext]) + return os.path.join(output_dir, base + self.out_extensions[ext]) except LookupError: # Better to raise an exception instead of silently continuing # and later complain about sources and targets having From a55e73f2634cec4345127765415f92690bafa5ae Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 14:39:02 -0400 Subject: [PATCH 10/14] Deprecate bcppcompiler. Support for Borland C++ compiler was dropped for compiling Python in python/cpython#66782 (2014) and the borlandc.org web site no longer references a compiler. Best I can tell, this compiler hasn't been released for 22 years. Surely no one is using it. --- distutils/bcppcompiler.py | 10 ++++++++++ pytest.ini | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/distutils/bcppcompiler.py b/distutils/bcppcompiler.py index ee033ed94a..80b6bd8522 100644 --- a/distutils/bcppcompiler.py +++ b/distutils/bcppcompiler.py @@ -13,6 +13,8 @@ import os +import warnings + from distutils.errors import ( DistutilsExecError, CompileError, @@ -26,6 +28,14 @@ from distutils import log +warnings.warn( + "bcppcompiler is deprecated and slated to be removed " + "in the future. Please discontinue use or file an issue " + "with pypa/distutils describing your use case.", + DeprecationWarning, +) + + class BCPPCompiler(CCompiler): """Concrete class that implements an interface to the Borland C/C++ compiler, as defined by the CCompiler abstract class. diff --git a/pytest.ini b/pytest.ini index 3fdd11cc9d..2eb4976d50 100644 --- a/pytest.ini +++ b/pytest.ini @@ -22,5 +22,5 @@ filterwarnings= ignore:The frontend.OptionParser class will be replaced by a subclass of argparse.ArgumentParser in Docutils 0.21 or later.:DeprecationWarning: ignore: The frontend.Option class will be removed in Docutils 0.21 or later.:DeprecationWarning: - # suppress warnings in deprecated msvc compilers - ignore:msvc9?compiler is deprecated + # suppress warnings in deprecated compilers + ignore:(bcpp|msvc9?)compiler is deprecated From 1e89985cf5974fb59f26d0b2e0974484b165a70f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 14:40:36 -0400 Subject: [PATCH 11/14] Remove _msvccompiler._make_out_path. The function is almost entirely redundant to the implementation in the parent class. The only difference is the order in which `strip_dir` is processed, but even there, it doesn't appear as if `strip_dir` is ever True, so take the risk and consolidate behavior. --- distutils/_msvccompiler.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/distutils/_msvccompiler.py b/distutils/_msvccompiler.py index 3da23ede89..729c2dd521 100644 --- a/distutils/_msvccompiler.py +++ b/distutils/_msvccompiler.py @@ -328,23 +328,6 @@ def out_extensions(self): }, } - def _make_out_path(self, output_dir, strip_dir, src_name): - base, ext = os.path.splitext(src_name) - if strip_dir: - base = os.path.basename(base) - else: - base = self._make_relative(base) - try: - # XXX: This may produce absurdly long paths. We should check - # the length of the result and trim base until we fit within - # 260 characters. - return os.path.join(output_dir, base + self.out_extensions[ext]) - except LookupError: - # Better to raise an exception instead of silently continuing - # and later complain about sources and targets having - # different lengths - raise CompileError(f"Don't know how to compile {src_name}") - def compile( # noqa: C901 self, sources, From 610da0bd4e3fb69690b52777e9de51b27933e66c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 14:57:23 -0400 Subject: [PATCH 12/14] In cygwincompiler, re-use object_filenames from ccompiler. --- distutils/cygwinccompiler.py | 37 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/distutils/cygwinccompiler.py b/distutils/cygwinccompiler.py index 63910f2ac8..2c4da5b57e 100644 --- a/distutils/cygwinccompiler.py +++ b/distutils/cygwinccompiler.py @@ -20,7 +20,6 @@ DistutilsPlatformError, CCompilerError, CompileError, - UnknownFileError, ) from distutils.version import LooseVersion, suppress_known_deprecation @@ -242,28 +241,20 @@ def runtime_library_dir_option(self, dir): # -- Miscellaneous methods ----------------------------------------- - def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): - """Adds supports for rc and res files.""" - if output_dir is None: - output_dir = '' - obj_names = [] - for src_name in source_filenames: - # use normcase to make sure '.rc' is really '.rc' and not '.RC' - base, ext = os.path.splitext(os.path.normcase(src_name)) - if ext not in (self.src_extensions + ['.rc', '.res']): - raise UnknownFileError( - "unknown file type '{}' (from '{}')".format(ext, src_name) - ) - if strip_dir: - base = os.path.basename(base) - if ext in ('.res', '.rc'): - # these need to be compiled to object files - obj_names.append( - os.path.join(output_dir, base + ext + self.obj_extension) - ) - else: - obj_names.append(os.path.join(output_dir, base + self.obj_extension)) - return obj_names + def _make_out_path(self, output_dir, strip_dir, src_name): + # use normcase to make sure '.rc' is really '.rc' and not '.RC' + norm_src_name = os.path.normcase(src_name) + return super()._make_out_path(output_dir, strip_dir, norm_src_name) + + @property + def out_extensions(self): + """ + Add support for rc and res files. + """ + return { + **super().out_extensions, + **{ext: ext + self.obj_extension for ext in ('.res', '.rc')}, + } # the same as cygwin plus some additional parameters From 5152a55c9fdbb76f5bfc9035521d7d7ad2054166 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 15:41:03 -0400 Subject: [PATCH 13/14] Add unit tests capturing the expectation --- distutils/sysconfig.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/distutils/sysconfig.py b/distutils/sysconfig.py index 4b72204389..3dd8185f79 100644 --- a/distutils/sysconfig.py +++ b/distutils/sysconfig.py @@ -164,6 +164,16 @@ def _get_python_inc_from_config(plat_specific, spec_prefix): the host platform Python installation, while the current Python executable is from the build platform installation. + + >>> monkeypatch = getfixture('monkeypatch') + >>> gpifc = _get_python_inc_from_config + >>> monkeypatch.setitem(gpifc.__globals__, 'get_config_var', str.lower) + >>> gpifc(False, '/usr/bin/') + >>> gpifc(False, '') + >>> gpifc(False, None) + 'includepy' + >>> gpifc(True, None) + 'confincludepy' """ if spec_prefix is None: return get_config_var('CONF' * plat_specific + 'INCLUDEPY') From d1a76c59f58d3a590121f81beeadcbe438d3d389 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 Aug 2022 15:54:48 -0400 Subject: [PATCH 14/14] Update changelog --- changelog.d/3553.change.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/3553.change.rst diff --git a/changelog.d/3553.change.rst b/changelog.d/3553.change.rst new file mode 100644 index 0000000000..145d7cb3ac --- /dev/null +++ b/changelog.d/3553.change.rst @@ -0,0 +1 @@ +Sync with pypa/distutils@22b9bcf, including fixed cross-compiling support and removing deprecation warning per pypa/distutils#169.