Skip to content

Stage the last tool in the manifest (fix dropped strace)#3

Merged
lacraig2 merged 4 commits into
mainfrom
fix/manifest-trailing-newline
Jun 8, 2026
Merged

Stage the last tool in the manifest (fix dropped strace)#3
lacraig2 merged 4 commits into
mainfrom
fix/manifest-trailing-newline

Conversation

@lacraig2

@lacraig2 lacraig2 commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

The arch-bundle manifest is built with concatStringsSep "\n" (no trailing newline). The staging loop's while IFS='|' read ... reads the final record into the variables but exits before the loop body runs, so the alphabetically-last tool — strace — was silently dropped from every arch bundle, even though it built fine and appeared in the manifest.

Fix: add the standard || [ -n "$tool_name" ] guard so the last record is staged.

Verified the armel bundle now contains gdbserver ltrace python strace (was missing strace before).

The manifest is built with concatStringsSep "\n", so it has no trailing
newline. The staging loop's `while IFS='|' read ...` reads the final
record into the variables but then exits before the loop body runs,
silently dropping whichever tool sorts last. Tools are emitted in
attribute-name order (gdbserver, ltrace, python, strace), so strace was
missing from every arch bundle even though it built and appeared in the
manifest.

Add the standard `|| [ -n "$tool_name" ]` guard so the last record is
staged. Confirmed the armel bundle now contains gdbserver, ltrace,
python, and strace.
penguin still references the older dylib/arch directory names (arm64,
loongarch, ppc64, ppc64el) in its sysroots staging and guest binary
rpaths, while penguin-tools uses the canonical names (aarch64,
loongarch64, powerpc64, powerpc64le). Add these as compatNames so each
bundle emits both, letting penguin-tools fully replace the dylibs that
hyperfs used to provide without any rename dance on the penguin side.

Verified the arm64 bundle emits igloo_static/arm64 -> aarch64 and
igloo_static/dylibs/arm64 -> aarch64.
@lacraig2

lacraig2 commented Jun 7, 2026

Copy link
Copy Markdown
Contributor Author

Added a second commit (ed20858): emit legacy arch/dylib dir names (arm64, loongarch, ppc64, ppc64el) as compatNames so penguin-tools can replace the dylibs hyperfs provided without any rename on the penguin side. Verified igloo_static/arm64 -> aarch64 and igloo_static/dylibs/arm64 -> aarch64. (Couldn't update the PR title/body — gh pr edit hits the projects-classic deprecation error on this repo.)

copy_dependency resolved each shared library and the interpreter with
readlink -f and staged the file under its *real* name (libc.so,
libstdc++.so.6.0.34, libdw-0.194.so). But binaries reference the
interpreter as ld-musl-<arch>.so.1 and their NEEDED entries use sonames
(libstdc++.so.6, libdw.so.1, ...). musl's loader looks up those literal
names in the runpath, so as staged none of the tools could even launch:
the interpreter ld-musl-<arch>.so.1 was absent, as were several sonames.

Stage the real file as before, but also create a relative symlink under
the referenced name (interpreter name / soname) whenever it differs.
This runs even when the real file was already copied for another
consumer, since one file is reached under multiple names (e.g.
ld-musl-<arch>.so.1 and libc.so both map to libc.so).

Audited the aarch64, armel, powerpc64, and powerpc64le bundles: every
ELF (tools, dylibs, and python's lib-dynload) now has a resolvable
interpreter and a complete NEEDED closure.
@lacraig2

lacraig2 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Third fix on this branch (ffb2a4a): alias bundled deps under the names binaries reference.

copy_dependency staged each shared lib / the interpreter under its real filename (libc.so, libstdc++.so.6.0.34, libdw-0.194.so), but binaries reference the interpreter as ld-musl-<arch>.so.1 and use sonames (libstdc++.so.6, libdw.so.1, …) in NEEDED. musl's loader looks up those literal names, so as staged none of the tools could launch — the interpreter file was missing, as were several sonames. validate_tree didn't catch it (it only checks for /nix/store + dangling links).

Now we also create a relative symlink under the referenced name whenever it differs from the real file. Audited the aarch64, armel, powerpc64, and powerpc64le bundles — every ELF (tools, dylibs, python lib-dynload) now has a resolvable interpreter and a complete NEEDED closure.

This branch now carries three correctness fixes (dropped strace, legacy arch/dylib compat names, dep aliasing). Recommend reviewing/merging as the package-correctness pass before bumping penguin's PENGUIN_TOOLS_VERSION.

Add a check that every staged ELF (tool binaries, dylibs, python's
lib-dynload) can be loaded on the guest from this tree alone: its
interpreter and every NEEDED soname must resolve inside dylibs/<arch>.
This is exactly the class of breakage the preceding dep-aliasing fix
addressed (missing ld-musl-<arch>.so.1 / sonames), which the existing
/nix/store + dangling-symlink checks did not catch. Baking it into the
per-arch bundle build makes CI enforce it across the whole matrix and
prevents regressions. Verified the armel bundle still builds clean.
@lacraig2 lacraig2 merged commit 5da4e68 into main Jun 8, 2026
1 check passed
@lacraig2 lacraig2 deleted the fix/manifest-trailing-newline branch June 8, 2026 04:37
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