Applies Buildroot's target-finalize cleanup to a harvested per-package
target tree.
Why this exists
Buildroot doesn't stop packages installing headers, static archives, docs and
manpages — it lets them, then deletes the lot in one target-finalize recipe
at the end of a full build, stripping every binary in $(TARGET_DIR) on the
way past.
NBPR never reaches that step. It runs <pkg>-dirclean, <pkg> and
<pkg>-legal-info, then harvests per-package/<pkg>/target/ directly. That's
deliberate — target-finalize first rsyncs every package into a shared
TARGET_DIR, which would destroy the per-package scoping
NBPR.Buildroot.FilesList exists to preserve — but it meant artefacts shipped
unstripped binaries and static archives into a rootfs whose own files
Buildroot had stripped.
Measured on real artefacts: nbpr_chrony 1815 KB → 423 KB, nbpr_libcap
508 KB → 60 KB, nbpr_pps_tools 103 KB → 37 KB.
So this reproduces the same recipe against one package's harvested tree.
Because it runs after the files-list copy, its removals overlap the narrower
runtime filter in FilesList (and that filter's shell twin in the container
backend): the filter avoids copying the obvious cases, this catches the rest.
That filter stays — besides pre-filtering, it's the only thing cleaning
staging/, which nothing here touches.
Shape
The whole thing is emitted as one POSIX shell fragment, and every decision
that depends on Buildroot's configuration is made in that shell by grepping
the resolved .config. That's not squeamishness about Elixir — it's that the
config only becomes meaningful after make olddefconfig, and for the
container backend the resolved file lives inside the container where Elixir
can't reach it. Deciding in shell keeps one definition of "finalize" for both
backends instead of one per backend.
What it doesn't do
staging/ is left alone, matching Buildroot — whose staging-finalize does
nothing but create a symlink. Headers, .la files and unstripped libraries
all survive there by design, because the point of the staging slice is
cross-compiling consumer NIFs against the package. What trimming staging does
get comes from FilesList, not here.
Stripping
Gated on BR2_STRIP_strip=y, which is what decides whether Buildroot's own
STRIPCMD is strip or /bin/true. Buildroot's exclusions are reproduced,
and they matter:
*.ko— kernel modules stop working if stripped like an executable, and NBPR ships them (kernel_modules:packages).ld-*.so*,libpthread*.so*—--strip-debugonly, so valgrind and pthread-aware gdb keep working.
BR2_STRIP_EXCLUDE_DIRS / BR2_STRIP_EXCLUDE_FILES are deliberately not
implemented. No stock Nerves system sets either, and translating them into
find clauses is the kind of code that looks right and silently strips
something it shouldn't. Instead, if a system sets one, stripping is skipped
entirely with a warning — safe, obvious, and a clear prompt to implement it
properly when something actually needs it.
Summary
Functions
Returns a POSIX shell fragment that finalizes target_dir.
Functions
Returns a POSIX shell fragment that finalizes target_dir.
host_bin_dir is the per-package host/bin holding the cross *-strip, and
config_path the resolved Buildroot .config — both as seen by whoever runs
the fragment, so the container backend passes container paths and the shell
backend host ones.