8000 e2fsprogs: defer libblkid/libuuid to util-linux (drop bundled forks) by norrietaylor · Pull Request #366 · gominimal/pkgs · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions packages/e2fsprogs/build.ncl
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
let { Attrs, BuildSpec, Local, OutputBin, OutputData, OutputLib, Source, .. } = import "minimal.ncl" in
let { subsetOf, Attrs, BuildSpec, Local, OutputBin, OutputData, OutputLib, Source, .. } = import "minimal.ncl" in
let base-bootstrap = import "../base-bootstrap/build.ncl" in
let make = import "../make/build.ncl" in
let pkgconf = import "../pkgconf/build.ncl" in
let toolchain = import "../toolchain/build.ncl" in
let glibc = import "../glibc/build.ncl" in
let bash = import "../bash/build.ncl" in
let util-linux = import "../util-linux/build.ncl" in

let version = "1.47.4" in
{
Expand All @@ -16,11 +18,25 @@ let version = "1.47.4" in
} | Source,
base-bootstrap,
make,
pkgconf,
toolchain,
# Build against util-linux's libblkid/libuuid (build.sh configures
# --disable-libblkid --disable-libuuid). Configure detects them via
# pkg-config, needing the headers and .pc files (OutputData) as well as the
# libs, so pull the whole package here — build_deps don't propagate to
# consumers' runtime closures.
util-linux,
],
# e2fsprogs bundles its own older forks of libblkid/libuuid with the same
# soname as util-linux's maintained, symbol-versioned libs; shipping both in
# one image collides. build.sh disables the forks, so mke2fs/e2fsck DT_NEED
# util-linux's libblkid.so.1/libuuid.so.1 at runtime — pull only those two
# outputs, not the whole ~18 MB toolset. Cycle-safe: nothing in util-linux's
# closure uses e2fsprogs.
runtime_deps = [
glibc,
bash,
subsetOf util-linux ["libblkid", "libuuid"],
],

cmd = "./build.sh",
Expand All @@ -31,17 +47,16 @@ let version = "1.47.4" in
outputs = {
chattr = { glob = "usr/bin/chattr" } | OutputBin,
lsattr = { glob = "usr/bin/lsattr" } | OutputBin,
uuidgen = { glob = "usr/bin/uuidgen" } | OutputBin,
compile_et = { glob = "usr/bin/compile_et" } | OutputBin,
mk_cmds = { glob = "usr/bin/mk_cmds" } | OutputBin,
sbins = { glob = "usr/sbin/*" } | OutputBin,

# libblkid/libuuid are intentionally not built here (--disable-libblkid
# --disable-libuuid); util-linux is the sole provider. See build.sh.
libext2fs = { glob = "usr/lib/libext2fs*.so*" } | OutputLib,
libcom_err = { glob = "usr/lib/libcom_err*.so*" } | OutputLib,
libe2p = { glob = "usr/lib/libe2p*.so*" } | OutputLib,
libss = { glob = "usr/lib/libss*.so*" } | OutputLib,
libuuid = { glob = "usr/lib/libuuid*.so*" } | OutputLib,
libblkid = { glob = "usr/lib/libblkid*.so*" } | OutputLib,
libs = { glob = "usr/lib/lib*.so*" } | OutputLib,

includes = { glob = "usr/include/**/*" } | OutputData,
Expand Down
14 changes: 14 additions & 0 deletions packages/e2fsprogs/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,25 @@ export CFLAGS="$MARCH -O2 -pipe -gno-record-gcc-switches -ffile-prefix-map=$(pwd
export LDFLAGS="-Wl,--build-id=none"
export CXXFLAGS="${CFLAGS}"

# Defer libblkid/libuuid (and uuidd) to util-linux, which is injected into this
# build via runtime_deps. e2fsprogs bundles its own older forks of libblkid and
# libuuid with the same soname (libblkid.so.1, libuuid.so.1) as util-linux's
# maintained, symbol-versioned ones; shipping both in a single image makes the
# dynamic loader resolve util-linux's libmount against the wrong libblkid and
# warn "no version information available". Building --disable-libblkid
# --disable-libuuid links e2fsprogs's own tools against util-linux's libs (an
# ABI superset), so the image carries exactly one libblkid/libuuid. Point
# pkg-config at util-linux's .pc files so configure finds them.
export PKG_CONFIG_PATH="/usr/lib/pkgconfig:${PKG_CONFIG_PATH:-}"

./configure --bindir=/usr/bin \
--sbindir=/usr/sbin \
--libdir=/usr/lib \
--enable-elf-shlibs \
--disable-defrag \
--disable-libblkid \
--disable-libuuid \
--disable-uuidd \
--without-libintl-prefix

make -j"$(nproc)"
Expand Down
28 changes: 15 additions & 13 deletions packages/microvm-rootfs/build.ncl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let { subsetOf, BuildSpec, Local, OutputData, .. } = import "minimal.ncl" in
let { BuildSpec, Local, OutputData, .. } = import "minimal.ncl" in
let base = import "../base/build.ncl" in
let e2fsprogs = import "../e2fsprogs/build.ncl" in
let git = import "../git/build.ncl" in
Expand All @@ -8,25 +8,27 @@ let util-linux = import "../util-linux/build.ncl" in
name = "microvm-rootfs",

# A read-only ext4 guest userland for a libkrun microVM. build.sh snapshots
# the runtime closure (base + git + networking tools), prunes build-only bulk,
# and packs an ext4 image loaded as a virtio-blk block device (/dev/vda). The
# guest minimald ships as the initramfs pid-1, mounts this image, and chroots
# into it — there is no standalone init in the image itself. e2fsprogs is
# build-only (mke2fs to pack the image) and its files are removed before
# packing, so the image ships only the runtime closure. git is in the closure
# because the in-guest minimald session bring-up inits a minimal context that
# shells out to git. iproute2 (ip) and util-linux's nsenter give the guest
# network/namespace plumbing — only the nsenter output is pulled from
# util-linux (subsetOf), not its whole ~18 MB toolset.
# the runtime closure, prunes build-only bulk, and packs an ext4 image loaded
# as a virtio-blk block device (/dev/vda). The guest minimald ships as the
# initramfs pid-1, mounts this image, and chroots into it — there is no
# standalone init in the image itself. git is in the closure because the
# in-guest minimald session bring-up inits a minimal context that shells out
# to git. iproute2 (ip) and util-linux's nsenter give the guest
# network/namespace plumbing. e2fsprogs ships mkfs.ext4 (and mke2fs, which
# also packs the image below) so the guest minimald can format the per-VM
# writable volume (/dev/vdb) on first boot; util-linux ships fstrim to reclaim
# space from that volume (its full toolset also carries the nsenter above).
# The mountpoint /var/lib/minimal is staged as an empty dir since the
# read-only root cannot be mkdir'd at runtime.
runtime_deps = [
base,
e2fsprogs,
git,
iproute2,
subsetOf util-linux ["nsenter"],
util-linux,
],
build_deps = [
{ file = "build.sh" } | Local,
e2fsprogs,
],

cmd = "./build.sh",
Expand Down
46 changes: 16 additions & 30 deletions packages/microvm-rootfs/build.sh
BD0
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#!/bin/bash
# Assemble a libkrun microVM guest userland as a read-only ext4 image.
#
# The build sandbox hardlinks this package's runtime closure (base + git + their
# libs) and its build-only deps (e2fsprogs, for mke2fs) into the sandbox root at
# standard paths. We snapshot the userland into a staging tree, drop the
# build-only e2fsprogs files, prune bulk, and pack an ext4 image with mke2fs. The
# image is loaded as a virtio-blk block device (/dev/vda); the guest minimald
# ships as the initramfs pid-1, mounts this image, and chroots into it, so the
# image itself carries no standalone init.
# The build sandbox hardlinks this package's runtime closure (base + git +
# iproute2 + e2fsprogs + util-linux + their libs) into the sandbox root at
# standard paths. We snapshot the userland into a staging tree, prune build-only
# bulk, and pack an ext4 image with mke2fs (from the e2fsprogs runtime closure,
# on PATH). The image is loaded as a virtio-blk block device (/dev/vda); the
# guest minimald ships as the initramfs pid-1, mounts this image, and chroots
# into it, so the image itself carries no standalone init. e2fsprogs (mkfs.ext4)
# and util-linux (fstrim) ship in the image so the guest can format and reclaim
# the per-VM writable volume (/dev/vdb) mounted at /var/lib/minimal.
set -euo pipefail

STAGE="$(pwd)/stage"
Expand All @@ -21,30 +23,14 @@ for d in usr bin sbin lib lib64 etc; do
fi
done

# e2fsprogs is a build-only dependency: it provides mke2fs to pack the image
# below (invoked from the build sandbox PATH, not from $STAGE), but the guest
# never needs it at runtime. Drop its staged files so the runtime image carries
# only the runtime closure. Remove e2fsprogs's sbin tools by name rather than
# nuking usr/sbin wholesale: iproute2 installs `ip` (and ss/tc/bridge) into
# /usr/sbin (SBINDIR=/usr/sbin) and that must survive into the guest. The list
# is the full e2fsprogs sbin set — nothing else in the runtime closure ships
# these names (util-linux is pulled as `subsetOf ["nsenter"]`, so its blkid/
# findfs/fsck/uuidd never reach the image and the e2fsprogs copies must go).
# rm -f tolerates names this e2fsprogs config happens not to build.
for tool in badblocks blkid debugfs dumpe2fs e2freefrag e2fsck e2image e2label \
e2mmpstatus e2scrub e2scrub_all e2undo e4crypt filefrag findfs fsck \
fsck.ext2 fsck.ext3 fsck.ext4 logsave mke2fs mkfs.ext2 mkfs.ext3 \
mkfs.ext4 mklost+found resize2fs tune2fs uuidd; do
rm -f "$STAGE/usr/sbin/$tool"
done
rm -f "$STAGE"/usr/bin/chattr "$STAGE"/usr/bin/lsattr "$STAGE"/usr/bin/uuidgen \
"$STAGE"/usr/bin/compile_et "$STAGE"/usr/bin/mk_cmds
# Note: `libss.so*` (not `libss*.so*`) — the latter also matches openssl's
# libssl.so, which the git runtime closure (curl, openssl) needs at runtime.
rm -f "$STAGE"/usr/lib/libext2fs.so* "$STAGE"/usr/lib/libe2p.so* "$STAGE"/usr/lib/libss.so*

mkdir -p "$STAGE/bin" "$STAGE/sbin"

# Per-VM writable volume mountpoint. The guest minimald mounts /dev/vdb here on
# first boot (after formatting it with mkfs.ext4). The root image is mounted
# read-only, so this directory cannot be created at runtime — it must ship in
# the image or the mount fails with ENOENT/EROFS.
mkdir -p "$STAGE/var/lib/minimal"

# Kernel mountpoints. devtmpfs auto-mounts on /dev at boot (CONFIG_DEVTMPFS_MOUNT)
# — without the directory it fails with "devtmpfs: error mounting -2" and the
# guest has no /dev/vsock node. /proc and /sys are conventional mountpoints.
Expand Down Expand Up @@ -75,7 +61,7 @@ fi

# Fail loudly (not silently with an empty output) if the image tool is absent.
command -v mke2fs >/dev/null || {
echo "ERROR: mke2fs not found on PATH ($PATH) — is e2fsprogs in build_deps?" >&2
echo "ERROR: mke2fs not found on PATH ($PATH) — is e2fsprogs in runtime_deps?" >&2
exit 1
}

Expand Down
0