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. diff --git a/pytest.ini b/pytest.ini index 892714bfa8..50a7971b71 100644 --- a/pytest.ini +++ b/pytest.ini @@ -60,7 +60,7 @@ filterwarnings= ignore:Setuptools is replacing distutils # suppress warnings in deprecated msvc compilers - ignore:msvc9?compiler is deprecated + ignore:(bcpp|msvc9?)compiler is deprecated ignore:Support for .* in .pyproject.toml. is still .beta. ignore::setuptools.command.editable_wheel.InformationOnly diff --git a/setuptools/_distutils/_msvccompiler.py b/setuptools/_distutils/_msvccompiler.py index ade80056e9..729c2dd521 100644 --- a/setuptools/_distutils/_msvccompiler.py +++ b/setuptools/_distutils/_msvccompiler.py @@ -318,38 +318,16 @@ def initialize(self, plat_name=None): # -- Worker methods ------------------------------------------------ - def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): - 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 }, } - 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)) - def compile( # noqa: C901 self, sources, diff --git a/setuptools/_distutils/bcppcompiler.py b/setuptools/_distutils/bcppcompiler.py index ee033ed94a..80b6bd8522 100644 --- a/setuptools/_distutils/bcppcompiler.py +++ b/setuptools/_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/setuptools/_distutils/ccompiler.py b/setuptools/_distutils/ccompiler.py index c8d3b24bc0..97551c99fe 100644 --- a/setuptools/_distutils/ccompiler.py +++ b/setuptools/_distutils/ccompiler.py @@ -6,7 +6,6 @@ import sys import os import re -import warnings from distutils.errors import ( CompileError, @@ -924,37 +923,39 @@ 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._mangle_base(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 + ) + + @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) + 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 + new_ext) @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] # 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 diff --git a/setuptools/_distutils/cygwinccompiler.py b/setuptools/_distutils/cygwinccompiler.py index 63910f2ac8..2c4da5b57e 100644 --- a/setuptools/_distutils/cygwinccompiler.py +++ b/setuptools/_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 diff --git a/setuptools/_distutils/sysconfig.py b/setuptools/_distutils/sysconfig.py index aae9c1b320..3dd8185f79 100644 --- a/setuptools/_distutils/sysconfig.py +++ b/setuptools/_distutils/sysconfig.py @@ -164,10 +164,19 @@ 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 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):