From e47cec06b96c3eaa5885aea3ec8e153201bc64c5 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Tue, 7 Jul 2026 18:21:53 +0800 Subject: [PATCH] feat(xim): persist declared xpkg exports to /.xpkg-exports.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Packages can declare runtime metadata (xpm..exports.runtime: loader / abi / libdirs — e.g. glibc declares its dynamic linker precisely so consumers don't hardcode 'lib64/ld-linux-x86-64.so.2'), and xlings already parses and uses it for elfpatch predicates. But the declaration was invisible ON DISK, so downstream consumers (mcpp's toolchain link model) had to re-derive the loader by convention (triple maps + globs). Persist it at install time in the declared RELATIVE form; consumers join against the payload root, so the file stays valid across copies and symlink inheritance. Idempotent, also written for already-installed payloads on their next resolve. --- src/core/xim/installer.cppm | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/core/xim/installer.cppm b/src/core/xim/installer.cppm index 0c0a3b60..93d9472f 100644 --- a/src/core/xim/installer.cppm +++ b/src/core/xim/installer.cppm @@ -1600,6 +1600,28 @@ public: executor.apply_install_stamp_if_empty(ctx); } + // Persist declared exports next to the payload + // (/.xpkg-exports.json) so downstream consumers + // (e.g. mcpp's toolchain link model) read the DECLARED runtime + // metadata (loader/abi/libdirs) instead of re-deriving it by + // convention. Paths are written in their declared RELATIVE form — + // consumers join against the payload root, so the file stays + // valid across copies and symlink inheritance. Idempotent; also + // written for already-installed payloads so existing installs + // gain the file on their next resolve. + if (!node.exports.loader.empty() || !node.exports.abi.empty() + || !node.exports.libdirs.empty()) { + nlohmann::json rt; + if (!node.exports.loader.empty()) rt["loader"] = node.exports.loader; + if (!node.exports.abi.empty()) rt["abi"] = node.exports.abi; + if (!node.exports.libdirs.empty()) rt["libdirs"] = node.exports.libdirs; + nlohmann::json j; + j["runtime"] = std::move(rt); + std::ofstream exportsOs(ctx.install_dir / ".xpkg-exports.json"); + if (exportsOs) exportsOs << j.dump(2) << "\n"; + else log::debug("{}: could not write .xpkg-exports.json", node.name); + } + // Apply elfpatch auto-patching if the install hook enabled it if (!payloadInstalled) { // Ensure binDir is in PATH so elfpatch can find patchelf