Skip to content

Commit aeefe34

Browse files
committed
2 parents a36b7ba + 6c0427b commit aeefe34

13 files changed

+97
-38
lines changed

newsfragments/4871.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Restored implicit distutils.ccompiler import for g-ir-scanner.

newsfragments/4876.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Restore `distutils.ccompiler.compiler_class` -- by :user:`Avasam`
+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
from .compilers.C import msvc
22

3+
__all__ = ["MSVCCompiler"]
4+
35
MSVCCompiler = msvc.Compiler

setuptools/_distutils/ccompiler.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
from .compilers.C import base
22
from .compilers.C.base import (
3-
CompileError,
4-
LinkError,
3+
compiler_class,
54
gen_lib_options,
65
gen_preprocess_options,
76
get_default_compiler,
87
new_compiler,
98
show_compilers,
109
)
10+
from .compilers.C.errors import CompileError, LinkError
1111

1212
__all__ = [
1313
'CompileError',
1414
'LinkError',
15+
'compiler_class',
1516
'gen_lib_options',
1617
'gen_preprocess_options',
1718
'get_default_compiler',

setuptools/_distutils/command/build.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,12 @@
1010
from collections.abc import Callable
1111
from typing import ClassVar
1212

13+
from ..ccompiler import show_compilers
1314
from ..core import Command
1415
from ..errors import DistutilsOptionError
1516
from ..util import get_platform
1617

1718

18-
def show_compilers():
19-
from ..ccompiler import show_compilers
20-
21-
show_compilers()
22-
23-
2419
class build(Command):
2520
description = "build everything needed to install"
2621

setuptools/_distutils/command/build_clib.py

+1-9
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,12 @@
1919
from distutils._log import log
2020
from typing import ClassVar
2121

22+
from ..ccompiler import new_compiler, show_compilers
2223
from ..core import Command
2324
from ..errors import DistutilsSetupError
2425
from ..sysconfig import customize_compiler
2526

2627

27-
def show_compilers():
28-
from ..ccompiler import show_compilers
29-
30-
show_compilers()
31-
32-
3328
class build_clib(Command):
3429
description = "build C/C++ libraries used by Python extensions"
3530

@@ -93,9 +88,6 @@ def run(self) -> None:
9388
if not self.libraries:
9489
return
9590

96-
# Yech -- this is cut 'n pasted from build_ext.py!
97-
from ..ccompiler import new_compiler
98-
9991
self.compiler = new_compiler(
10092
compiler=self.compiler, dry_run=self.dry_run, force=self.force
10193
)

setuptools/_distutils/command/build_ext.py

+1-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from typing import ClassVar
1717

1818
from .._modified import newer_group
19+
from ..ccompiler import new_compiler, show_compilers
1920
from ..core import Command
2021
from ..errors import (
2122
CCompilerError,
@@ -34,12 +35,6 @@
3435
extension_name_re = re.compile(r'^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$')
3536

3637

37-
def show_compilers():
38-
from ..ccompiler import show_compilers
39-
40-
show_compilers()
41-
42-
4338
class build_ext(Command):
4439
description = "build C/C++ extensions (compile/link to build directory)"
4540

@@ -303,8 +298,6 @@ def finalize_options(self) -> None: # noqa: C901
303298
raise DistutilsOptionError("parallel should be an integer")
304299

305300
def run(self) -> None: # noqa: C901
306-
from ..ccompiler import new_compiler
307-
308301
# 'self.extensions', as supplied by setup.py, is a list of
309302
# Extension instances. See the documentation for Extension (in
310303
# distutils.extension) for details.

setuptools/_distutils/command/check.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ def _check_rst_data(self, data):
141141
document.note_source(source_path, -1)
142142
try:
143143
parser.parse(data, document)
144-
except AttributeError as e:
144+
except (AttributeError, TypeError) as e:
145145
reporter.messages.append((
146146
-1,
147147
f'Could not finish the parsing: {e}.',

setuptools/_distutils/command/config.py

-2
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,6 @@ def try_run(
258258
built from 'body' and 'headers'. Return true on success, false
259259
otherwise.
260260
"""
261-
from ..ccompiler import CompileError, LinkError
262-
263261
self._check_compiler()
264262
try:
265263
src, obj, exe = self._link(

setuptools/_distutils/compilers/C/unix.py

+14
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,20 @@ class Compiler(base.Compiler):
158158
dylib_lib_extension = ".dll"
159159
dylib_lib_format = "cyg%s%s"
160160

161+
def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs):
162+
"""Remove standard library path from rpath"""
163+
libraries, library_dirs, runtime_library_dirs = super()._fix_lib_args(
164+
libraries, library_dirs, runtime_library_dirs
165+
)
166+
libdir = sysconfig.get_config_var('LIBDIR')
167+
if (
168+
runtime_library_dirs
169+
and libdir.startswith("/usr/lib")
170+
and (libdir in runtime_library_dirs)
171+
):
172+
runtime_library_dirs.remove(libdir)
173+
return libraries, library_dirs, runtime_library_dirs
174+
161175
def preprocess(
162176
self,
163177
source: str | os.PathLike[str],

setuptools/_distutils/tests/test_build_ext.py

+59-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import contextlib
2+
import glob
23
import importlib
3-
import os
4+
import os.path
45
import platform
56
import re
67
import shutil
78
import site
9+
import subprocess
810
import sys
911
import tempfile
1012
import textwrap
13+
import time
1114
from distutils import sysconfig
1215
from distutils.command.build_ext import build_ext
1316
from distutils.core import Distribution
@@ -51,6 +54,9 @@ def user_site_dir(request):
5154
site.USER_BASE = orig_user_base
5255
build_ext.USER_BASE = orig_user_base
5356

57+
if sys.platform == 'cygwin':
58+
time.sleep(1)
59+
5460

5561
@contextlib.contextmanager
5662
def safe_extension_import(name, path):
@@ -86,11 +92,35 @@ class TestBuildExt(TempdirManager):
8692
def build_ext(self, *args, **kwargs):
8793
return build_ext(*args, **kwargs)
8894

89-
def test_build_ext(self):
95+
@pytest.mark.parametrize("copy_so", [False])
96+
def test_build_ext(self, copy_so):
9097
missing_compiler_executable()
9198
copy_xxmodule_c(self.tmp_dir)
9299
xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
93100
xx_ext = Extension('xx', [xx_c])
101+
if sys.platform != "win32":
102+
if not copy_so:
103+
xx_ext = Extension(
104+
'xx',
105+
[xx_c],
106+
library_dirs=['/usr/lib'],
107+
libraries=['z'],
108+
runtime_library_dirs=['/usr/lib'],
109+
)
110+
elif sys.platform == 'linux':
111+
libz_so = {
112+
os.path.realpath(name) for name in glob.iglob('/usr/lib*/libz.so*')
113+
}
114+
libz_so = sorted(libz_so, key=lambda lib_path: len(lib_path))
115+
shutil.copyfile(libz_so[-1], '/tmp/libxx_z.so')
116+
117+
xx_ext = Extension(
118+
'xx',
119+
[xx_c],
120+
library_dirs=['/tmp'],
121+
libraries=['xx_z'],
122+
runtime_library_dirs=['/tmp'],
123+
)
94124
dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
95125
dist.package_dir = self.tmp_dir
96126
cmd = self.build_ext(dist)
@@ -109,10 +139,13 @@ def test_build_ext(self):
109139
sys.stdout = old_stdout
110140

111141
with safe_extension_import('xx', self.tmp_dir):
112-
self._test_xx()
142+
self._test_xx(copy_so)
143+
144+
if sys.platform == 'linux' and copy_so:
145+
os.unlink('/tmp/libxx_z.so')
113146

114147
@staticmethod
115-
def _test_xx():
148+
def _test_xx(copy_so):
116149
import xx
117150

118151
for attr in ('error', 'foo', 'new', 'roj'):
@@ -127,6 +160,28 @@ def _test_xx():
127160
assert isinstance(xx.Null(), xx.Null)
128161
assert isinstance(xx.Str(), xx.Str)
129162

163+
if sys.platform == 'linux':
164+
so_headers = subprocess.check_output(
165+
["readelf", "-d", xx.__file__], universal_newlines=True
166+
)
167+
import pprint
168+
169+
pprint.pprint(so_headers)
170+
rpaths = [
171+
rpath
172+
for line in so_headers.split("\n")
173+
if "RPATH" in line or "RUNPATH" in line
174+
for rpath in line.split()[2][1:-1].split(":")
175+
]
176+
if not copy_so:
177+
pprint.pprint(rpaths)
178+
# Linked against a library in /usr/lib{,64}
179+
assert "/usr/lib" not in rpaths and "/usr/lib64" not in rpaths
180+
else:
181+
# Linked against a library in /tmp
182+
assert "/tmp" in rpaths
183+
# The import is the real test here
184+
130185
def test_solaris_enable_shared(self):
131186
dist = Distribution({'name': 'xx'})
132187
cmd = self.build_ext(dist)
+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
import importlib
2+
13
from .compilers.C import unix
24

35
UnixCCompiler = unix.Compiler
6+
7+
# ensure import of unixccompiler implies ccompiler imported
8+
# (pypa/setuptools#4871)
9+
importlib.import_module('distutils.ccompiler')

setuptools/_distutils/util.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -315,13 +315,14 @@ def execute(
315315
verbose: bool = False,
316316
dry_run: bool = False,
317317
) -> None:
318-
"""Perform some action that affects the outside world (eg. by
319-
writing to the filesystem). Such actions are special because they
320-
are disabled by the 'dry_run' flag. This method takes care of all
321-
that bureaucracy for you; all you have to do is supply the
318+
"""
319+
Perform some action that affects the outside world (e.g. by
320+
writing to the filesystem). Such actions are special because they
321+
are disabled by the 'dry_run' flag. This method handles that
322+
complication; simply supply the
322323
function to call and an argument tuple for it (to embody the
323-
"external action" being performed), and an optional message to
324-
print.
324+
"external action" being performed) and an optional message to
325+
emit.
325326
"""
326327
if msg is None:
327328
msg = f"{func.__name__}{args!r}"

0 commit comments

Comments
 (0)