The fourth closure round asked for libaio and thin-provisioning-tools, both wanted by lvm2 alone. thin-provisioning-tools is Rust now, so a language runtime was arriving through a fourth-order dependency. Nothing in the repository wants `lvm2`. Checked across every .PKGINFO: cryptsetup wants device-mapper, and device-mapper is the other package this same source produces. Dropping the sub-package removed both entries and the Rust question with them. The measurement is the argument, and it went the other way an hour earlier. tcl, unixodbc and libmicrohttpd each cost zero new packages, so building them beat dropping sub-packages. This one costs a language runtime, so dropping wins. The rule is not to prefer either -- it is to measure each time. device-mapper had also picked up the host's libselinux, silently. Seventh package to do it, second found by reading binaries rather than by a build. 35 packages, then 19, then 2, then 0. --- FR --- Le quatrième tour de fermeture réclamait libaio et thin-provisioning-tools, tous deux voulus par lvm2 seul. thin-provisioning-tools est en Rust désormais : un environnement de langage arrivait par une dépendance de quatrième ordre. Rien dans le dépôt ne veut `lvm2`. Vérifié sur chaque .PKGINFO : cryptsetup veut device-mapper, et device-mapper est l'autre paquet que cette même source produit. Écarter le sous-paquet a retiré les deux entrées et la question Rust avec elles. La mesure est l'argument, et elle avait tranché dans l'autre sens une heure plus tôt. tcl, unixodbc et libmicrohttpd coûtaient zéro paquet nouveau : les bâtir valait mieux qu'écarter des sous-paquets. Celui-ci coûte un environnement de langage : écarter gagne. La règle n'est de préférer ni l'un ni l'autre — c'est de mesurer chaque fois. device-mapper avait aussi ramassé le libselinux de l'hôte, en silence. Septième paquet à le faire, deuxième trouvé en lisant des binaires plutôt que par une compilation. 35 paquets, puis 19, puis 2, puis 0. Assisted-by: Claude Opus 5
76 lines
3.7 KiB
Bash
Executable file
76 lines
3.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# lvm2: only device-mapper is wanted, and the lvm2 half costs a Rust toolchain.
|
|
#
|
|
# The chain that puts this PKGBUILD in stage 1 is
|
|
# systemd -> cryptsetup -> device-mapper, and device-mapper is one of the two
|
|
# packages this source produces. Nothing in the repository asks for `lvm2`
|
|
# itself -- checked across every .PKGINFO, the only consumer of device-mapper
|
|
# is cryptsetup, and the only consumer of lvm2 is lvm2's own dependency on
|
|
# device-mapper.
|
|
#
|
|
# What the lvm2 half brings with it:
|
|
#
|
|
# thin-provisioning-tools -- rewritten in Rust. Its prepare() stops on
|
|
# `error: Error loading target specification: Could not find
|
|
# specification for target "host-tuple"`, and behind that stands cargo,
|
|
# a crates.io fetch and the whole Rust bootstrap question. This port
|
|
# already declined that detour once, for python-cryptography.
|
|
#
|
|
# libaio -- and not usefully. Ubuntu renamed its library libaio.so.1t64 for
|
|
# the time64 ABI transition, so the lvm2 binaries link a soname Arch has
|
|
# never had. Building Arch's libaio would not change what stage 1 links.
|
|
#
|
|
# Both leave the closure with the sub-package, which is why this is one hook
|
|
# rather than three.
|
|
#
|
|
# THE MEASUREMENT IS THE ARGUMENT, and it is the same one that went the other
|
|
# way for tcl and unixodbc an hour earlier. Those cost zero new packages, so
|
|
# building them beat dropping a sub-package. This one costs a language
|
|
# runtime, so dropping wins. The rule is not "prefer dropping" or "prefer
|
|
# building" -- it is to measure each time.
|
|
#
|
|
# Deferred: a target that wants LVM builds Rust first, restores the sub-package
|
|
# and rebuilds. device-mapper alone is what dm-crypt and systemd need.
|
|
set -euo pipefail
|
|
python3 - <<'PY'
|
|
import io
|
|
s = io.open("PKGBUILD", encoding="utf-8").read()
|
|
old = "pkgname=('lvm2' 'device-mapper')"
|
|
assert s.count(old) == 1, "lvm2: pkgname line not in the expected form"
|
|
s = s.replace(old, "pkgname=('device-mapper')", 1)
|
|
io.open("PKGBUILD", "w", encoding="utf-8").write(s)
|
|
PY
|
|
grep -q "^pkgname=('device-mapper')$" PKGBUILD || {
|
|
echo "lvm2: sub-package not reduced to device-mapper" >&2; exit 1; }
|
|
# package_lvm2() stays in the file, uncalled -- makepkg never calls a function
|
|
# whose name is absent from pkgname, as with package_libquadmath() in gcc.
|
|
grep -q "^package_device-mapper()" PKGBUILD || {
|
|
echo "lvm2: device-mapper package function missing" >&2; exit 1; }
|
|
echo "lvm2: only device-mapper built (lvm2 would pull Rust via thin-provisioning-tools)"
|
|
|
|
# device-mapper also picked up the host's libselinux, silently.
|
|
#
|
|
# $ readelf -d usr/bin/dmsetup | grep NEEDED
|
|
# (NEEDED) Shared library: [libselinux.so.1]
|
|
#
|
|
# Seventh package in this port to do it, and the second found by the soname
|
|
# audit rather than by a build. lvm2's configure has --disable-selinux and
|
|
# defaults to detecting; Ubuntu's libselinux1-dev is present because
|
|
# libmount-dev and libglib2.0-dev pull it in, so it detected.
|
|
#
|
|
# Arch has no libselinux package at all -- the reason coreutils, findutils,
|
|
# sed, tar and gettext each carry the same three lines. This is the sixth
|
|
# copy, and TODO.md already records that the per-package hook does not scale
|
|
# to a probe every package can trip.
|
|
python3 - <<'PY'
|
|
import io
|
|
s = io.open("PKGBUILD", encoding="utf-8").read()
|
|
assert "--disable-selinux" not in s, "lvm2: selinux already disabled, hook ran twice"
|
|
anchor = " --enable-cmdlib \\\n"
|
|
assert s.count(anchor) == 1, "lvm2: configure block not in the expected form"
|
|
s = s.replace(anchor, " --disable-selinux \\\n" + anchor, 1)
|
|
io.open("PKGBUILD", "w", encoding="utf-8").write(s)
|
|
PY
|
|
[ "$(grep -c -- '--disable-selinux' PKGBUILD)" = 1 ] || {
|
|
echo "lvm2: --disable-selinux not inserted exactly once" >&2; exit 1; }
|
|
echo "lvm2: --disable-selinux (Arch has no libselinux; the host does)"
|