Expected behavior for RPATH handling
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 45/100
- Issue 类型
- 功能
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- python
调研方向
首先查看 gh-788 以及 Linux 和 macOS 行为的场景表。确定现有测试包后,使用它们覆盖列出的情况;完成的标准是预期行为已达成一致、场景已完成测试,并且该表已作为新的文档页面添加。
由索引模型根据 Issue 内容生成。
描述
Writing this up as a new issue while in the middle of reviewing gh-788. This is quite complicated, and we don't have good test coverage. So this issue aims to lay out as many relevant scenarios as possible, with the expected behavior on Linux and macOS for each case. Reviewing that is a lot easier than reviewing code for which we don't yet have tests.
Once we agree that the behavior is right, we can decide on test packages to add. Also, I'd like to add a table like this in a new page in the docs; I think the audience for this is relatively small, but when you do need this info, you really need it - and I don't know of any other source where this is covered well.
The tables explain desired behavior of extension modules in a wheel built with meson-python (i.e., before auditwheel or delocate repair).
Dis the wheel's relocated-library directory, named.<distribution_name>.mesonpy.libs. The examples assume it is beside the directory containing the extension, so the extension reaches it through$ORIGIN/../Don Linux or@loader_path/../Don macOS. Extensions in deeper directories require the corresponding relative path toD.Eis an absolute external dependency prefix, outside the source and build trees. It remains available after installation.- The tables list the paths relevant to each scenario. “None” means no project-specific search paths; unrelated external runtime paths remain unchanged.
Installed code must work after removing the source and build directories, without loader-path environment overrides. The empty-RUNPATH scenario explicitly requires a loader failure instead. Build-path removal assumes Meson provides the necessary metadata, or has already taken care of the removal itself.
All scenarios must also work when building another wheel from the same build directory, without changing the resulting search paths
Shared behavior
| Scenario | Linux extension paths | macOS extension LC_RPATH paths | Notes |
|---|---|---|---|
| Extension without dependencies on additional project-built shared libraries | None | None | Basic regression, ensure nothing is added. |
One library is moved into D |
$ORIGIN/../D |
@loader_path/../D |
Update its consumer to find the library at its installed location. |
Two libraries from different build directories move into the same D |
$ORIGIN/../D, once |
@loader_path/../D, one command |
Add the destination search path once, without duplicates. |
Extension → first library → second library; both libraries are moved into D |
$ORIGIN/../D |
@loader_path/../D |
The first library also needs $ORIGIN/. on Linux or @loader_path/. on macOS. Repair the entire dependency chain, not just the extension. |
| Extension → sibling library, using a platform-correct installation path | $ORIGIN |
@loader_path |
Keep the sibling library discoverable after installation. |
Extension → sibling library → second library in sub/ |
$ORIGIN |
@loader_path |
The sibling library needs $ORIGIN/sub on Linux or @loader_path/sub on macOS to load its own dependency. |
Extension directly depends on both a sibling library and a library in sub/; an existing working layout |
$ORIGIN, $ORIGIN/sub |
@loader_path, @loader_path/sub |
Preserve both paths and continued functionality. Neither library needs its own project search path. |
Extension depends on two relocated libraries in D and an in-package library in private/ |
$ORIGIN/private, $ORIGIN/../D |
@loader_path/private, @loader_path/../D |
Keep working paths to both groups. |
An external library is linked by absolute filename or through -L/-l, with an explicit runtime path supplied by -Wl,-rpath,E/lib |
E/lib |
E/lib |
Preserve the explicitly requested external runtime path for either linking form. The -L directory alone does not imply a path that must be preserved. |
Link flags explicitly request a relative runtime path with -Wl,-rpath,$ORIGIN/user (Linux) or -Wl,-rpath,@loader_path/user (macOS), and an absolute path with -Wl,-rpath,E/lib; other libraries are relocated into D |
$ORIGIN/user, E/lib, $ORIGIN/../D |
@loader_path/user, E/lib, @loader_path/../D |
Preserve the requested relative or absolute paths and add the relocation path. This applies whether the flags come from target linker arguments, environment flags, or pkg-config, and also to bundled libraries needing path updates. A binary need not request both relative and absolute paths. |
install_rpath requests $ORIGIN/one:$ORIGIN/two:$ORIGIN/one on Linux, or @loader_path/one:@loader_path/two:@loader_path/one on macOS |
$ORIGIN/one, $ORIGIN/two |
@loader_path/one, @loader_path/two, as separate commands |
Keep each distinct installation path once. |
| The same path appears in both build and installation metadata | $ORIGIN/keep, once |
@loader_path/keep, once |
The explicit installation request takes precedence over removal of the same build path. |
| A build-only path remains, but no installation path is requested | None | None | Remove the build-only path without leaving padding or accidental empty entries. See the intentional empty-RUNPATH exception below. |
Linux: RPATH and RUNPATH
RPATH and RUNPATH are ELF dynamic tags, also used on platforms other than Linux; their search behavior depends on the dynamic loader. The runtime descriptions below refer to Linux with glibc: RUNPATH takes precedence over RPATH in the same binary, and applies only to direct dependencies, whereas RPATH supports transitive lookup. Linux with musl does not make that transitivity distinction: both tag types can supply paths for indirect dependencies. Preserving the input tag type remains a requirement, even where conversion would not change the observed runtime behavior. macOS uses Mach-O LC_RPATH commands and has no RPATH/RUNPATH distinction.
| Scenario | Linux extension paths | macOS extension LC_RPATH paths | Notes |
|---|---|---|---|
| Editing paths in a binary containing either RPATH or RUNPATH | Updated paths in the original tag type | Not applicable | Do not silently convert RPATH to RUNPATH or vice versa. |
Explicit installation paths compete with preserved paths; private/ and external/ contain libraries with the same SONAME |
$ORIGIN/private before $ORIGIN/external; preserve input tag type |
Not applicable | Search installation paths first, so the library in private/ takes precedence over the same-SONAME library in external/. |
| Executable → middle library → leaf library; the executable uses transitive RPATH | DT_RPATH: $ORIGIN/lib |
Not applicable | Both libraries are in lib/ and have no project paths. The executable's RPATH must resolve the indirect dependency. |
| Executable → middle library → leaf library; the executable uses direct-dependency RUNPATH | DT_RUNPATH: $ORIGIN/lib |
Not applicable | The middle library needs $ORIGIN for its leaf dependency. Preserve its input tag type; the entire chain must load. |
| Executable uses RPATH; the middle library uses RUNPATH and must update its path to the installed leaf | DT_RPATH: $ORIGIN/middle |
Not applicable | Middle: DT_RUNPATH containing $ORIGIN/../installed-leaf. Preserve both tag types and load the complete chain. |
| Executable uses RUNPATH; the middle library uses RPATH and must update its path to the installed leaf | DT_RUNPATH: $ORIGIN/middle |
Not applicable | Middle: DT_RPATH containing $ORIGIN/../installed-leaf. Preserve both tag types and load the complete chain. |
| One binary contains both tags, pointing at different copies of the same library | DT_RUNPATH: $ORIGIN/runpath-choice; optional inactive DT_RPATH: $ORIGIN/rpath-choice |
Not applicable | Load the library found through RUNPATH; the competing copy reachable only through RPATH must be ignored. Remove build-only RUNPATH entries without merging the ignored RPATH into it. The ignored RPATH may be retained or removed. |
| Both tags exist, but RUNPATH is empty | Empty DT_RUNPATH tag; optional inactive DT_RPATH: $ORIGIN/rpath-choice |
Not applicable | Preserve the empty RUNPATH so RPATH stays ignored. A dependency available only through RPATH must remain undiscoverable: this deliberately requires a loader failure. |
| Removing build-only paths leaves no paths | No RPATH or RUNPATH tag | Not applicable | Remove the tag instead of leaving an empty search entry. The deliberately empty RUNPATH above is an explicit exception. |
macOS: LC_RPATH
These cases exercise separate Mach-O load commands and install_name_tool behavior.
| Scenario | macOS extension LC_RPATH paths | Notes |
|---|---|---|
Legacy installation paths use literal $ORIGIN, including on macOS |
@loader_path; also @loader_path/sub when required |
Preserve working behavior with native macOS anchors, including subdirectory paths. Literal $ORIGIN is not a usable macOS result. |
| Several installation paths are requested | @loader_path/one, @loader_path/two, as separate commands |
Do not encode the macOS paths as one colon-containing command. |
An extension already contains two LC_RPATH commands for @loader_path/dupa; this path should be preserved and no libraries are relocated |
@loader_path/dupa, one command |
Reduce the two existing commands to one, even when no other path edits are needed. |
An extension contains two LC_RPATH commands for the same build-only path, @loader_path/dupa |
None | Remove every copy of @loader_path/dupa successfully. |
Keep existing paths containing spaces, parentheses, and trailing whitespace; add @loader_path/new path/(library) and remove the build-only @loader_path/remove this (build) |
@loader_path/some path/(library), @loader_path/trailing (one trailing space), @loader_path/new path/(library) |
Preserve the exact retained strings, add the new path once, and remove @loader_path/remove this (build) completely. |
Full disclosure: I started this table by hand, then did a lot of testing and synthesis with an AI tool (Codex/Astra), which turned up a few more cases that are new rows in the table above (in particular for mixed RPATH/RUNPATH, after I prompted it for that - we've had issues with that before, e.g. gh-125). Text is mine, and reviewed/polished as carefully as I could for clarity and correctness. I'll comment on the testing results of trying to test gh-788 for these behaviors on that PR, rather than here.
- 主要语言
- Python
- 星标
- 181
- 派生
- 94
- 平均合并
- 18 小时 23 分钟
- 30 天内合并 PR
- 12
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
mesonbuild/meson-python 的其他 Issue
-
documentation
难度 2/5 1-3 小时 新手友好度 65/100
mesonbuild/meson-python#541 ·
维护者通常 1 天内回复
-
documentation
难度 2/5 1-3 小时 新手友好度 65/100
mesonbuild/meson-python#473 · 6 条评论 ·
维护者通常 1 天内回复
-
难度 3/5 1-2 天 新手友好度 52/100
mesonbuild/meson-python#871 · 7 条评论 · 1 个 reaction ·
维护者通常 1 天内回复
-
pip install overrides existing build configuration可能已有人在做 @Alvaro-Kothe 于 126 天前认领。 未关闭question
难度 3/5 1-2 天 新手友好度 68/100
mesonbuild/meson-python#851 · 6 条评论 ·
维护者通常 1 天内回复
-
enhancement
难度 4/5 3-5 天 新手友好度 45/100
mesonbuild/meson-python#848 · 3 条评论 ·
维护者通常 1 天内回复
查看 mesonbuild/meson-python 的全部 Issue
相似的 Issue
-
Issue Triage-Needed
难度 2/5 1-3 小时 新手友好度 68/100
pulp/pulp_container#2581 ·
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 85/100
521xueweihan/HelloGitHub#4040 ·
-
bug
难度 2/5 1-3 小时 新手友好度 64/100
ClanGenOfficial/clangen#6313 ·
维护者通常 2 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 84/100
维护者通常 1 天内回复
-
bug(trainer): CustomTrainer func_args with non literal values fail inside the TrainJob可能已有人在做 @avanishkasar 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复