From 2706ec4577dd31018c7309591725c70a71885a80 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Wed, 30 Jul 2025 17:58:38 +0200 Subject: [PATCH 1/7] ENH: drop empty strings when listing RPATH entries for ELF binaries This entries are not meaningful. This has the additional benefit of not returning an empty string RPATH entry for binaries with RPATH unset. --- mesonpy/_rpath.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonpy/_rpath.py b/mesonpy/_rpath.py index a7cbbb92a..13aedb4f1 100644 --- a/mesonpy/_rpath.py +++ b/mesonpy/_rpath.py @@ -74,7 +74,7 @@ def fix_rpath(filepath: Path, libs_relative_path: str) -> None: def _get_rpath(filepath: Path) -> List[str]: r = subprocess.run(['patchelf', '--print-rpath', os.fspath(filepath)], capture_output=True, text=True) - return r.stdout.strip().split(':') + return [x for x in r.stdout.strip().split(':') if x] def _set_rpath(filepath: Path, rpath: Iterable[str]) -> None: subprocess.run(['patchelf','--set-rpath', ':'.join(rpath), os.fspath(filepath)], check=True) From 497c0183eee1a33267d9bb84bf4ccd865e3722b2 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Sat, 15 Feb 2025 12:03:21 +0100 Subject: [PATCH 2/7] TST: rework the sharedlib-in-package test package This reorganizes the test package to a flatter layout that helps visualizing all the parts involved in the test and introduces an asymmetry between the source layout and the installation layout that demonstrates the bugs in the RPATH handling. --- .../packages/sharedlib-in-package/meson.build | 1 + .../sharedlib-in-package/mypkg/__init__.py | 4 +- .../sharedlib-in-package/mypkg/_examplemod.c | 25 +++--------- .../sharedlib-in-package/mypkg/examplelib.c | 9 ----- .../sharedlib-in-package/mypkg/examplelib.h | 7 ---- .../sharedlib-in-package/mypkg/meson.build | 26 +----------- .../mypkg/sub/examplelib2.h | 7 ---- tests/packages/sharedlib-in-package/src/lib.c | 10 +++++ tests/packages/sharedlib-in-package/src/lib.h | 13 ++++++ .../sharedlib-in-package/src/meson.build | 40 +++++++++++++++++++ .../{mypkg/sub/examplelib2.c => src/sublib.c} | 4 +- .../sharedlib-in-package/src/sublib.h | 13 ++++++ tests/test_wheel.py | 8 ++-- 13 files changed, 91 insertions(+), 76 deletions(-) delete mode 100644 tests/packages/sharedlib-in-package/mypkg/examplelib.c delete mode 100644 tests/packages/sharedlib-in-package/mypkg/examplelib.h delete mode 100644 tests/packages/sharedlib-in-package/mypkg/sub/examplelib2.h create mode 100644 tests/packages/sharedlib-in-package/src/lib.c create mode 100644 tests/packages/sharedlib-in-package/src/lib.h create mode 100644 tests/packages/sharedlib-in-package/src/meson.build rename tests/packages/sharedlib-in-package/{mypkg/sub/examplelib2.c => src/sublib.c} (66%) create mode 100644 tests/packages/sharedlib-in-package/src/sublib.h diff --git a/tests/packages/sharedlib-in-package/meson.build b/tests/packages/sharedlib-in-package/meson.build index 71921cfea..e8f80243c 100644 --- a/tests/packages/sharedlib-in-package/meson.build +++ b/tests/packages/sharedlib-in-package/meson.build @@ -6,4 +6,5 @@ project('sharedlib-in-package', 'c', version: '1.0.0') py = import('python').find_installation(pure: false) +subdir('src') subdir('mypkg') diff --git a/tests/packages/sharedlib-in-package/mypkg/__init__.py b/tests/packages/sharedlib-in-package/mypkg/__init__.py index 857d2e906..e4fbc2a9b 100644 --- a/tests/packages/sharedlib-in-package/mypkg/__init__.py +++ b/tests/packages/sharedlib-in-package/mypkg/__init__.py @@ -45,7 +45,7 @@ def _append_to_sharedlib_load_path(): # end-literalinclude -from ._example import example_prod, example_sum #noqa: E402 +from ._example import prodsum # noqa: E402 -__all__ = ['example_prod', 'example_sum'] +__all__ = ['prodsum'] diff --git a/tests/packages/sharedlib-in-package/mypkg/_examplemod.c b/tests/packages/sharedlib-in-package/mypkg/_examplemod.c index 080e03c18..b4cc3f0c2 100644 --- a/tests/packages/sharedlib-in-package/mypkg/_examplemod.c +++ b/tests/packages/sharedlib-in-package/mypkg/_examplemod.c @@ -4,36 +4,23 @@ #include -#include "examplelib.h" -#include "examplelib2.h" +#include "lib.h" -static PyObject* example_sum(PyObject* self, PyObject *args) +static PyObject* example_prodsum(PyObject* self, PyObject *args) { - int a, b; - if (!PyArg_ParseTuple(args, "ii", &a, &b)) { - return NULL; - } + int a, b, x; - long result = sum(a, b); - - return PyLong_FromLong(result); -} - -static PyObject* example_prod(PyObject* self, PyObject *args) -{ - int a, b; - if (!PyArg_ParseTuple(args, "ii", &a, &b)) { + if (!PyArg_ParseTuple(args, "iii", &a, &b, &x)) { return NULL; } - long result = prod(a, b); + long result = prodsum(a, b, x); return PyLong_FromLong(result); } static PyMethodDef methods[] = { - {"example_prod", (PyCFunction)example_prod, METH_VARARGS, NULL}, - {"example_sum", (PyCFunction)example_sum, METH_VARARGS, NULL}, + {"prodsum", (PyCFunction)example_prodsum, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL}, }; diff --git a/tests/packages/sharedlib-in-package/mypkg/examplelib.c b/tests/packages/sharedlib-in-package/mypkg/examplelib.c deleted file mode 100644 index f486bd7fb..000000000 --- a/tests/packages/sharedlib-in-package/mypkg/examplelib.c +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2022 The meson-python developers -// -// SPDX-License-Identifier: MIT - -#include "sub/mypkg_dll.h" - -MYPKG_DLL int sum(int a, int b) { - return a + b; -} diff --git a/tests/packages/sharedlib-in-package/mypkg/examplelib.h b/tests/packages/sharedlib-in-package/mypkg/examplelib.h deleted file mode 100644 index c09f4f785..000000000 --- a/tests/packages/sharedlib-in-package/mypkg/examplelib.h +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: 2022 The meson-python developers -// -// SPDX-License-Identifier: MIT - -#include "sub/mypkg_dll.h" - -MYPKG_DLL int sum(int a, int b); diff --git a/tests/packages/sharedlib-in-package/mypkg/meson.build b/tests/packages/sharedlib-in-package/mypkg/meson.build index 75904bed6..5cad96363 100644 --- a/tests/packages/sharedlib-in-package/mypkg/meson.build +++ b/tests/packages/sharedlib-in-package/mypkg/meson.build @@ -2,34 +2,10 @@ # # SPDX-License-Identifier: MIT -if meson.get_compiler('c').get_id() in ['msvc', 'clang-cl', 'intel-cl'] - export_dll_args = ['-DMYPKG_DLL_EXPORTS'] - import_dll_args = ['-DMYPKG_DLL_IMPORTS'] -else - export_dll_args = [] - import_dll_args = [] -endif - -example_lib = shared_library( - 'examplelib', - 'examplelib.c', - c_args: export_dll_args, - install: true, - install_dir: py.get_install_dir() / 'mypkg', -) - -example_lib_dep = declare_dependency( - compile_args: import_dll_args, - link_with: example_lib, -) - -subdir('sub') - py.extension_module( '_example', '_examplemod.c', - dependencies: [example_lib_dep, example_lib2_dep], - include_directories: 'sub', + dependencies: lib_dep, install: true, subdir: 'mypkg', install_rpath: '$ORIGIN', diff --git a/tests/packages/sharedlib-in-package/mypkg/sub/examplelib2.h b/tests/packages/sharedlib-in-package/mypkg/sub/examplelib2.h deleted file mode 100644 index 64b6a907e..000000000 --- a/tests/packages/sharedlib-in-package/mypkg/sub/examplelib2.h +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: 2022 The meson-python developers -// -// SPDX-License-Identifier: MIT - -#include "mypkg_dll.h" - -MYPKG_DLL int prod(int a, int b); diff --git a/tests/packages/sharedlib-in-package/src/lib.c b/tests/packages/sharedlib-in-package/src/lib.c new file mode 100644 index 000000000..e4fe14784 --- /dev/null +++ b/tests/packages/sharedlib-in-package/src/lib.c @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: 2022 The meson-python developers +// +// SPDX-License-Identifier: MIT + +#include "lib.h" +#include "sublib.h" + +int prodsum(int a, int b, int x) { + return prod(a, x) + b; +} diff --git a/tests/packages/sharedlib-in-package/src/lib.h b/tests/packages/sharedlib-in-package/src/lib.h new file mode 100644 index 000000000..fb6a02d8a --- /dev/null +++ b/tests/packages/sharedlib-in-package/src/lib.h @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2022 The meson-python developers +// +// SPDX-License-Identifier: MIT + +#if defined(MYPKG_DLL_EXPORTS) + #define EXPORT __declspec(dllexport) +#elif defined(MYPKG_DLL_IMPORTS) + #define EXPORT __declspec(dllimport) +#else + #define EXPORT +#endif + +EXPORT int prodsum(int a, int b, int x); diff --git a/tests/packages/sharedlib-in-package/src/meson.build b/tests/packages/sharedlib-in-package/src/meson.build new file mode 100644 index 000000000..5097a76e9 --- /dev/null +++ b/tests/packages/sharedlib-in-package/src/meson.build @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: 2022 The meson-python developers +# +# SPDX-License-Identifier: MIT + +if meson.get_compiler('c').get_id() in ['msvc', 'clang-cl', 'intel-cl'] + export_dll_args = ['-DMYPKG_DLL_EXPORTS'] + import_dll_args = ['-DMYPKG_DLL_IMPORTS'] +else + export_dll_args = [] + import_dll_args = [] +endif + +sublib = shared_library( + 'sublib', + 'sublib.c', + c_args: export_dll_args, + install: true, + install_dir: py.get_install_dir() / 'mypkg/sub', +) + +sublib_dep = declare_dependency( + compile_args: import_dll_args, + link_with: sublib, +) + +lib = shared_library( + 'lib', + 'lib.c', + dependencies: sublib_dep, + c_args: export_dll_args, + install: true, + install_dir: py.get_install_dir() / 'mypkg', + install_rpath: '$ORIGIN/sub', +) + +lib_dep = declare_dependency( + compile_args: import_dll_args, + link_with: lib, + include_directories: include_directories('.'), +) diff --git a/tests/packages/sharedlib-in-package/mypkg/sub/examplelib2.c b/tests/packages/sharedlib-in-package/src/sublib.c similarity index 66% rename from tests/packages/sharedlib-in-package/mypkg/sub/examplelib2.c rename to tests/packages/sharedlib-in-package/src/sublib.c index 12f5b87a7..facfdf2e1 100644 --- a/tests/packages/sharedlib-in-package/mypkg/sub/examplelib2.c +++ b/tests/packages/sharedlib-in-package/src/sublib.c @@ -2,8 +2,8 @@ // // SPDX-License-Identifier: MIT -#include "mypkg_dll.h" +#include "sublib.h" -MYPKG_DLL int prod(int a, int b) { +int prod(int a, int b) { return a * b; } diff --git a/tests/packages/sharedlib-in-package/src/sublib.h b/tests/packages/sharedlib-in-package/src/sublib.h new file mode 100644 index 000000000..9fc7ae51d --- /dev/null +++ b/tests/packages/sharedlib-in-package/src/sublib.h @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2022 The meson-python developers +// +// SPDX-License-Identifier: MIT + +#if defined(MYPKG_DLL_EXPORTS) + #define EXPORT __declspec(dllexport) +#elif defined(MYPKG_DLL_IMPORTS) + #define EXPORT __declspec(dllimport) +#else + #define EXPORT +#endif + +EXPORT int prod(int a, int b); diff --git a/tests/test_wheel.py b/tests/test_wheel.py index b6f64ceec..3ae6b3afa 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -180,13 +180,11 @@ def test_local_lib(venv, wheel_link_against_local_lib): def test_sharedlib_in_package(venv, wheel_sharedlib_in_package): venv.pip('install', wheel_sharedlib_in_package) - output = venv.python('-c', 'import mypkg; print(mypkg.example_sum(2, 5))') - assert int(output) == 7 - output = venv.python('-c', 'import mypkg; print(mypkg.example_prod(6, 7))') - assert int(output) == 42 + output = venv.python('-c', 'import mypkg; print(mypkg.prodsum(2, 3, 4))') + assert int(output) == 11 -@pytest.mark.skipif(MESON_VERSION < (1, 3, 0), reason='Meson version too old') +@pytest.mark.skipif(MESON_VERSION < (1, 3, 0), reason='meson too old') def test_link_library_in_subproject(venv, wheel_link_library_in_subproject): venv.pip('install', wheel_link_library_in_subproject) output = venv.python('-c', 'import foo; print(foo.example_sum(3, 6))') From c2e7036ba7dc1b0dc692f01e7634f642ad6635fa Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Wed, 30 Jul 2025 14:39:27 +0200 Subject: [PATCH 3/7] TST: use linker flags instead of install_rpath to set the RPATH meson-python does not support `install_rpath` yet and anyhow `install_rpath` is not exposed in the introspection data and thus cannot be set by meson-python when building the Python wheel. Use `link_args` to set the RPATH. --- tests/packages/sharedlib-in-package/mypkg/meson.build | 6 +++++- tests/packages/sharedlib-in-package/src/meson.build | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/packages/sharedlib-in-package/mypkg/meson.build b/tests/packages/sharedlib-in-package/mypkg/meson.build index 5cad96363..ff1d85a05 100644 --- a/tests/packages/sharedlib-in-package/mypkg/meson.build +++ b/tests/packages/sharedlib-in-package/mypkg/meson.build @@ -8,7 +8,11 @@ py.extension_module( dependencies: lib_dep, install: true, subdir: 'mypkg', - install_rpath: '$ORIGIN', + # install_rpath is not exposed in the Meson introspection data in Meson + # versions prior to 1.6.0 and thus cannot be set by meson-python when + # building the Python wheel. Use link_args to set the RPATH. + # install_rpath: '$ORIGIN', + link_args: '-Wl,-rpath,$ORIGIN', ) py.install_sources( diff --git a/tests/packages/sharedlib-in-package/src/meson.build b/tests/packages/sharedlib-in-package/src/meson.build index 5097a76e9..d27a2d396 100644 --- a/tests/packages/sharedlib-in-package/src/meson.build +++ b/tests/packages/sharedlib-in-package/src/meson.build @@ -30,7 +30,11 @@ lib = shared_library( c_args: export_dll_args, install: true, install_dir: py.get_install_dir() / 'mypkg', - install_rpath: '$ORIGIN/sub', + # install_rpath is not exposed in the Meson introspection data in Meson + # versions prior to 1.6.0 and thus cannot be set by meson-python when + # building the Python wheel. Use link_args to set the RPATH. + # install_rpath: '$ORIGIN/sub', + link_args: '-Wl,-rpath,$ORIGIN/sub', ) lib_dep = declare_dependency( From 98c06167e9c351abf950f03aed618274a930eb58 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Wed, 30 Jul 2025 14:45:25 +0200 Subject: [PATCH 4/7] TST: use platform specific anchors in RPATH entries macOS requires using `@loader_path` in place of `$ORIGIN`. --- tests/packages/sharedlib-in-package/meson.build | 2 ++ tests/packages/sharedlib-in-package/mypkg/meson.build | 4 ++-- tests/packages/sharedlib-in-package/src/meson.build | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/packages/sharedlib-in-package/meson.build b/tests/packages/sharedlib-in-package/meson.build index e8f80243c..d311a58a7 100644 --- a/tests/packages/sharedlib-in-package/meson.build +++ b/tests/packages/sharedlib-in-package/meson.build @@ -6,5 +6,7 @@ project('sharedlib-in-package', 'c', version: '1.0.0') py = import('python').find_installation(pure: false) +origin = build_machine.system() == 'darwin' ? '@loader_path' : '$ORIGIN' + subdir('src') subdir('mypkg') diff --git a/tests/packages/sharedlib-in-package/mypkg/meson.build b/tests/packages/sharedlib-in-package/mypkg/meson.build index ff1d85a05..cebf2d523 100644 --- a/tests/packages/sharedlib-in-package/mypkg/meson.build +++ b/tests/packages/sharedlib-in-package/mypkg/meson.build @@ -11,8 +11,8 @@ py.extension_module( # install_rpath is not exposed in the Meson introspection data in Meson # versions prior to 1.6.0 and thus cannot be set by meson-python when # building the Python wheel. Use link_args to set the RPATH. - # install_rpath: '$ORIGIN', - link_args: '-Wl,-rpath,$ORIGIN', + # install_rpath: f'@origin@', + link_args: f'-Wl,-rpath,@origin@', ) py.install_sources( diff --git a/tests/packages/sharedlib-in-package/src/meson.build b/tests/packages/sharedlib-in-package/src/meson.build index d27a2d396..b673ef29e 100644 --- a/tests/packages/sharedlib-in-package/src/meson.build +++ b/tests/packages/sharedlib-in-package/src/meson.build @@ -33,8 +33,8 @@ lib = shared_library( # install_rpath is not exposed in the Meson introspection data in Meson # versions prior to 1.6.0 and thus cannot be set by meson-python when # building the Python wheel. Use link_args to set the RPATH. - # install_rpath: '$ORIGIN/sub', - link_args: '-Wl,-rpath,$ORIGIN/sub', + # install_rpath: f'@origin@/sub', + link_args: f'-Wl,-rpath,@origin@/sub', ) lib_dep = declare_dependency( From 5bb37a7906b127b231f099dab0e1b7a3ea34e916 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Wed, 30 Jul 2025 16:42:59 +0200 Subject: [PATCH 5/7] TST: make RPATH test stricter --- tests/test_wheel.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/test_wheel.py b/tests/test_wheel.py index 3ae6b3afa..264d9decb 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -192,7 +192,7 @@ def test_link_library_in_subproject(venv, wheel_link_library_in_subproject): @pytest.mark.skipif(sys.platform in {'win32', 'cygwin'}, reason='requires RPATH support') -def test_rpath(wheel_link_against_local_lib, tmp_path): +def test_link_against_local_lib_rpath(wheel_link_against_local_lib, tmp_path): artifact = wheel.wheelfile.WheelFile(wheel_link_against_local_lib) artifact.extractall(tmp_path) @@ -200,9 +200,7 @@ def test_rpath(wheel_link_against_local_lib, tmp_path): expected = {f'{origin}/../.link_against_local_lib.mesonpy.libs', 'custom-rpath',} rpath = set(mesonpy._rpath._get_rpath(tmp_path / 'example' / f'_example{EXT_SUFFIX}')) - # Verify that rpath is a superset of the expected one: linking to - # the Python runtime may require additional rpath entries. - assert rpath >= expected + assert rpath == expected @pytest.mark.skipif(sys.platform in {'win32', 'cygwin'}, reason='requires RPATH support') From d3ddf79a66472b9cd99db1b2faba7363f180faee Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Wed, 30 Jul 2025 16:43:24 +0200 Subject: [PATCH 6/7] TST: add another RPATH handling verification test This shows that build RPATHs are not correctly stripped. --- tests/test_wheel.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/test_wheel.py b/tests/test_wheel.py index 264d9decb..7e82ab68f 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -178,6 +178,27 @@ def test_local_lib(venv, wheel_link_against_local_lib): assert int(output) == 3 +@pytest.mark.skipif(sys.platform in {'win32', 'cygwin'}, reason='requires RPATH support') +def test_sharedlib_in_package_rpath(wheel_sharedlib_in_package, tmp_path): + artifact = wheel.wheelfile.WheelFile(wheel_sharedlib_in_package) + artifact.extractall(tmp_path) + + origin = '@loader_path' if sys.platform == 'darwin' else '$ORIGIN' + + rpath = set(mesonpy._rpath._get_rpath(tmp_path / 'mypkg' / f'_example{EXT_SUFFIX}')) + # This RPATH entry should be removed by meson-python but it is not. + build_rpath = {f'{origin}/../src'} + assert rpath == {origin, *build_rpath} + + rpath = set(mesonpy._rpath._get_rpath(tmp_path / 'mypkg' / f'liblib{LIB_SUFFIX}')) + # This RPATH entry should be removed by meson-python but it is not. + build_rpath = {f'{origin}/'} + assert rpath == {f'{origin}/sub', *build_rpath} + + rpath = set(mesonpy._rpath._get_rpath(tmp_path / 'mypkg' / 'sub' / f'libsublib{LIB_SUFFIX}')) + assert rpath == set() + + def test_sharedlib_in_package(venv, wheel_sharedlib_in_package): venv.pip('install', wheel_sharedlib_in_package) output = venv.python('-c', 'import mypkg; print(mypkg.prodsum(2, 3, 4))') From e99ea48589c3d2d80adb43c21d3b516b812c48cb Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Wed, 30 Jul 2025 17:25:38 +0200 Subject: [PATCH 7/7] TST: test RPATH entries added via flags in $LDFLAGS environment variable --- tests/test_wheel.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/test_wheel.py b/tests/test_wheel.py index 7e82ab68f..d118a4e08 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -199,6 +199,22 @@ def test_sharedlib_in_package_rpath(wheel_sharedlib_in_package, tmp_path): assert rpath == set() +@pytest.mark.skipif(sys.platform in {'win32', 'cygwin'}, reason='requires RPATH support') +def test_sharedlib_in_package_rpath_ldflags(package_sharedlib_in_package, tmp_path, monkeypatch): + origin = '@loader_path' if sys.platform == 'darwin' else '$ORIGIN' + extra_rpath = {f'{origin}/test-ldflags', '/usr/lib/test-ldflags'} + ldflags = ' '.join(f'-Wl,-rpath,{p}' for p in extra_rpath) + monkeypatch.setenv('LDFLAGS', ldflags) + + filename = mesonpy.build_wheel(tmp_path) + artifact = wheel.wheelfile.WheelFile(tmp_path / filename) + artifact.extractall(tmp_path) + + for path in f'_example{EXT_SUFFIX}', f'liblib{LIB_SUFFIX}', f'sub/libsublib{LIB_SUFFIX}': + rpath = set(mesonpy._rpath._get_rpath(tmp_path / 'mypkg' / path)) + assert extra_rpath <= rpath + + def test_sharedlib_in_package(venv, wheel_sharedlib_in_package): venv.pip('install', wheel_sharedlib_in_package) output = venv.python('-c', 'import mypkg; print(mypkg.prodsum(2, 3, 4))') @@ -224,6 +240,25 @@ def test_link_against_local_lib_rpath(wheel_link_against_local_lib, tmp_path): assert rpath == expected +@pytest.mark.skipif(sys.platform in {'win32', 'cygwin'}, reason='requires RPATH support') +def test_link_against_local_lib_rpath_ldflags(package_link_against_local_lib, tmp_path, monkeypatch): + origin = '@loader_path' if sys.platform == 'darwin' else '$ORIGIN' + extra_rpath = {f'{origin}/test-ldflags', '/usr/lib/test-ldflags'} + ldflags = ' '.join(f'-Wl,-rpath,{p}' for p in extra_rpath) + monkeypatch.setenv('LDFLAGS', ldflags) + + filename = mesonpy.build_wheel(tmp_path) + artifact = wheel.wheelfile.WheelFile(tmp_path / filename) + artifact.extractall(tmp_path) + + # The RPATH entry relative to $ORIGIN added via $LDFLAGS is + # erroneusly stripped by meson-python. + extra_rpath = {'/usr/lib/test-ldflags',} + + rpath = set(mesonpy._rpath._get_rpath(tmp_path / 'example' / f'_example{EXT_SUFFIX}')) + assert extra_rpath <= rpath + + @pytest.mark.skipif(sys.platform in {'win32', 'cygwin'}, reason='requires RPATH support') def test_uneeded_rpath(wheel_purelib_and_platlib, tmp_path): artifact = wheel.wheelfile.WheelFile(wheel_purelib_and_platlib)