Skip to content

Commit b3f17d2

Browse files
authored
Merge pull request pypa/distutils#160 from DWesl/patch-2
ENH: Don't add system library directories to rpath
2 parents b53777a + d4310a4 commit b3f17d2

File tree

4 files changed

+75
-5
lines changed

4 files changed

+75
-5
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ jobs:
122122
python${{ matrix.python }}-pip,
123123
gcc-core,
124124
gcc-g++,
125+
zlib-devel,
125126
ncompress
126127
git
127128
- name: Install tox using pip

distutils/command/check.py

Lines changed: 1 addition & 1 deletion
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}.',

distutils/compilers/C/unix.py

Lines changed: 14 additions & 0 deletions
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],

distutils/tests/test_build_ext.py

Lines changed: 59 additions & 4 deletions
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)

0 commit comments

Comments
 (0)