Skip to content

Commit 8a45a0c

Browse files
committed
Allow running patchelf even when the environment's bin directory is not on the PATH
1 parent bb18721 commit 8a45a0c

File tree

5 files changed

+30
-10
lines changed

5 files changed

+30
-10
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ While cibuildwheel itself requires a recent Python version to run (we support th
2929
| CPython 3.9 ||||| ✅² |||||| ✅⁵ | N/A | N/A | N/A |
3030
| CPython 3.10 ||||| ✅² |||||| ✅⁵ | N/A | N/A | N/A |
3131
| CPython 3.11 ||||| ✅² |||||| ✅⁵ | N/A | N/A | N/A |
32-
| CPython 3.12 ||||| ✅² |||||| ✅⁵ | N/A | N/A | ✅⁴ |
33-
| CPython 3.13³ ||||| ✅² |||||| ✅⁵ ||| N/A |
34-
| CPython 3.14 ||||| ✅² |||||| ✅⁵ | N/A | N/A | N/A |
32+
| CPython 3.12 ||||| ✅² |||||| ✅⁵ | N/A | N/A | ✅⁴ |
33+
| CPython 3.13³ ||||| ✅² |||||| ✅⁵ | | | ✅⁴ |
34+
| CPython 3.14 ||||| ✅² |||||| ✅⁵ || | N/A |
3535
| PyPy 3.8 v7.3 |||| N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A | N/A | N/A |
3636
| PyPy 3.9 v7.3 |||| N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A | N/A | N/A |
3737
| PyPy 3.10 v7.3 |||| N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A | N/A | N/A |

cibuildwheel/platforms/android.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -508,17 +508,21 @@ def repair_default(
508508
new_soname = soname_with_hash(src_path)
509509
dst_path = libs_dir / new_soname
510510
shutil.copyfile(src_path, dst_path)
511-
call("patchelf", "--set-soname", new_soname, dst_path)
511+
512+
# If cibuildwheel was called without activating its environment, the `bin`
513+
# directory will not be on the PATH.
514+
cibw_bin = Path(sys.executable).parent
515+
call(cibw_bin / "patchelf", "--set-soname", new_soname, dst_path)
512516

513517
for path in paths_to_patch:
514-
call("patchelf", "--replace-needed", old_soname, new_soname, path)
518+
call(cibw_bin / "patchelf", "--replace-needed", old_soname, new_soname, path)
515519
call(
516-
"patchelf",
520+
cibw_bin / "patchelf",
517521
"--set-rpath",
518522
f"${{ORIGIN}}/{relpath(libs_dir, path.parent)}",
519523
path,
520524
)
521-
call(sys.executable, "-m", "wheel", "pack", unpacked_dir, "-d", repaired_wheel_dir)
525+
call(cibw_bin / "wheel", "pack", unpacked_dir, "-d", repaired_wheel_dir)
522526

523527

524528
def elf_file_filter(paths: Iterable[Path]) -> Iterator[tuple[Path, ELFFile]]:

docs/options.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ When setting the options, you can use shell-style globbing syntax, as per [fnmat
6060
| Python 3.11 | cp311-macosx_x86_64<br/>cp311-macosx_universal2<br/>cp311-macosx_arm64 | cp311-win_amd64<br/>cp311-win32<br/>cp311-win_arm64 | cp311-manylinux_x86_64<br/>cp311-manylinux_i686<br/>cp311-musllinux_x86_64<br/>cp311-musllinux_i686 | cp311-manylinux_aarch64<br/>cp311-manylinux_ppc64le<br/>cp311-manylinux_s390x<br/>cp311-manylinux_armv7l<br/>cp311-manylinux_riscv64<br/>cp311-musllinux_aarch64<br/>cp311-musllinux_ppc64le<br/>cp311-musllinux_s390x<br/>cp311-musllinux_armv7l<br/>cp311-musllinux_riscv64 | | | |
6161
| Python 3.12 | cp312-macosx_x86_64<br/>cp312-macosx_universal2<br/>cp312-macosx_arm64 | cp312-win_amd64<br/>cp312-win32<br/>cp312-win_arm64 | cp312-manylinux_x86_64<br/>cp312-manylinux_i686<br/>cp312-musllinux_x86_64<br/>cp312-musllinux_i686 | cp312-manylinux_aarch64<br/>cp312-manylinux_ppc64le<br/>cp312-manylinux_s390x<br/>cp312-manylinux_armv7l<br/>cp312-manylinux_riscv64<br/>cp312-musllinux_aarch64<br/>cp312-musllinux_ppc64le<br/>cp312-musllinux_s390x<br/>cp312-musllinux_armv7l<br/>cp312-musllinux_riscv64 | | | cp312-pyodide_wasm32 |
6262
| Python 3.13 | cp313-macosx_x86_64<br/>cp313-macosx_universal2<br/>cp313-macosx_arm64 | cp313-win_amd64<br/>cp313-win32<br/>cp313-win_arm64 | cp313-manylinux_x86_64<br/>cp313-manylinux_i686<br/>cp313-musllinux_x86_64<br/>cp313-musllinux_i686 | cp313-manylinux_aarch64<br/>cp313-manylinux_ppc64le<br/>cp313-manylinux_s390x<br/>cp313-manylinux_armv7l<br/>cp313-manylinux_riscv64<br/>cp313-musllinux_aarch64<br/>cp313-musllinux_ppc64le<br/>cp313-musllinux_s390x<br/>cp313-musllinux_armv7l<br/>cp313-musllinux_riscv64 | cp313-android_arm64_v8a<br/>cp313-android_x86_64 | cp313-ios_arm64_iphoneos<br/>cp313-ios_arm64_iphonesimulator<br/>cp313-ios_x86_64_iphonesimulator | cp313-pyodide_wasm32 |
63-
| Python 3.14 | cp314-macosx_x86_64<br/>cp314-macosx_universal2<br/>cp314-macosx_arm64 | cp314-win_amd64<br/>cp314-win32<br/>cp314-win_arm64 | cp314-manylinux_x86_64<br/>cp314-manylinux_i686<br/>cp314-musllinux_x86_64<br/>cp314-musllinux_i686 | cp314-manylinux_aarch64<br/>cp314-manylinux_ppc64le<br/>cp314-manylinux_s390x<br/>cp314-manylinux_armv7l<br/>cp314-manylinux_riscv64<br/>cp314-musllinux_aarch64<br/>cp314-musllinux_ppc64le<br/>cp314-musllinux_s390x<br/>cp314-musllinux_armv7l<br/>cp314-musllinux_riscv64 | cp314-ios_arm64_iphoneos<br/>cp314-ios_arm64_iphonesimulator<br/>cp314-ios_x86_64_iphonesimulator | |
63+
| Python 3.14 | cp314-macosx_x86_64<br/>cp314-macosx_universal2<br/>cp314-macosx_arm64 | cp314-win_amd64<br/>cp314-win32<br/>cp314-win_arm64 | cp314-manylinux_x86_64<br/>cp314-manylinux_i686<br/>cp314-musllinux_x86_64<br/>cp314-musllinux_i686 | cp314-manylinux_aarch64<br/>cp314-manylinux_ppc64le<br/>cp314-manylinux_s390x<br/>cp314-manylinux_armv7l<br/>cp314-manylinux_riscv64<br/>cp314-musllinux_aarch64<br/>cp314-musllinux_ppc64le<br/>cp314-musllinux_s390x<br/>cp314-musllinux_armv7l<br/>cp314-musllinux_riscv64 | cp314-android_arm64_v8a<br/>cp314-android_x86_64 | cp314-ios_arm64_iphoneos<br/>cp314-ios_arm64_iphonesimulator<br/>cp314-ios_x86_64_iphonesimulator | |
6464
| PyPy3.8 v7.3 | pp38-macosx_x86_64<br/>pp38-macosx_arm64 | pp38-win_amd64 | pp38-manylinux_x86_64<br/>pp38-manylinux_i686 | pp38-manylinux_aarch64 | | | |
6565
| PyPy3.9 v7.3 | pp39-macosx_x86_64<br/>pp39-macosx_arm64 | pp39-win_amd64 | pp39-manylinux_x86_64<br/>pp39-manylinux_i686 | pp39-manylinux_aarch64 | | | |
6666
| PyPy3.10 v7.3 | pp310-macosx_x86_64<br/>pp310-macosx_arm64 | pp310-win_amd64 | pp310-manylinux_x86_64<br/>pp310-manylinux_i686 | pp310-manylinux_aarch64 | | | |

docs/platforms.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,6 @@ It also requires the following commands to be on the `PATH`:
205205

206206
* `curl`
207207
* `java` (or set the `JAVA_HOME` environment variable)
208-
* `patchelf` (if the wheel links against any external libraries)
209208

210209
### Android version compatibility
211210

@@ -214,6 +213,11 @@ minimum supported [API level](https://developer.android.com/tools/releases/platf
214213
for generated wheels. This will default to the minimum API level of the selected Python
215214
version.
216215

216+
If the [`repair-wheel-command`](options.md#repair-wheel-command) adds any libraries to
217+
the wheel, then `ANDROID_API_LEVEL` must be at least 24. This is already the default
218+
when building for Python 3.14 and later, but you may need to set it when building for
219+
Python 3.13.
220+
217221
### Build frontend support
218222

219223
Android builds only support the `build` frontend. In principle, support for the

test/test_android.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import os
22
import platform
33
import re
4+
import sys
45
from dataclasses import dataclass
6+
from pathlib import Path
57
from shutil import rmtree
68
from subprocess import CalledProcessError
79
from textwrap import dedent
@@ -353,11 +355,21 @@ def test_libcxx(tmp_path, capfd):
353355
project_dir = tmp_path / "project"
354356
output_dir = tmp_path / "output"
355357

358+
# cibuildwheel should be able to run `patchelf` and `wheel` even when its
359+
# environment's `bin` directory is not on the PATH.
360+
non_venv_path = ":".join(
361+
item for item in os.environ["PATH"].split(":") if Path(item) != Path(sys.executable).parent
362+
)
363+
356364
# A C++ package should include libc++, and the extension module should be able to
357365
# find it using DT_RUNPATH.
358366
new_c_project(setup_py_extension_args_add="language='c++'").generate(project_dir)
359367
script = 'import spam; print(", ".join(f"{s}: {spam.filter(s)}" for s in ["ham", "spam"]))'
360-
cp313_test_env = {**cp313_env, "CIBW_TEST_COMMAND": f"python -c '{script}'"}
368+
cp313_test_env = {
369+
**cp313_env,
370+
"CIBW_TEST_COMMAND": f"python -c '{script}'",
371+
"PATH": non_venv_path,
372+
}
361373

362374
# Including external libraries requires API level 24.
363375
with pytest.raises(CalledProcessError):

0 commit comments

Comments
 (0)