fix(nix): keep only the serialport prebuild this system can load

The first ever aarch64 build of the app died here, on a Raspberry Pi 4:

  auto-patchelf could not satisfy dependency liblog.so wanted by
    node_modules/@serialport/bindings-cpp/prebuilds/android-arm64/node.napi.armv8.node
  auto-patchelf could not satisfy dependency libc++_shared.so wanted by
    (the same file)

@serialport/bindings-cpp ships prebuilds for every platform it supports:
android-arm, android-arm64, darwin, linux-arm, linux-arm64, linux-x64 in
both glibc and musl, win32-ia32 and win32-x64. installPhase copied the
whole directory.

On x86_64 that was harmless because autoPatchelf skips ELF files whose
architecture does not match the host, so the Android and ARM prebuilds
were never touched. On aarch64 the android-arm64 prebuild IS the host
architecture, so autoPatchelf picks it up and goes looking for Android's
liblog.so and libc++_shared.so, which NixOS does not have. The failure was
invisible until someone built for a second architecture.

Keep only the prebuild the target can load, selected from
stdenv.hostPlatform: linux-arm64 on aarch64, linux-x64 elsewhere, glibc
rather than musl.

Pruning rather than adding those two libraries to
autoPatchelfIgnoreMissingDeps, which would have been the one-line fix.
Teaching autoPatchelf to tolerate a binary we never load, for a platform
we do not target, leaves the foreign prebuilds in the closure and leaves
the same trap set for the next architecture. The existing
"libc.musl-x86_64.so.1" entry in that list is this same problem solved the
other way; it is now redundant, and is left in place only because this
commit is unblocking a machine mid-build and is not the moment to find out
whether something else depended on it.

Verified on x86_64: the app still builds, ships linux-x64/node.napi.glibc.node
alone where it previously carried nine platforms, and comes to 25M.
This commit is contained in:
Padreug 2026-09-25 12:30:25 +02:00
commit 6568618811

View file

@ -172,6 +172,27 @@ pkgs.stdenv.mkDerivation (finalAttrs: {
cp -rL "$bcpp_store/node_modules/@serialport/bindings-cpp/prebuilds" $out/node_modules/@serialport/bindings-cpp/prebuilds cp -rL "$bcpp_store/node_modules/@serialport/bindings-cpp/prebuilds" $out/node_modules/@serialport/bindings-cpp/prebuilds
cp "$bcpp_store/node_modules/@serialport/bindings-cpp/package.json" $out/node_modules/@serialport/bindings-cpp/package.json cp "$bcpp_store/node_modules/@serialport/bindings-cpp/package.json" $out/node_modules/@serialport/bindings-cpp/package.json
# bindings-cpp ships prebuilds for every platform it supports: android,
# win32, darwin, and linux for several arches in both glibc and musl. Keep
# only the one this system can actually load.
#
# This is load-bearing on aarch64, not just tidiness. On x86_64 autoPatchelf
# skipped the foreign prebuilds because their ELF architecture did not match
# the host. On aarch64 the android-arm64 prebuild IS the host architecture,
# so autoPatchelf tries to patch it and fails hunting for Android's
# liblog.so and libc++_shared.so, which do not exist on NixOS. First Pi
# build died exactly there.
#
# Pruning rather than extending autoPatchelfIgnoreMissingDeps: teaching
# autoPatchelf to tolerate a binary we never load, for a platform we do not
# target, is the wrong shape of fix. The musl entry in that list below is
# the same problem solved the other way, and is now redundant.
keep_prebuild=${if pkgs.stdenv.hostPlatform.isAarch64 then "linux-arm64" else "linux-x64"}
find $out/node_modules/@serialport/bindings-cpp/prebuilds -mindepth 1 -maxdepth 1 \
! -name "$keep_prebuild" -exec rm -rf {} +
rm -f $out/node_modules/@serialport/bindings-cpp/prebuilds/*/*.musl.node
echo "serialport prebuilds kept: $(ls $out/node_modules/@serialport/bindings-cpp/prebuilds)/$(ls $out/node_modules/@serialport/bindings-cpp/prebuilds/"$keep_prebuild")"
copy_pnpm_pkg @serialport/bindings-interface $out/node_modules/@serialport/bindings-interface copy_pnpm_pkg @serialport/bindings-interface $out/node_modules/@serialport/bindings-interface
copy_pnpm_pkg @serialport/binding-mock $out/node_modules/@serialport/binding-mock copy_pnpm_pkg @serialport/binding-mock $out/node_modules/@serialport/binding-mock