Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Don't add system library directories to rpath #160

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ jobs:
python${{ matrix.python }}-tox,
gcc-core,
gcc-g++,
zlib-devel,
ncompress
git
- name: Run tests
Expand Down
2 changes: 1 addition & 1 deletion distutils/command/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def _check_rst_data(self, data):
document.note_source(source_path, -1)
try:
parser.parse(data, document)
except AttributeError as e:
except (AttributeError, TypeError) as e:
reporter.messages.append((
-1,
f'Could not finish the parsing: {e}.',
Expand Down
1 change: 1 addition & 0 deletions distutils/compat/py38.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def removeprefix(self, prefix):
return self[len(prefix) :]
else:
return self[:]

else:

def removesuffix(self, suffix):
Expand Down
63 changes: 59 additions & 4 deletions distutils/tests/test_build_ext.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import contextlib
import glob
import importlib
import os
import os.path
import platform
import re
import shutil
import site
import subprocess
import sys
import tempfile
import textwrap
import time
from distutils import sysconfig
from distutils.command.build_ext import build_ext
from distutils.core import Distribution
Expand Down Expand Up @@ -55,6 +58,9 @@ def user_site_dir(request):
site.USER_BASE = orig_user_base
build_ext.USER_BASE = orig_user_base

if sys.platform == 'cygwin':
time.sleep(1)


@contextlib.contextmanager
def safe_extension_import(name, path):
Expand Down Expand Up @@ -90,11 +96,35 @@ class TestBuildExt(TempdirManager):
def build_ext(self, *args, **kwargs):
return build_ext(*args, **kwargs)

def test_build_ext(self):
@pytest.mark.parametrize("copy_so", [False])
def test_build_ext(self, copy_so):
missing_compiler_executable()
copy_xxmodule_c(self.tmp_dir)
xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
xx_ext = Extension('xx', [xx_c])
if sys.platform != "win32":
if not copy_so:
xx_ext = Extension(
'xx',
[xx_c],
library_dirs=['/usr/lib'],
libraries=['z'],
runtime_library_dirs=['/usr/lib'],
)
elif sys.platform == 'linux':
libz_so = {
os.path.realpath(name) for name in glob.iglob('/usr/lib*/libz.so*')
}
libz_so = sorted(libz_so, key=lambda lib_path: len(lib_path))
shutil.copyfile(libz_so[-1], '/tmp/libxx_z.so')

xx_ext = Extension(
'xx',
[xx_c],
library_dirs=['/tmp'],
libraries=['xx_z'],
runtime_library_dirs=['/tmp'],
)
dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
dist.package_dir = self.tmp_dir
cmd = self.build_ext(dist)
Expand All @@ -113,10 +143,13 @@ def test_build_ext(self):
sys.stdout = old_stdout

with safe_extension_import('xx', self.tmp_dir):
self._test_xx()
self._test_xx(copy_so)

if sys.platform == 'linux' and copy_so:
os.unlink('/tmp/libxx_z.so')

@staticmethod
def _test_xx():
def _test_xx(copy_so):
import xx

for attr in ('error', 'foo', 'new', 'roj'):
Expand All @@ -131,6 +164,28 @@ def _test_xx():
assert isinstance(xx.Null(), xx.Null)
assert isinstance(xx.Str(), xx.Str)

if sys.platform == 'linux':
so_headers = subprocess.check_output(
["readelf", "-d", xx.__file__], universal_newlines=True
)
import pprint

pprint.pprint(so_headers)
rpaths = [
rpath
for line in so_headers.split("\n")
if "RPATH" in line or "RUNPATH" in line
for rpath in line.split()[2][1:-1].split(":")
]
if not copy_so:
pprint.pprint(rpaths)
# Linked against a library in /usr/lib{,64}
assert "/usr/lib" not in rpaths and "/usr/lib64" not in rpaths
else:
# Linked against a library in /tmp
assert "/tmp" in rpaths
# The import is the real test here

def test_solaris_enable_shared(self):
dist = Distribution({'name': 'xx'})
cmd = self.build_ext(dist)
Expand Down
14 changes: 14 additions & 0 deletions distutils/unixccompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,20 @@ class UnixCCompiler(CCompiler):
dylib_lib_extension = ".dll"
dylib_lib_format = "cyg%s%s"

def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs):
"""Remove standard library path from rpath"""
libraries, library_dirs, runtime_library_dirs = super()._fix_lib_args(
libraries, library_dirs, runtime_library_dirs
)
libdir = sysconfig.get_config_var('LIBDIR')
if (
runtime_library_dirs
and libdir.startswith("/usr/lib")
and (libdir in runtime_library_dirs)
):
runtime_library_dirs.remove(libdir)
return libraries, library_dirs, runtime_library_dirs
DWesl marked this conversation as resolved.
Show resolved Hide resolved

def preprocess(
self,
source,
Expand Down
Loading