diff --git a/distutils/compat/__init__.py b/distutils/compat/__init__.py new file mode 100644 index 00000000..b7be7267 --- /dev/null +++ b/distutils/compat/__init__.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +from .py38 import removeprefix + + +def consolidate_linker_args(args: list[str]) -> str: + """ + Ensure the return value is a string for backward compatibility. + + Retain until at least 2024-10-31. + """ + + if not all(arg.startswith('-Wl,') for arg in args): + return args + return '-Wl,' + ','.join(removeprefix(arg, '-Wl,') for arg in args) diff --git a/distutils/compat/py38.py b/distutils/compat/py38.py new file mode 100644 index 00000000..0af38140 --- /dev/null +++ b/distutils/compat/py38.py @@ -0,0 +1,23 @@ +import sys + +if sys.version_info < (3, 9): + + def removesuffix(self, suffix): + # suffix='' should not call self[:-0]. + if suffix and self.endswith(suffix): + return self[: -len(suffix)] + else: + return self[:] + + def removeprefix(self, prefix): + if self.startswith(prefix): + return self[len(prefix) :] + else: + return self[:] +else: + + def removesuffix(self, suffix): + return self.removesuffix(suffix) + + def removeprefix(self, prefix): + return self.removeprefix(prefix) diff --git a/distutils/tests/test_unixccompiler.py b/distutils/tests/test_unixccompiler.py index f17edf2f..6f05fa69 100644 --- a/distutils/tests/test_unixccompiler.py +++ b/distutils/tests/test_unixccompiler.py @@ -4,6 +4,7 @@ import sys import unittest.mock as mock from distutils import sysconfig +from distutils.compat import consolidate_linker_args from distutils.errors import DistutilsPlatformError from distutils.unixccompiler import UnixCCompiler from distutils.util import _clear_cached_macosx_ver @@ -149,10 +150,10 @@ def gcv(v): return 'yes' sysconfig.get_config_var = gcv - assert self.cc.rpath_foo() == [ + assert self.cc.rpath_foo() == consolidate_linker_args([ '-Wl,--enable-new-dtags', '-Wl,-rpath,/foo', - ] + ]) def gcv(v): if v == 'CC': @@ -161,10 +162,10 @@ def gcv(v): return 'yes' sysconfig.get_config_var = gcv - assert self.cc.rpath_foo() == [ + assert self.cc.rpath_foo() == consolidate_linker_args([ '-Wl,--enable-new-dtags', '-Wl,-rpath,/foo', - ] + ]) # GCC non-GNULD sys.platform = 'bar' @@ -189,10 +190,10 @@ def gcv(v): return 'yes' sysconfig.get_config_var = gcv - assert self.cc.rpath_foo() == [ + assert self.cc.rpath_foo() == consolidate_linker_args([ '-Wl,--enable-new-dtags', '-Wl,-rpath,/foo', - ] + ]) # non-GCC GNULD sys.platform = 'bar' @@ -204,10 +205,10 @@ def gcv(v): return 'yes' sysconfig.get_config_var = gcv - assert self.cc.rpath_foo() == [ + assert self.cc.rpath_foo() == consolidate_linker_args([ '-Wl,--enable-new-dtags', '-Wl,-rpath,/foo', - ] + ]) # non-GCC non-GNULD sys.platform = 'bar' diff --git a/distutils/unixccompiler.py b/distutils/unixccompiler.py index a54481c0..0248bde8 100644 --- a/distutils/unixccompiler.py +++ b/distutils/unixccompiler.py @@ -22,6 +22,7 @@ import sys from . import sysconfig +from .compat import consolidate_linker_args from ._log import log from ._macos_compat import compiler_fixup from ._modified import newer @@ -315,11 +316,11 @@ def runtime_library_dir_option(self, dir: str) -> str | list[str]: # For all compilers, `-Wl` is the presumed way to pass a # compiler option to the linker if sysconfig.get_config_var("GNULD") == "yes": - return [ + return consolidate_linker_args([ # Force RUNPATH instead of RPATH "-Wl,--enable-new-dtags", "-Wl,-rpath," + dir, - ] + ]) else: return "-Wl,-R" + dir