mesonbuild / mesonbuild/meson-python
Duplicate entries in RPATH
- Dominant language
- Python
- Stars
- 180
- Forks
- 93
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 18
Description
When building with meson python on a recent version of macOS I can no longer import my module.
```python
import gridfire
```
```
ImportError: dlopen(/opt/homebrew/anaconda3/envs/fourdstar/lib/python3.13/site-packages/gridfire.cpython-313-darwin.so, 0x0002): tried: '/opt/homebrew/anaconda3/envs/fourdstar/lib/python3.13/site-packages/gridfire.cpython-313-darwin.so' (duplicate LC_RPATH '@loader_path/.gridfire.mesonpy.libs'), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/anaconda3/envs/fourdstar/lib/python3.13/site-packages/gridfire.cpython-313-darwin.so' (no such file), '/opt/homebrew/anaconda3/envs/fourdstar/lib/python3.13/site-packages/gridfire.cpython-313-darwin.so' (duplicate LC_RPATH '@loader_path/.gridfire.mesonpy.libs')
```
When I inspect the shared object file with otool I see that it contains many duplicate LC_RPATH entries
```bash
otool -l gridfire.cpython-313-darwin.so | grep RPATH -A2
```
```
cmd LC_RPATH
cmdsize 48
path @loader_path/.gridfire.mesonpy.libs (offset 12)
--
cmd LC_RPATH
cmdsize 48
path @loader_path/.gridfire.mesonpy.libs (offset 12)
--
cmd LC_RPATH
cmdsize 48
path @loader_path/.gridfire.mesonpy.libs (offset 12)
--
cmd LC_RPATH
cmdsize 48
path @loader_path/.gridfire.mesonpy.libs (offset 12)
--
cmd LC_RPATH
cmdsize 48
path @loader_path/.gridfire.mesonpy.libs (offset 12)
--
cmd LC_RPATH
cmdsize 48
path @loader_path/.gridfire.mesonpy.libs (offset 12)
--
cmd LC_RPATH
cmdsize 48
path @loader_path/.gridfire.mesonpy.libs (offset 12)
--
cmd LC_RPATH
cmdsize 48
path @loader_path/.gridfire.mesonpy.libs (offset 12)
--
cmd LC_RPATH
cmdsize 48
path @loader_path/.gridfire.mesonpy.libs (offset 12)
--
cmd LC_RPATH
cmdsize 56
path /opt/homebrew/Cellar/openssl@3/3.5.2/lib (offset 12)
--
cmd LC_RPATH
cmdsize 48
path /opt/homebrew/Cellar/xz/5.8.1/lib (offset 12)
--
cmd LC_RPATH
cmdsize 40
path /opt/homebrew/opt/zstd/lib (offset 12)
```
If I manually remove all but one of the rpath instances using install_name_tool
```bash
install_name_tool -delete_rpath @loader_path/.gridfire.mesonpy.libs
```
Then I can import and use my module just fine. Presumably then I could write some somewhat convoluted but not too complex tool to use otool to count the number of duplicate paths and remove them; however, I'm sure this strikes me as a one-way street to a bad time (lack of portability, and just a generally convoluted build step).
> Other discussions (https://github.com/facebook/zstd/issues/4369, https://fenicsproject.discourse.group/t/duplicate-lc-rpath-errors-on-macos-15-4-sequoia/17364) have pinpointed this change in behavior with recent versions of apple's XCode command line tools. Specifically that duplicate lc_rpaths are now treated as an error when loading shared libraries.
My question then is **how do I prevent meson-python from adding all these duplicate paths to the shared object file?**
## Details
- macOS Version 26.0.1
- CLITools version : 26.0.0.0.1.1757719676
- meson-python version: 0.18.0
- meson version: 1.9.1
- clang version: Apple clang 17.0.0 (clang-1700.3.19.1)
## Other details
- I have tried building with `pip install . --no-cache-dir` and `pip install . --no-cache-dir --isolated` and neither of these make a difference.
- I have confirmed the same behavior in my other mesonpy library, fourdst. I see the same behavior there where if I remove all but one of the rpath's using install_name_tool then I can import and use the module just fine
- When I inspect the shared library created by meson (which I belive is generated before meson-python steps in, though I may be mistaken, there are no duplicate lc_rpaths).
```bash
otool -l libgridfire.dylib | grep RPATH -A2
```
```
cmd LC_RPATH
cmdsize 72
path @loader_path/../subprojects/libconstants/src/constants (offset 12)
--
cmd LC_RPATH
cmdsize 64
path @loader_path/../subprojects/libconfig/src/config (offset 12)
--
cmd LC_RPATH
cmdsize 56
path @loader_path/../subprojects/yaml-cpp (offset 12)
--
cmd LC_RPATH
cmdsize 72
path @loader_path/../subprojects/libcomposition/src/composition (offset 12)
--
cmd LC_RPATH
cmdsize 64
path @loader_path/../subprojects/liblogging/src/logging (offset 12)
--
cmd LC_RPATH
cmdsize 56
path @loader_path/../subprojects/libplugin/src (offset 12)
--
cmd LC_RPATH
cmdsize 64
path @loader_path/../subprojects/minizip-ng-4.0.10 (offset 12)
--
cmd LC_RPATH
cmdsize 56
path @loader_path/../subprojects/cvode-7.3.0 (offset 12)
--
cmd LC_RPATH
cmdsize 56
path /opt/homebrew/Cellar/openssl@3/3.5.2/lib (offset 12)
--
cmd LC_RPATH
cmdsize 48
path /opt/homebrew/Cellar/xz/5.8.1/lib (offset 12)
--
cmd LC_RPATH
cmdsize 40
path /opt/homebrew/opt/zstd/lib (offset 12)
```
Originally reported by @tboudreaux in https://github.com/mesonbuild/meson-python/discussions/812
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reproducing the macOS build and comparing otool output for libgridfire.dylib with the installed gridfire.cpython-313-darwin.so. Trace the meson-python build/install path that adds @loader_path/.gridfire.mesonpy.libs and determine where duplicates arise. Done means the installed extension has no duplicate LC_RPATH entries and imports successfully without manual install_name_tool changes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, python
- Domain
- build-system, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 50/100