Skip to content

Commit 3efc8e8

Browse files
committed
py3-auditwheel: cherrypick support for alternative library path
Cherrypick: - pypa/auditwheel#597 Which adds support for alternative LD_LIBRARY_PATH such that one can link wheels against 2.28 abi, whilst the system otherwise uses higher abi libraries. A pseudo sysroot.
1 parent aeecc1a commit 3efc8e8

File tree

2 files changed

+276
-1
lines changed

2 files changed

+276
-1
lines changed

py3-auditwheel.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package:
22
name: py3-auditwheel
33
version: "6.4.0"
4-
epoch: 1
4+
epoch: 2
55
description: auditing and relabeling of PEP 600 Linux wheels
66
copyright:
77
- license: MIT
@@ -38,6 +38,10 @@ pipeline:
3838
tag: ${{package.version}}
3939
expected-commit: 93f45cc85f80b7b37525985157eea8496f8bb4f6
4040

41+
- uses: patch
42+
with:
43+
patches: 597.patch
44+
4145
subpackages:
4246
- range: py-versions
4347
name: py${{range.key}}-${{vars.pypi-package}}

py3-auditwheel/597.patch

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
From 0934b8fc91e3f08369d98fb9dcc24a1a5521a132 Mon Sep 17 00:00:00 2001
2+
From: Dimitri John Ledkov <[email protected]>
3+
Date: Wed, 4 Jun 2025 22:30:07 +0100
4+
Subject: [PATCH 1/4] test_analyze_wheel_abi: refactor test with explicit env
5+
6+
Be explicit in the test-case matrix when to set env variable. This
7+
enables to check if environment variable is actually correctly reset.
8+
9+
This commit passes unit tests.
10+
---
11+
tests/integration/test_bundled_wheels.py | 25 ++++++++++++++----------
12+
1 file changed, 15 insertions(+), 10 deletions(-)
13+
14+
diff --git a/tests/integration/test_bundled_wheels.py b/tests/integration/test_bundled_wheels.py
15+
index 046b8fc0..f7bc6296 100644
16+
--- a/tests/integration/test_bundled_wheels.py
17+
+++ b/tests/integration/test_bundled_wheels.py
18+
@@ -1,13 +1,11 @@
19+
from __future__ import annotations
20+
21+
import importlib
22+
-import os
23+
import platform
24+
import sys
25+
import zipfile
26+
from argparse import Namespace
27+
from datetime import datetime, timezone
28+
-from os.path import isabs
29+
from pathlib import Path
30+
from unittest.mock import Mock
31+
32+
@@ -23,69 +21,76 @@
33+
34+
35+
@pytest.mark.parametrize(
36+
- ("file", "external_libs", "exclude"),
37+
+ ("file", "external_libs", "exclude", "env"),
38+
[
39+
(
40+
"cffi-1.5.0-cp27-none-linux_x86_64.whl",
41+
{"libffi.so.5", "libpython2.7.so.1.0"},
42+
frozenset(),
43+
+ None,
44+
),
45+
(
46+
"cffi-1.5.0-cp27-none-linux_x86_64.whl",
47+
set(),
48+
frozenset(["libffi.so.5", "libpython2.7.so.1.0"]),
49+
+ None,
50+
),
51+
(
52+
"cffi-1.5.0-cp27-none-linux_x86_64.whl",
53+
{"libffi.so.5", "libpython2.7.so.1.0"},
54+
frozenset(["libffi.so.noexist", "libnoexist.so.*"]),
55+
+ None,
56+
),
57+
(
58+
"cffi-1.5.0-cp27-none-linux_x86_64.whl",
59+
{"libpython2.7.so.1.0"},
60+
frozenset(["libffi.so.[4,5]"]),
61+
+ None,
62+
),
63+
(
64+
"cffi-1.5.0-cp27-none-linux_x86_64.whl",
65+
{"libffi.so.5", "libpython2.7.so.1.0"},
66+
frozenset(["libffi.so.[6,7]"]),
67+
+ None,
68+
),
69+
(
70+
"cffi-1.5.0-cp27-none-linux_x86_64.whl",
71+
{"libpython2.7.so.1.0"},
72+
frozenset([f"{HERE}/*"]),
73+
+ "LD_LIBRARY_PATH",
74+
),
75+
(
76+
"cffi-1.5.0-cp27-none-linux_x86_64.whl",
77+
{"libpython2.7.so.1.0"},
78+
frozenset(["libffi.so.*"]),
79+
+ None,
80+
),
81+
- ("cffi-1.5.0-cp27-none-linux_x86_64.whl", set(), frozenset(["*"])),
82+
+ ("cffi-1.5.0-cp27-none-linux_x86_64.whl", set(), frozenset(["*"]), None),
83+
(
84+
"python_snappy-0.5.2-pp260-pypy_41-linux_x86_64.whl",
85+
{"libsnappy.so.1"},
86+
frozenset(),
87+
+ None,
88+
),
89+
],
90+
)
91+
-def test_analyze_wheel_abi(file, external_libs, exclude):
92+
+def test_analyze_wheel_abi(file, external_libs, exclude, env):
93+
# If exclude libs contain path, LD_LIBRARY_PATH need to be modified to find the libs
94+
# `lddtree.load_ld_paths` needs to be reloaded for it's `lru_cache`-ed.
95+
- modify_ld_library_path = any(isabs(e) for e in exclude)
96+
97+
with pytest.MonkeyPatch.context() as cp:
98+
- if modify_ld_library_path:
99+
- cp.setenv("LD_LIBRARY_PATH", f"{HERE}")
100+
+ if env:
101+
+ cp.setenv(env, f"{HERE}")
102+
importlib.reload(lddtree)
103+
104+
winfo = analyze_wheel_abi(
105+
Libc.GLIBC, Architecture.x86_64, HERE / file, exclude, False, True
106+
)
107+
assert set(winfo.external_refs["manylinux_2_5_x86_64"].libs) == external_libs, (
108+
- f"{HERE}, {exclude}, {os.environ}"
109+
+ f"{HERE}, {exclude}, {env}"
110+
)
111+
112+
- if modify_ld_library_path:
113+
+ if env:
114+
importlib.reload(lddtree)
115+
116+
117+
118+
From 9f06c60d451a1b92bda33eaca25f882634b9d5e7 Mon Sep 17 00:00:00 2001
119+
From: Dimitri John Ledkov <[email protected]>
120+
Date: Wed, 4 Jun 2025 22:39:22 +0100
121+
Subject: [PATCH 2/4] test_analyze_wheel_abi: add failing test case
122+
123+
Add a failing test case confiring that environment is not being
124+
correctly reset.
125+
---
126+
tests/integration/test_bundled_wheels.py | 6 ++++++
127+
1 file changed, 6 insertions(+)
128+
129+
diff --git a/tests/integration/test_bundled_wheels.py b/tests/integration/test_bundled_wheels.py
130+
index f7bc6296..0c1d2227 100644
131+
--- a/tests/integration/test_bundled_wheels.py
132+
+++ b/tests/integration/test_bundled_wheels.py
133+
@@ -59,6 +59,12 @@
134+
frozenset([f"{HERE}/*"]),
135+
"LD_LIBRARY_PATH",
136+
),
137+
+ (
138+
+ "cffi-1.5.0-cp27-none-linux_x86_64.whl",
139+
+ {"libffi.so.5", "libpython2.7.so.1.0"},
140+
+ frozenset([f"{HERE}/*"]),
141+
+ None,
142+
+ ),
143+
(
144+
"cffi-1.5.0-cp27-none-linux_x86_64.whl",
145+
{"libpython2.7.so.1.0"},
146+
147+
From e2063e3893b01268c5821b47a663334e0ecc8c4e Mon Sep 17 00:00:00 2001
148+
From: Dimitri John Ledkov <[email protected]>
149+
Date: Wed, 4 Jun 2025 22:46:52 +0100
150+
Subject: [PATCH 3/4] test_analyze_wheel_abi: reload and reimport wheel_abi
151+
152+
It seems that in addition to reloading lddtree, reload of
153+
auditwheel.wheel_abi is needed to full flush and reset
154+
analyze_wheel_abi() lru_caches.
155+
---
156+
tests/integration/test_bundled_wheels.py | 8 +++++---
157+
1 file changed, 5 insertions(+), 3 deletions(-)
158+
159+
diff --git a/tests/integration/test_bundled_wheels.py b/tests/integration/test_bundled_wheels.py
160+
index 0c1d2227..7fa01700 100644
161+
--- a/tests/integration/test_bundled_wheels.py
162+
+++ b/tests/integration/test_bundled_wheels.py
163+
@@ -11,6 +11,7 @@
164+
165+
import pytest
166+
167+
+import auditwheel.wheel_abi
168+
from auditwheel import lddtree, main_repair
169+
from auditwheel.architecture import Architecture
170+
from auditwheel.libc import Libc
171+
@@ -87,7 +88,8 @@ def test_analyze_wheel_abi(file, external_libs, exclude, env):
172+
with pytest.MonkeyPatch.context() as cp:
173+
if env:
174+
cp.setenv(env, f"{HERE}")
175+
- importlib.reload(lddtree)
176+
+ importlib.reload(lddtree)
177+
+ importlib.reload(auditwheel.wheel_abi)
178+
179+
winfo = analyze_wheel_abi(
180+
Libc.GLIBC, Architecture.x86_64, HERE / file, exclude, False, True
181+
@@ -96,8 +98,8 @@ def test_analyze_wheel_abi(file, external_libs, exclude, env):
182+
f"{HERE}, {exclude}, {env}"
183+
)
184+
185+
- if env:
186+
- importlib.reload(lddtree)
187+
+ importlib.reload(lddtree)
188+
+ importlib.reload(auditwheel.wheel_abi)
189+
190+
191+
def test_analyze_wheel_abi_pyfpe():
192+
193+
From 496e92ef4e00cbb34e1b18394f0d993eb233b764 Mon Sep 17 00:00:00 2001
194+
From: Dimitri John Ledkov <[email protected]>
195+
Date: Wed, 16 Apr 2025 12:36:33 +0100
196+
Subject: [PATCH 4/4] lddtree: support alternative LD_LIBRARY_PATH called
197+
AUDITWHEEL_LD_LIBRARY_PATH
198+
199+
Sometimes wheels are different only just by shared libraries that are
200+
vendored in. Sometimes the wheel being repaired and the libraries that
201+
need to be vendored in are accessible on the host that was not used
202+
for building the wheel. In such cases, it could be the case that
203+
shared libraries used by python that is executing the auditwheel
204+
script, are incompatible (too old or too new) than those that need to
205+
be vendored.
206+
207+
In such cases, LD_LIBRARY_PATH is not convenient to use, as the python
208+
interpreter for the auditwheel script is crashing.
209+
210+
Add an AUDITWHEEL_LD_LIBRARY_PATH whichis used by lddtree, but
211+
otherwise does not affect the python interpreter executing auditwheel
212+
script.
213+
214+
This helps vendoring in older libraries from an alternative path, into
215+
a wheel built against an older python, whilst otherwise running
216+
auditwheel repair on a modern system with a much newer python. This is
217+
particularly useful when stripping a wheel of vendored libraries, and
218+
repair it again to update the shared library dependencies coming from
219+
an unpacked chroot.
220+
221+
Separately it also helps creating alternative wheels with shared
222+
libraries rebuilt with higher march settings. Given that python
223+
upstream doesn't support loading optimised libraries as has been
224+
implemented and supported in Intel ClearLinux Python which allows one
225+
to have alternative march setting shared library deps.
226+
---
227+
src/auditwheel/lddtree.py | 13 +++++++++++--
228+
tests/integration/test_bundled_wheels.py | 6 ++++++
229+
2 files changed, 17 insertions(+), 2 deletions(-)
230+
231+
diff --git a/src/auditwheel/lddtree.py b/src/auditwheel/lddtree.py
232+
index 44785791..661446a4 100644
233+
--- a/src/auditwheel/lddtree.py
234+
+++ b/src/auditwheel/lddtree.py
235+
@@ -321,8 +321,17 @@ def load_ld_paths(
236+
"""
237+
ldpaths: dict[str, list[str]] = {"conf": [], "env": [], "interp": []}
238+
239+
- # Load up $LD_LIBRARY_PATH.
240+
- env_ldpath = os.environ.get("LD_LIBRARY_PATH")
241+
+ # Load up $AUDITWHEEL_LD_LIBRARY_PATH and $LD_LIBRARY_PATH
242+
+ env_ldpath = ":".join(
243+
+ filter(
244+
+ None,
245+
+ (
246+
+ os.environ.get("AUDITWHEEL_LD_LIBRARY_PATH"),
247+
+ os.environ.get("LD_LIBRARY_PATH"),
248+
+ ),
249+
+ )
250+
+ )
251+
+
252+
if env_ldpath is not None:
253+
if root != "/":
254+
log.warning("ignoring LD_LIBRARY_PATH due to ROOT usage")
255+
diff --git a/tests/integration/test_bundled_wheels.py b/tests/integration/test_bundled_wheels.py
256+
index 7fa01700..97f12487 100644
257+
--- a/tests/integration/test_bundled_wheels.py
258+
+++ b/tests/integration/test_bundled_wheels.py
259+
@@ -60,6 +60,12 @@
260+
frozenset([f"{HERE}/*"]),
261+
"LD_LIBRARY_PATH",
262+
),
263+
+ (
264+
+ "cffi-1.5.0-cp27-none-linux_x86_64.whl",
265+
+ {"libpython2.7.so.1.0"},
266+
+ frozenset([f"{HERE}/*"]),
267+
+ "AUDITWHEEL_LD_LIBRARY_PATH",
268+
+ ),
269+
(
270+
"cffi-1.5.0-cp27-none-linux_x86_64.whl",
271+
{"libffi.so.5", "libpython2.7.so.1.0"},

0 commit comments

Comments
 (0)