Skip to content

feat(xim): wire exports schema + predicate-driven elfpatch trigger#253

Merged
Sunrisepeak merged 3 commits intomainfrom
feat/elfpatch-exports
May 2, 2026
Merged

feat(xim): wire exports schema + predicate-driven elfpatch trigger#253
Sunrisepeak merged 3 commits intomainfrom
feat/elfpatch-exports

Conversation

@Sunrisepeak
Copy link
Copy Markdown
Member

Summary

xlings-side companion to openxlings/libxpkg#9.

  • PlanNode gains an exports field mirroring libxpkg's ExportsRuntime shape
  • Resolver populates node.exports from pkg->xpm.exports[platform] in both IndexManager and PackageCatalog overloads
  • Installer extends ExecutionContext with runtime_deps_list, build_deps_list, deps_exports (per-runtime-dep slim export info, paths pre-joined to absolute), and self_exports

The new fields plumb metadata end-to-end so libxpkg's elfpatch.lua can do predicate-driven post-install patching (decision tree in libxpkg PR).

Detailed design: docs/plans/2026-05-02-elfpatch-exports-design.md (also shipping in this PR).

Why draft

This PR's xmake.lua needs to bump add_requires("mcpplibs-xpkg 0.0.32")"0.0.33" to actually compile, but 0.0.33 doesn't exist in mcpplibs-index yet. CI is therefore expected to be RED until:

  1. openxlings/libxpkg#9 merges + v0.0.33 tag pushed
  2. mcpplibs-index registers 0.0.33 (sha256 + URL)
  3. This PR pushes the version bump → CI turns green

The companion xim-pkgindex PR (d2learn/xim-pkgindex#104) has been drafted and waits on this PR to merge first.

Validation already done locally

Joint local build (xmake f --local_libxpkg=/path/to/libxpkg/checkout) compiles all source through link stage 93%. Link blocked by pre-existing local env mismatch (ftxui xrepo cache built against glibc, won't link with musl-static — same env issue as #249/#250/#251 had locally; CI doesn't have this issue).

Test plan

Behavior change scope

Phase 1 only — the resolver/installer plumbing. No behavior change until the libxpkg-side elfpatch.lua predicate trigger activates, which only happens once add_requires is at 0.0.33 (post-merge of upstream PR). Existing 4 consumers in xim-pkgindex still call elfpatch.auto({...}) and continue to work via the deprecation alias (debug log only in verbose mode).

Companion to mcpplibs/libxpkg's exports schema addition.

PlanNode gains an `exports` field (mirroring libxpkg ExportsRuntime
shape, kept in xlings's namespace to avoid dragging the upstream
header into every TU). Resolver populates it from
pkg->xpm.exports[platform] in both IndexManager and PackageCatalog
overloads.

Installer extends ExecutionContext with runtime_deps_list,
build_deps_list, deps_exports (per-runtime-dep slim export info), and
self_exports — all paths pre-joined with absolute install_dir so the
Lua side gets ready-to-use absolute paths. The deps_exports lookup
walks plan.nodes to find the dep matching each runtime_deps spec
(name + optional @Version), then composes loader/libdirs from THAT
dep's install_dir.

This is "Phase 1" per docs/plans/2026-05-02-elfpatch-exports-design.md:
zero behavior change. Nothing reads the new fields yet — they're
plumbed end-to-end so phase 2 (elfpatch.lua predicate trigger,
already in libxpkg) can use them on the next libxpkg release.

Validated locally: source compiles to link stage 93% against local
libxpkg (--local_libxpkg=/path); link blocked by pre-existing env
issue (ftxui static lib glibc/musl mismatch in xrepo cache),
unrelated to these changes. CI three-platform will exercise actual link.
@Sunrisepeak Sunrisepeak marked this pull request as ready for review May 2, 2026 12:49
@Sunrisepeak Sunrisepeak merged commit 124a8d1 into main May 2, 2026
3 checks passed
@Sunrisepeak Sunrisepeak deleted the feat/elfpatch-exports branch May 2, 2026 13:05
Sunrisepeak added a commit that referenced this pull request May 2, 2026
…tch (#254)

Bumps VERSION from 0.4.10 to 0.4.11. Highlights since 0.4.10:

  * #253 — Declarative `xpm.<platform>.exports` package metadata, plus
    a predicate-driven elfpatch trigger that lets xlings auto-patch
    consumer ELFs based on what providers declare (rather than
    consumers hardcoding loader paths in their install hooks).

    Schema (provider side, all sub-fields optional):

        xpm = {
            linux = {
                deps    = { runtime = {...}, build = {...} },
                exports = {
                    runtime = {
                        loader  = "lib64/ld-linux-x86-64.so.2",
                        libdirs = { "lib64", "lib" },
                        abi     = "linux-x86_64-glibc",
                    },
                },
                ...
            },
        }

    Only libc-class providers (glibc, musl) need to declare the
    `loader` field; `libdirs` defaults to the {lib64, lib} convention
    and need not be re-declared by 99% of packages.

    Consumer side: xlings reads runtime deps' exports after install
    and applies INTERP / RPATH automatically. The 4 existing
    consumers (binutils / openssl / gcc / d2x) keep working unchanged
    via the libxpkg deprecation alias for the legacy
    `elfpatch.auto({...})` API; they migrate to the new flow on a
    rolling schedule (xim-pkgindex follow-on PRs). Old API drop
    target: 2026-11.

    Internal layered fixes that came along for free:
      - `_RUNTIME.deps_list` was the runtime ∪ build union; new
        `runtime_deps_list` / `build_deps_list` split avoids
        build_dep lib paths leaking into consumer RPATH (latent bug
        from #249).
      - elfpatch's ELF target collector now checks `e_machine` so a
        package that ships both x86_64 and aarch64 binaries doesn't
        get all of them patched on whatever the host happens to be.
      - Static binaries (no PT_INTERP) skip the patchelf fork+exec
        round-trip.

  * libxpkg dependency bumped to mcpplibs-xpkg 0.0.33 (carries the
    schema parser + new elfpatch.lua API).

  * Design doc landed at docs/plans/2026-05-02-elfpatch-exports-design.md.

Migration: 0.4.10 → 0.4.11 is binary-compatible. Existing xpkgs
keep working through the legacy elfpatch deprecation alias. New
behavior (predicate-driven auto-patch) only kicks in once a package
declares `exports.runtime.loader` AND consumers stop calling
`elfpatch.auto(...)` in their install hook — both are opt-in
package metadata changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant