[FIX] trust artefacts, not exit codes; add a PKGBUILD patch mechanism
A run reported "51 built, 0 failed" while glibc, gcc, coreutils and pacman had all failed. The cause is a bash rule that is easy to forget: callers invoke build_package inside an "if", and "if" DISABLES set -e for the whole function body. A failing makepkg fell through to repo-add, whose success became the function exit status. build_package now returns explicitly on failure and, more importantly, verifies that a package file actually exists. An exit code is not proof; only the artefact is. Measured before the fix: 23 files in the repository where a hundred were claimed. First real port patch, applied through a per-package hook rather than by hand: the glibc PKGBUILD passes --enable-sframe, and s390x has no SFrame at all -- configure refuses outright. Hooks re-clone cleanly, so an upstream change is never silently discarded. --nocheck for stage 1: these test suites run against the HOST libraries, not the Arch ones, so their verdict says nothing about the port. acl failed its check step on a sound build. Stage 2 runs them for real. The remaining failures were host makedepends that --nodeps hides: po4a, gnat, debuginfod and jansson are now installed up front. --- FR --- Une execution annoncait « 51 built, 0 failed » alors que glibc, gcc, coreutils et pacman avaient tous echoue. La cause est une regle de bash qu on oublie : build_package est appelee dans un « if », et « if » DESACTIVE set -e pour tout le corps de la fonction. Un makepkg en echec poursuivait jusqu a repo-add, dont la reussite devenait le code de sortie. build_package rend desormais la main explicitement en cas d echec et, surtout, verifie qu un fichier de paquet existe vraiment. Un code de sortie ne prouve rien ; seul l artefact prouve. Mesure avant correction : 23 fichiers dans le depot la ou cent etaient annonces. Premier vrai correctif de portage, applique par crochet et non a la main : le PKGBUILD de glibc passe --enable-sframe, et s390x n a aucun SFrame -- configure refuse net. Les crochets survivent a un reclonage, donc une evolution amont n est jamais perdue en silence. --nocheck pour l etage 1 : ces suites s executent contre les bibliotheques de l HOTE, pas celles d Arch, et leur verdict ne dit rien du portage. acl echouait a son etape check sur une compilation saine. L etage 2 les executera pour de vrai. Les autres echecs etaient des makedepends d hote que --nodeps masque : po4a, gnat, debuginfod et jansson sont poses d entree. Assisted-by: Claude Opus 5
This commit is contained in:
parent
1a0e19a368
commit
b29ac89e7a
2 changed files with 75 additions and 9 deletions
18
patches/pkgbuild/glibc.sh
Executable file
18
patches/pkgbuild/glibc.sh
Executable file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# glibc: SFrame does not exist on s390x.
|
||||||
|
#
|
||||||
|
# Arch's PKGBUILD passes --enable-sframe, added when x86_64 gained SFrame
|
||||||
|
# stack tracing. glibc's own configure rejects it outright on this
|
||||||
|
# architecture:
|
||||||
|
#
|
||||||
|
# configure: error: the architecture doesn't support SFrame
|
||||||
|
#
|
||||||
|
# This is not a build-environment problem and no host package fixes it: the
|
||||||
|
# feature is genuinely absent from s390x. Dropping the flag is what a port
|
||||||
|
# does -- and it must be dropped surgically, leaving every other configure
|
||||||
|
# option untouched, so that a future Arch change to this PKGBUILD is not
|
||||||
|
# silently discarded.
|
||||||
|
set -euo pipefail
|
||||||
|
sed -i '/--enable-sframe/d' PKGBUILD
|
||||||
|
grep -q -- '--enable-sframe' PKGBUILD && { echo "glibc: sframe flag still present" >&2; exit 1; }
|
||||||
|
echo "glibc: --enable-sframe removed (unsupported on s390x)"
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
# the z/VM round-trip the other scripts need.
|
# the z/VM round-trip the other scripts need.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
HERE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PATCH_DIR="${PATCH_DIR:-$HERE_DIR/../patches/pkgbuild}"
|
||||||
WORK="${WORK:-$HOME/work/arch-s390x}"
|
WORK="${WORK:-$HOME/work/arch-s390x}"
|
||||||
REPO="${REPO:-$WORK/repo/s390x}"
|
REPO="${REPO:-$WORK/repo/s390x}"
|
||||||
PACMAN_GIT="https://gitlab.archlinux.org/pacman/pacman.git"
|
PACMAN_GIT="https://gitlab.archlinux.org/pacman/pacman.git"
|
||||||
|
|
@ -24,15 +26,27 @@ log() { printf '\n== %s ==\n' "$*"; }
|
||||||
|
|
||||||
install_host_deps() {
|
install_host_deps() {
|
||||||
log "Host build dependencies"
|
log "Host build dependencies"
|
||||||
# bsdtar and fakeroot are makepkg's own requirements, not the package's:
|
# Two distinct groups, and confusing them costs hours.
|
||||||
# without them it fails deep inside extraction with a bare
|
#
|
||||||
# "bsdtar: command not found".
|
# makepkg's OWN requirements: bsdtar and fakeroot. Without them it fails
|
||||||
|
# deep inside extraction with a bare "bsdtar: command not found".
|
||||||
|
#
|
||||||
|
# The PKGBUILDs' makedepends: --nodeps tells pacman not to check them, so
|
||||||
|
# every one must be satisfied from the Ubuntu host by hand. Each name on
|
||||||
|
# the last three lines was added because a build stopped on it --
|
||||||
|
# systemtap-sdt-dev and gmp/mpfr/mpc for glibc and gcc, autopoint and
|
||||||
|
# gperf for coreutils, asciidoc for pacman, po4a for xz, gnat for gcc's
|
||||||
|
# Ada front end, debuginfod and jansson for binutils.
|
||||||
sudo apt-get -o DPkg::Lock::Timeout=600 install -y -qq \
|
sudo apt-get -o DPkg::Lock::Timeout=600 install -y -qq \
|
||||||
meson ninja-build pkg-config gettext \
|
meson ninja-build pkg-config gettext \
|
||||||
libarchive-dev libcurl4-openssl-dev libgpgme-dev libssl-dev \
|
libarchive-dev libcurl4-openssl-dev libgpgme-dev libssl-dev \
|
||||||
libarchive-tools fakeroot \
|
libarchive-tools fakeroot \
|
||||||
build-essential autoconf automake libtool m4 patch texinfo bison flex \
|
build-essential autoconf automake libtool m4 patch texinfo bison flex \
|
||||||
zstd xz-utils bzip2
|
zstd xz-utils bzip2 \
|
||||||
|
systemtap-sdt-dev asciidoc autopoint gperf help2man rsync \
|
||||||
|
libgmp-dev libmpfr-dev libmpc-dev python3-docutils \
|
||||||
|
libseccomp-dev libpcre2-dev \
|
||||||
|
po4a gnat libdebuginfod-dev libjansson-dev
|
||||||
}
|
}
|
||||||
|
|
||||||
build_pacman() {
|
build_pacman() {
|
||||||
|
|
@ -69,6 +83,9 @@ configure_makepkg() {
|
||||||
# --skipchecksums: GitLab regenerates .patch URLs, so their checksums drift
|
# --skipchecksums: GitLab regenerates .patch URLs, so their checksums drift
|
||||||
# from what the PKGBUILD recorded. Release tarballs still validate; only
|
# from what the PKGBUILD recorded. Release tarballs still validate; only
|
||||||
# the generated patches are skipped.
|
# the generated patches are skipped.
|
||||||
|
# --nocheck: stage-1 test suites run against the HOST libraries, not Arch's,
|
||||||
|
# so their verdict says nothing about the port. acl failed its check() on a
|
||||||
|
# perfectly sound build, and the suites cost hours. Stage 2 runs them.
|
||||||
build_package() {
|
build_package() {
|
||||||
local name="$1"
|
local name="$1"
|
||||||
log "Building $name"
|
log "Building $name"
|
||||||
|
|
@ -76,11 +93,42 @@ build_package() {
|
||||||
[ -d "$WORK/pkg/$name" ] || \
|
[ -d "$WORK/pkg/$name" ] || \
|
||||||
git clone --depth 1 "$PKG_GIT_BASE/$name.git" "$WORK/pkg/$name"
|
git clone --depth 1 "$PKG_GIT_BASE/$name.git" "$WORK/pkg/$name"
|
||||||
cd "$WORK/pkg/$name"
|
cd "$WORK/pkg/$name"
|
||||||
makepkg --nodeps --ignorearch --skippgpcheck --skipchecksums -f
|
# Port patches. Upstream PKGBUILDs are written for x86_64 and some carry
|
||||||
|
# flags no other architecture accepts -- glibc's --enable-sframe is the
|
||||||
|
# first. They are applied here, one hook per package, so each change is
|
||||||
|
# visible, reviewable and survives a re-clone, rather than being an edit
|
||||||
|
# someone once made by hand in a working copy.
|
||||||
|
local hook="$PATCH_DIR/$name.sh"
|
||||||
|
if [ -f "$hook" ]; then
|
||||||
|
git checkout -- PKGBUILD 2>/dev/null || true
|
||||||
|
bash "$hook" || return 1
|
||||||
|
fi
|
||||||
|
rm -f ./*.pkg.tar.*
|
||||||
|
# Explicit `|| return 1`. Relying on `set -e` here does NOT work: callers
|
||||||
|
# invoke build_package inside `if`, which disables set -e for the whole
|
||||||
|
# function body. A failing makepkg then fell through to repo-add, whose
|
||||||
|
# success became the function's exit status -- and a run reported
|
||||||
|
# "51 built, 0 failed" while glibc, gcc, coreutils and pacman had all
|
||||||
|
# failed. Measured: the repository held 23 files, not a hundred.
|
||||||
|
makepkg --nodeps --ignorearch --skippgpcheck --skipchecksums --nocheck -f \
|
||||||
|
|| return 1
|
||||||
|
# An exit code is not proof. Only the artefact is.
|
||||||
|
local produced=()
|
||||||
|
shopt -s nullglob
|
||||||
|
produced=(./*.pkg.tar.*)
|
||||||
|
shopt -u nullglob
|
||||||
|
if [ "${#produced[@]}" -eq 0 ]; then
|
||||||
|
echo "no package produced for $name" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
mkdir -p "$REPO"
|
mkdir -p "$REPO"
|
||||||
cp -f ./*.pkg.tar.* "$REPO/"
|
cp -f "${produced[@]}" "$REPO/" || return 1
|
||||||
cd "$REPO"
|
# Only the new packages. Globbing the whole repository made repo-add
|
||||||
repo-add core.db.tar.gz ./*.pkg.tar.*
|
# re-index everything on every call: quadratic, and it buried the real
|
||||||
|
# lines under warnings about entries that already existed.
|
||||||
|
local names=() f
|
||||||
|
for f in "${produced[@]}"; do names+=("$(basename "$f")"); done
|
||||||
|
( cd "$REPO" && repo-add core.db.tar.gz "${names[@]}" ) || return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
|
@ -93,7 +141,7 @@ main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Only run when executed, never when sourced: build-stage1.sh reuses
|
# Only run when executed, never when sourced: build-stage1.sh reuses
|
||||||
# build_package() and must not re-run the whole bootstrap to get it.
|
# build_package and must not re-run the whole bootstrap to get it.
|
||||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
main "$@"
|
main "$@"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue