Skip to content

Commit 57cb47c

Browse files
committed
ENH: always require patchelf on Linux
patchelf is required on Linux when executables, libraries, or extension modules in the package link to a shared library itself also distributed with the package. To determine whether patchelf is required, the project to be built into a wheel needs to be configured. Because ephemeral build directories are used, the project needs to be configured a second time when the wheel is actually built. For all but the simplest projects the time spent in ``meson setup`` is significant. This patch removes the check and thus the requirement for configuring the project twice, and assumes that patchelf is always required on Linux: dependency on the patchelf package is added when a suitable patchelf executable is not found in the environment. Configuring the project requires ninja to be available. When ninja is not available the it was assumed that patchelf is required. The check was also implemented incorrectly and did not actually check whether a shared library is included in the wheel. Therefore, this patch changes whether the patchelf package is installed only when projects that do not include any native code components that are build on systems where ninja is available an patchelf is not. The impact of this change is largest for pure Python projects. To measure it, I timed the time required to build wheels for meson-python itself with ninja and patchelf installed or not in the environment: ninja patchelf main this ----- -------- ------------ ------------ no no 6.5 +- 0.3 s 6.5 +- 0.3 s yes no 6.0 +- 0.3 s 5.8 +- 0.3 s yes yes 5.6 +- 0.6 s 5.6 +- 0.6 s Timings are from 7 consecutive runs of ``python -m pip wheel``. All the required dependencies are in the pip cache. Using ``python -m build -w`` the build time is around 9 seconds and is dominated by the time requires to install pip in the isolated build environment, so the run time differences less pronounced. Scatter in the data is dominated by the network round trip times of pip checking the package index for the dependencies latest versions. Even in the least favorable case, this change does not have a negative impact on the wheel build time. Fixes #485.
1 parent d463b25 commit 57cb47c

File tree

2 files changed

+6
-28
lines changed

2 files changed

+6
-28
lines changed

mesonpy/__init__.py

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,27 +1038,14 @@ def build_sdist(
10381038

10391039

10401040
@_pyproject_hook
1041-
def get_requires_for_build_wheel(
1042-
config_settings: Optional[Dict[str, str]] = None,
1043-
) -> List[str]:
1041+
def get_requires_for_build_wheel(config_settings: Optional[Dict[str, str]] = None) -> List[str]:
10441042
dependencies = []
10451043

10461044
if os.environ.get('NINJA') is None and _env_ninja_command() is None:
10471045
dependencies.append(_depstr.ninja)
10481046

1049-
if sys.platform.startswith('linux'):
1050-
# we may need patchelf
1051-
if not shutil.which('patchelf'):
1052-
# patchelf not already accessible on the system
1053-
if _env_ninja_command() is not None:
1054-
# we have ninja available, so we can run Meson and check if the project needs patchelf
1055-
with _project(config_settings) as project:
1056-
if not project.is_pure:
1057-
dependencies.append(_depstr.patchelf)
1058-
else:
1059-
# we can't check if the project needs patchelf, so always add it
1060-
# XXX: wait for https://github.com/mesonbuild/meson/pull/10779
1061-
dependencies.append(_depstr.patchelf)
1047+
if sys.platform.startswith('linux') and not shutil.which('patchelf'):
1048+
dependencies.append(_depstr.patchelf)
10621049

10631050
return dependencies
10641051

tests/test_pep517.py

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,10 @@
1212

1313
import mesonpy
1414

15-
from mesonpy._util import chdir
1615

17-
from .conftest import package_dir
18-
19-
20-
@pytest.mark.parametrize('package', ['pure', 'library'])
2116
@pytest.mark.parametrize('system_patchelf', ['patchelf', None], ids=['patchelf', 'nopatchelf'])
2217
@pytest.mark.parametrize('ninja', [None, '1.8.1', '1.8.3'], ids=['noninja', 'oldninja', 'newninja'])
23-
def test_get_requires_for_build_wheel(monkeypatch, package, system_patchelf, ninja):
18+
def test_get_requires_for_build_wheel(monkeypatch, package_pure, system_patchelf, ninja):
2419
# the NINJA environment variable affects the ninja executable lookup and breaks the test
2520
monkeypatch.delenv('NINJA', raising=False)
2621

@@ -51,14 +46,10 @@ def run(cmd: List[str], *args: object, **kwargs: object) -> subprocess.Completed
5146
if not ninja_available:
5247
expected |= {mesonpy._depstr.ninja}
5348

54-
if (
55-
system_patchelf is None and sys.platform.startswith('linux')
56-
and (not ninja_available or (ninja_available and package != 'pure'))
57-
):
49+
if system_patchelf is None and sys.platform.startswith('linux'):
5850
expected |= {mesonpy._depstr.patchelf}
5951

60-
with chdir(package_dir / package):
61-
assert set(mesonpy.get_requires_for_build_wheel()) == expected
52+
assert set(mesonpy.get_requires_for_build_wheel()) == expected
6253

6354

6455
def test_invalid_config_settings(capsys, package_pure, tmp_path_session):

0 commit comments

Comments
 (0)