Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Expected behavior for RPATH handling

Abierto
#903 3 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
45/100
Tipo de issue
Nueva funcionalidad
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
python

Línea de trabajo

Comienza revisando gh-788 y las tablas de escenarios para el comportamiento en Linux y macOS. Usa los paquetes de pruebas existentes, una vez identificados, para cubrir los casos enumerados; se considera terminado cuando el comportamiento esperado está acordado, los escenarios están probados y la tabla se ha añadido como una nueva página de documentación.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

documentation enhancement tests

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).

  • D is 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/../D on Linux or @loader_path/../D on macOS. Extensions in deeper directories require the corresponding relative path to D.
  • E is 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.

Lenguaje dominante
Python
Estrellas
180
Forks
93
Merge medio
18 h 1 min
PR fusionados (30 d)
18

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de mesonbuild/meson-python

Todos los issues de mesonbuild/meson-python

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.