mesonbuild / mesonbuild/meson-python

Duplicate entries in RPATH

Open
#813 4 comments 0 reactions 0 assignees View on GitHub
bug
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.