[ADD] bootstrap pacman, makepkg and repo-add natively on s390x
The README lists pacman, bash and coreutils as three missing pieces.
They are not three tasks: pacman is the only one that matters, because
its source tree also ships makepkg and repo-add. Once those run, every
remaining package stops being hand-work and becomes makepkg on the
upstream PKGBUILD.
pacman 7.1.0 builds unpatched on s390x. No cross-compilation is
involved: on native hardware the whole userspace builds at full speed,
which removes the z/VM round-trip the other scripts need.
Measured end to end: zlib built from the official PKGBUILD yields
zlib, zlib-static and minizip, all tagged arch = s390x, the library
reporting "ELF 64-bit MSB shared object, IBM S/390", and repo-add
indexing them into a usable core.db.
--- FR ---
Le README annonce pacman, bash et coreutils comme trois pieces
manquantes. Ce ne sont pas trois travaux : seul pacman compte, parce
que son arbre source livre aussi makepkg et repo-add. Des qu ils
tournent, chaque paquet restant cesse d etre du travail manuel et
devient un makepkg sur le PKGBUILD amont.
pacman 7.1.0 se compile sans correctif sur s390x. Aucune compilation
croisee n intervient : sur du materiel natif tout l espace utilisateur
se batit a pleine vitesse, ce qui supprime l aller-retour z/VM dont
dependent les autres scripts.
Mesure de bout en bout : zlib bati depuis le PKGBUILD officiel produit
zlib, zlib-static et minizip, tous marques arch = s390x, la
bibliotheque se declarant « ELF 64-bit MSB shared object, IBM S/390 »,
et repo-add les indexant dans un core.db utilisable.
Assisted-by: Claude Opus 5
2026-08-15 03:18:47 -04:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
# Bootstrap the Arch packaging toolchain (pacman, makepkg, repo-add) on an
|
|
|
|
|
# s390x host, then build official Arch PKGBUILDs for s390x.
|
|
|
|
|
#
|
|
|
|
|
# WHY THIS IS THE KEYSTONE
|
|
|
|
|
#
|
|
|
|
|
# The README lists "pacman, bash and GNU coreutils are not yet ported" as three
|
|
|
|
|
# missing pieces. They are not three tasks -- pacman is the only one that
|
|
|
|
|
# matters, because pacman's source tree also ships makepkg and repo-add. Once
|
|
|
|
|
# those three run, every remaining package stops being hand-work and becomes
|
|
|
|
|
# `makepkg` on the upstream PKGBUILD.
|
|
|
|
|
#
|
|
|
|
|
# NO CROSS-COMPILATION IS NEEDED HERE. This runs on native s390x hardware, so
|
|
|
|
|
# the whole userspace builds at full speed with the host toolchain. That drops
|
|
|
|
|
# the z/VM round-trip the other scripts need.
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
[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
2026-08-15 20:40:17 -04:00
|
|
|
HERE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
|
PATCH_DIR="${PATCH_DIR:-$HERE_DIR/../patches/pkgbuild}"
|
[ADD] bootstrap pacman, makepkg and repo-add natively on s390x
The README lists pacman, bash and coreutils as three missing pieces.
They are not three tasks: pacman is the only one that matters, because
its source tree also ships makepkg and repo-add. Once those run, every
remaining package stops being hand-work and becomes makepkg on the
upstream PKGBUILD.
pacman 7.1.0 builds unpatched on s390x. No cross-compilation is
involved: on native hardware the whole userspace builds at full speed,
which removes the z/VM round-trip the other scripts need.
Measured end to end: zlib built from the official PKGBUILD yields
zlib, zlib-static and minizip, all tagged arch = s390x, the library
reporting "ELF 64-bit MSB shared object, IBM S/390", and repo-add
indexing them into a usable core.db.
--- FR ---
Le README annonce pacman, bash et coreutils comme trois pieces
manquantes. Ce ne sont pas trois travaux : seul pacman compte, parce
que son arbre source livre aussi makepkg et repo-add. Des qu ils
tournent, chaque paquet restant cesse d etre du travail manuel et
devient un makepkg sur le PKGBUILD amont.
pacman 7.1.0 se compile sans correctif sur s390x. Aucune compilation
croisee n intervient : sur du materiel natif tout l espace utilisateur
se batit a pleine vitesse, ce qui supprime l aller-retour z/VM dont
dependent les autres scripts.
Mesure de bout en bout : zlib bati depuis le PKGBUILD officiel produit
zlib, zlib-static et minizip, tous marques arch = s390x, la
bibliotheque se declarant « ELF 64-bit MSB shared object, IBM S/390 »,
et repo-add les indexant dans un core.db utilisable.
Assisted-by: Claude Opus 5
2026-08-15 03:18:47 -04:00
|
|
|
WORK="${WORK:-$HOME/work/arch-s390x}"
|
|
|
|
|
REPO="${REPO:-$WORK/repo/s390x}"
|
|
|
|
|
PACMAN_GIT="https://gitlab.archlinux.org/pacman/pacman.git"
|
|
|
|
|
PKG_GIT_BASE="https://gitlab.archlinux.org/archlinux/packaging/packages"
|
|
|
|
|
|
|
|
|
|
log() { printf '\n== %s ==\n' "$*"; }
|
|
|
|
|
|
|
|
|
|
install_host_deps() {
|
|
|
|
|
log "Host build dependencies"
|
[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
2026-08-15 20:40:17 -04:00
|
|
|
# Two distinct groups, and confusing them costs hours.
|
|
|
|
|
#
|
|
|
|
|
# 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.
|
[ADD] host deps: the tools six packages needed and nobody declared
--nodeps means every makedepend must be named here by hand. Seven builds
stopped on one, each naming a different tool: itstool, convert, fig2dev,
asciidoctor, libnsl, python -m build, libbpf, history.
The list was also a lie by omission. libreadline-dev, libncurses-dev,
zlib1g-dev, python3-dev, doxygen, xsltproc, docbook-xsl, elinks and
libcap2-bin were on this VM by hand and never declared. They made the
builds pass here and would fail on a fresh Ubuntu, for reasons that have
nothing to do with s390x.
history.pc is generated rather than copied: our own readline package
ships a correct one, but its libdir names /usr/lib, which on a multiarch
host holds no libhistory. The .pc has to describe THIS host.
Three hooks for what apt cannot buy. systemd asks for an EFI arch s390x
does not have -- and says "python3 is missing modules: elftools", which
sends you to apt for four lines before admitting the real reason.
--- FR ---
--nodeps veut dire que chaque makedepend doit être nommé ici à la main.
Sept compilations se sont arrêtées sur l'une d'elles, chacune désignant
un outil différent : itstool, convert, fig2dev, asciidoctor, libnsl,
python -m build, libbpf, history.
La liste mentait aussi par omission. libreadline-dev, libncurses-dev,
zlib1g-dev, python3-dev, doxygen, xsltproc, docbook-xsl, elinks et
libcap2-bin étaient posés à la main sur cette VM, jamais déclarés. Ils
faisaient passer les compilations ici et auraient échoué sur un Ubuntu
neuf, pour des raisons étrangères à s390x.
history.pc est généré et non copié : notre propre paquet readline en
livre un correct, mais son libdir nomme /usr/lib, qui sur un hôte
multiarch ne contient aucun libhistory. Le .pc doit décrire CET hôte-ci.
Trois crochets pour ce qu'apt n'achète pas. systemd réclame une
architecture EFI que s390x n'a pas — et annonce « python3 is missing
modules: elftools », ce qui envoie chez apt pour quatre lignes avant
d'avouer la vraie raison.
Assisted-by: Claude Opus 5
2026-08-17 01:33:41 -04:00
|
|
|
#
|
|
|
|
|
# THE LIST WAS ALSO A LIE BY OMISSION. An audit of the six packages that
|
|
|
|
|
# follow found libreadline-dev, libncurses-dev, zlib1g-dev, python3-dev,
|
|
|
|
|
# doxygen, xsltproc, docbook-xsl, elinks and libcap2-bin already present
|
|
|
|
|
# on the build VM but installed BY HAND, never declared here. On this
|
|
|
|
|
# host they made the builds pass; on a fresh Ubuntu they would have
|
|
|
|
|
# failed at readline, at libxml2 and inside shadow's `make install`, for
|
|
|
|
|
# reasons that have nothing to do with s390x. They are named below now.
|
|
|
|
|
# The rest is per-package, and each group says which package needs it.
|
|
|
|
|
#
|
|
|
|
|
# gnupg imagemagick + fig2dev render doc/*.svg and doc/*.fig, which
|
|
|
|
|
# a git checkout must generate; librsvg2-bin guarantees the
|
|
|
|
|
# SVG coder even under --no-install-recommends.
|
|
|
|
|
# shadow itstool builds the translated man pages; libcap2-bin gives
|
|
|
|
|
# the bare `setcap` its install rule calls.
|
|
|
|
|
# util-linux asciidoctor -- Ruby, and NOT the `asciidoc` above, which
|
|
|
|
|
# is a different program added for pacman. Easy to mistake
|
|
|
|
|
# for coverage.
|
|
|
|
|
# pam libnsl/libtirpc for NIS, the DocBook 5 catalog, and elinks,
|
|
|
|
|
# which meson uses to dump the HTML manuals to text.
|
|
|
|
|
# brotli cmake, and the PEP 517 chain its python bindings build with.
|
|
|
|
|
# libxml2 ICU, readline, and the doc toolchain.
|
|
|
|
|
# systemd the widest surface of anything in stage 1; every one of
|
|
|
|
|
# these was checked against a real meson configure.
|
[ADD] the closure pacman's resolver named
Everything in stage 1 until now was added because a BUILD stopped. These were
added because test-chroot.sh ran the resolver with --nodeps OFF -- the check
the whole bootstrap skips -- and it listed exactly what the repository owed.
Nothing here is speculative.
Thirty-five packages, then five rounds of failures that each got further than
the last: 12 failed, then 7, then 4, then 0. The pattern was almost always a
host tool nobody had declared, and the fix for one uncovered the next --
ducktype then yelp-build, ss then lmdb, autoconf-archive then cmocka.
Two corrections worth keeping. libargon2-dev was the wrong package: openldap
passes --with-argon2=libsodium, so the error named argon2 and the answer was
sodium. And apt-cache reported NONE for all eight candidates because this host
answers `Candidat :`, not `Candidate:` -- the same locale trap that had broken
util-linux hours earlier, met again inside the script written to verify its
fix. Query apt under LC_ALL=C.
--- FR ---
Tout ce qui composait l'étage 1 jusqu'ici avait été ajouté parce qu'une
COMPILATION s'arrêtait. Ceux-ci l'ont été parce que test-chroot.sh a lancé le
résolveur avec --nodeps DÉSACTIVÉ — le contrôle que tout l'amorçage saute — et
qu'il a listé exactement ce que le dépôt devait. Rien ici n'est spéculatif.
Trente-cinq paquets, puis cinq tours d'échecs allant chacun plus loin que le
précédent : 12, puis 7, puis 4, puis 0. Le motif était presque toujours un
outil hôte que personne n'avait déclaré, et corriger l'un dévoilait le
suivant — ducktype puis yelp-build, ss puis lmdb, autoconf-archive puis
cmocka.
Deux corrections à garder. libargon2-dev était le mauvais paquet : openldap
passe --with-argon2=libsodium, l'erreur nommait donc argon2 quand la réponse
était sodium. Et apt-cache annonçait NONE pour les huit candidats parce que
cet hôte répond « Candidat : » et non « Candidate: » — le piège de locale même
qui avait cassé util-linux quelques heures plus tôt, retrouvé dans le script
écrit pour en vérifier le correctif. Interroger apt sous LC_ALL=C.
Assisted-by: Claude Opus 5
2026-08-19 05:28:32 -04:00
|
|
|
#
|
|
|
|
|
# The last two lines are the closure round, and every one of them was
|
|
|
|
|
# named by a build that stopped: popt by cryptsetup, scdoc by kmod,
|
|
|
|
|
# libgpg-error by libgcrypt, Cython by libseccomp, tcl by sqlite, argon2
|
|
|
|
|
# by openldap, autoconf-archive by tpm2-tss and ducktype by dbus.
|
|
|
|
|
#
|
|
|
|
|
# A note on checking these. `apt-cache policy` was reporting NONE for all
|
|
|
|
|
# eight, which looked like eight wrong names. This host answers in French:
|
|
|
|
|
# the field is `Candidat :`, not `Candidate:`, so a grep for the English
|
|
|
|
|
# word found nothing. Exactly the trap that broke util-linux's build --
|
|
|
|
|
# met again while verifying the fix for it. Query apt under LC_ALL=C.
|
|
|
|
|
#
|
|
|
|
|
# The last line is the round after that, and each fix uncovered the next:
|
|
|
|
|
# yelp-build by dbus (once ducktype was found), lmdb by krb5 (once the ss
|
|
|
|
|
# flag was gone), cmocka by tpm2-tss (once autoconf-archive fixed its
|
|
|
|
|
# macros). A build that gets further is progress even when it still fails.
|
|
|
|
|
#
|
|
|
|
|
# libsodium-dev replaced libargon2-dev, which was a wrong guess: openldap
|
|
|
|
|
# passes `--with-argon2=libsodium`, so argon2.h was never what it wanted.
|
|
|
|
|
# The error named argon2 and the answer was sodium -- the message pointing
|
|
|
|
|
# at the wrong library, one more time.
|
|
|
|
|
#
|
|
|
|
|
# verto by krb5 and uthash by tpm2-tss came the round after, each once its
|
|
|
|
|
# predecessor was satisfied. Three rounds of this taught one thing worth
|
|
|
|
|
# writing down: when a package stops on a missing TOOL three times in a
|
|
|
|
|
# row, stop installing tools. dbus wanted ducktype, then yelp-build, then
|
|
|
|
|
# qhelpgenerator -- and the third needs Qt, so the chain had no end. Its
|
|
|
|
|
# doc features are pinned off in a hook instead. A single missing library
|
|
|
|
|
# is a host dep; a queue of them is a feature that should be disabled.
|
[ADD] closure rounds two and three, and the CA bundle
Thirty-five packages pulled in nineteen more, and those two. The resolver
named each round as precisely as the first, and it now reports satisfied:
101 packages, --nodeps off.
THE MEASUREMENT THAT CHANGED ITS ANSWER. Four of round two were going to be
avoided by dropping sub-packages -- sqlite-tcl, sqlite-analyzer, the openldap
server, debuginfod -- reasoning that had been right for python-brotli.
Measured instead: tcl, unixodbc and libmicrohttpd each cost ZERO new
packages, because the closure had filled in around them. Building them beats
four hooks, and it does not leave sqlite shipping an sqltclsh that cannot
start. The arithmetic that was right at forty packages was wrong at a hundred
and thirty.
ca-certificates-mozilla is the only entry here that is not a library: it is
the root certificate list itself, and ca-certificates is only the machinery
around it. Without it the target trusts nothing and every HTTPS verification
fails. It has no packaging repo -- nss produces it -- so nss and nspr came
too, measured first: nspr free, nss needing only mercurial on the host, and
hg.mozilla.org answering in 0.3s. 172 certificates shipped.
--- FR ---
Trente-cinq paquets en ont tiré dix-neuf autres, puis ces deux-là. Le
résolveur a nommé chaque tour aussi précisément que le premier, et il se
déclare maintenant satisfait : 101 paquets, --nodeps désactivé.
LA MESURE QUI A CHANGÉ SA RÉPONSE. Quatre paquets du deuxième tour allaient
être évités en écartant des sous-paquets — sqlite-tcl, sqlite-analyzer, le
serveur openldap, debuginfod — par un raisonnement juste pour python-brotli.
Mesuré plutôt que supposé : tcl, unixodbc et libmicrohttpd coûtent ZÉRO
paquet nouveau, la fermeture s'étant refermée autour d'eux. Les bâtir vaut
mieux que quatre crochets, et évite de livrer un sqlite contenant un sqltclsh
incapable de démarrer. L'arithmétique juste à quarante paquets était fausse à
cent trente.
ca-certificates-mozilla est la seule entrée ici qui ne soit pas une
bibliothèque : c'est la liste des certificats racine elle-même, et
ca-certificates n'en est que la mécanique. Sans lui la cible ne fait
confiance à rien et toute vérification HTTPS échoue. Il n'a pas de dépôt de
packaging — nss le produit — donc nss et nspr ont suivi, mesurés d'abord :
nspr gratuit, nss ne réclamant que mercurial sur l'hôte, et hg.mozilla.org
répondant en 0,3 s. 172 certificats livrés.
Assisted-by: Claude Opus 5
2026-08-19 06:24:11 -04:00
|
|
|
#
|
|
|
|
|
# The closure's second round wanted three more, and each named a program
|
|
|
|
|
# rather than a library: asn1Parser by p11-kit (libtasn1-bin -- we build
|
|
|
|
|
# the libtasn1 PACKAGE, but the host needs the TOOL), libevent by
|
|
|
|
|
# libverto, libaio by lvm2.
|
|
|
|
|
#
|
|
|
|
|
# libsasl asked for a fourth and did not get it. Its error said
|
|
|
|
|
# "libpq-fe.h: No such file or directory" while the header sat in
|
|
|
|
|
# /usr/include/postgresql, and mysql.h sat in /usr/include/mariadb -- two
|
|
|
|
|
# files that exist, on paths configure does not try. By the rule above,
|
|
|
|
|
# that is a queue, so the SQL auxprop plugin is disabled in a hook
|
|
|
|
|
# instead. Arch declares depends=(glibc) for libsasl and says why: the
|
|
|
|
|
# plugins are dlopened, so nothing is lost.
|
|
|
|
|
#
|
|
|
|
|
# mercurial is for nss, whose only source is an hg clone of Mozilla's NSS
|
|
|
|
|
# repository. gyp, perl and python were already here.
|
|
|
|
|
#
|
|
|
|
|
# libnspr4-dev is nss's other half: its build hardcodes -I/usr/include/nspr
|
|
|
|
|
# and stops on `plarena.h: No such file or directory`. We DO build an nspr
|
|
|
|
|
# package -- 4.40, newer than the host's 4.36 -- but this is an ABSENCE on
|
|
|
|
|
# the host, not an age, so the ordinary stage-1 rule applies and the host
|
|
|
|
|
# package is the answer. The libgcrypt hook exists precisely because that
|
|
|
|
|
# rule did not apply there: 1.51 against a floor of 1.56 cannot be fixed
|
|
|
|
|
# by installing anything.
|
[ADD] stage 2: the rebuild loop, and git to feed it
The loop applies each hook on the HOST -- /build is the same directory from
both sides, so makepkg in the chroot reads the patched PKGBUILD and nothing is
duplicated inside. It drops --nocheck: stage 1 skipped the test suites because
they ran against the host's libraries, and here they test what was built.
Each rebuilt package is installed into the chroot before the next one, with
the host's pacman and --root, because the chroot's own pacman will not start
until stage 2 has rebuilt it.
Two hooks must NOT run there, and both for the same satisfying reason: the
condition they work around does not exist in the chroot. libgcrypt.sh points
at a host prefix holding our libgpg-error, which the chroot has installed
properly. git.sh drops ZLIB_NG=1 because Ubuntu ships no zlib-ng headers,
while our own zlib-ng package ships them.
git is here because STAGE 2 needs it, not the repository: 51 of the 159
PKGBUILDs take their sources from git+https, and makepkg validates that clone
even under --noextract. Nothing depends on git. Its three -- perl-error,
perl-mailtools with perl-timedate, zlib-ng -- were read from the depends array
rather than from my own tool, which had reported `zsh` as a dependency of git.
It is not; the tool's regex was catching a neighbouring array.
--- FR ---
La boucle applique chaque crochet sur l'HÔTE — /build est le même répertoire
des deux côtés, donc makepkg dans le chroot lit le PKGBUILD corrigé et rien
n'est dupliqué dedans. Elle abandonne --nocheck : l'étage 1 sautait les suites
de tests parce qu'elles s'exécutaient contre les bibliothèques de l'hôte ; ici
elles éprouvent ce qui a été bâti. Chaque paquet reconstruit est installé dans
le chroot avant le suivant, avec le pacman de l'hôte et --root, celui du
chroot ne démarrant pas avant que l'étage 2 ne l'ait reconstruit.
Deux crochets ne doivent PAS y tourner, et pour la même raison satisfaisante :
la condition qu'ils contournent n'existe pas dans le chroot. libgcrypt.sh
pointe sur un préfixe hôte contenant notre libgpg-error, que le chroot a
installé correctement. git.sh retire ZLIB_NG=1 parce qu'Ubuntu ne livre pas
les en-têtes zlib-ng, alors que notre propre paquet zlib-ng les livre.
git est là parce que l'ÉTAGE 2 en a besoin, pas le dépôt : 51 des 159
PKGBUILD prennent leurs sources en git+https, et makepkg valide ce clone même
sous --noextract. Rien ne dépend de git. Ses trois dépendances — perl-error,
perl-mailtools avec perl-timedate, zlib-ng — ont été lues dans le tableau
depends plutôt que dans mon propre outil, qui annonçait `zsh` comme dépendance
de git. Elle ne l'est pas : la regex de l'outil attrapait un tableau voisin.
Assisted-by: Claude Opus 5
2026-08-19 08:56:41 -04:00
|
|
|
#
|
|
|
|
|
# glib and libsecret are git's, for contrib/credential/libsecret. git is in
|
|
|
|
|
# stage 1 only because STAGE 2 needs it: 51 of the 159 PKGBUILDs take their
|
|
|
|
|
# sources from git+https, and makepkg validates that clone even under
|
|
|
|
|
# --noextract. Nothing in the repository depends on git.
|
[ADD] the build systems stage 2 rebuilds with
Ten of the 159 PKGBUILDs call arch-meson and four call cmake, so a chroot
without them could rebuild most of the repository and then stop. Neither is a
dependency of anything in the repository, which is why no closure round ever
named them -- the same shape as fakeroot and bison, one layer up.
python returns with meson, and that is not the earlier decision being
reversed. Dropping python at stage 1 was about what the REPOSITORY must
supply: it was wanted only by two wheels Arch's own python could not load.
This is about what the BUILD ENVIRONMENT must contain, and meson is written in
Python. Different question, different answer.
python needed two fixes of its own. Its xvfb loop is in build() AND in
check(); stage 1 never ran the second because of --nocheck, but stage 2 drops
--nocheck on purpose, so it would have spun there too. And Python 3.13 removed
the vendored libmpdec, so --with-system-libmpdec is the only way to build and
needs the host headers -- reported nine hundred lines in as a missing make
rule for a file that used to be vendored.
cmake wanted rhash, then jsoncpp, then cppdap, one at a time. That is a queue,
and the rule in install_host_deps says a queue is a feature to disable. Not
applied here, deliberately: each exists as an Ubuntu package, so the queue
ends. The rule is for queues that do not, like dbus reaching a documentation
tool that needed Qt. Its Qt GUI is dropped -- a dialog box on a headless
mainframe.
--- FR ---
Dix des 159 PKGBUILD appellent arch-meson et quatre appellent cmake : un
chroot sans eux pourrait reconstruire l'essentiel du dépôt puis s'arrêter.
Aucun des deux n'est une dépendance de quoi que ce soit dans le dépôt, ce qui
explique qu'aucun tour de fermeture ne les ait nommés — même forme que
fakeroot et bison, une couche plus haut.
python revient avec meson, et ce n'est pas un revirement. L'écarter à l'étage
1 portait sur ce que le DÉPÔT doit fournir : il n'était voulu que par deux
roues que le python d'Arch ne pouvait pas charger. Ici il s'agit de ce que
l'ENVIRONNEMENT DE BUILD doit contenir, et meson est écrit en Python. Autre
question, autre réponse.
python a demandé deux correctifs propres. Sa boucle xvfb est dans build() ET
dans check() ; l'étage 1 n'a jamais exécuté la seconde grâce à --nocheck, mais
l'étage 2 l'abandonne exprès — elle y aurait tourné aussi. Et Python 3.13 a
retiré le libmpdec embarqué : --with-system-libmpdec est la seule voie et
réclame les en-têtes de l'hôte, signalé neuf cents lignes plus loin comme une
règle make manquante pour un fichier autrefois embarqué.
cmake a réclamé rhash, puis jsoncpp, puis cppdap, un par un. C'est une file, et
la règle d'install_host_deps dit qu'une file est une fonctionnalité à
désactiver. Non appliquée ici, délibérément : chacun existe en paquet Ubuntu,
donc la file se termine. La règle vise celles qui ne terminent pas, comme dbus
atteignant un outil de documentation qui exigeait Qt. Son interface Qt est
retirée — une boîte de dialogue sur un mainframe sans écran.
Assisted-by: Claude Opus 5
2026-08-19 19:53:46 -04:00
|
|
|
#
|
|
|
|
|
# libmpdec-dev is python's, and it is not optional: Python 3.13 removed the
|
|
|
|
|
# vendored libmpdec, so --with-system-libmpdec is the only way to build and
|
|
|
|
|
# it needs the system headers. Without them the failure is
|
|
|
|
|
#
|
|
|
|
|
# No rule to make target 'Modules/_decimal/libmpdec/basearith.h'
|
|
|
|
|
#
|
|
|
|
|
# nine hundred lines into a PGO build -- a missing header reported as a
|
|
|
|
|
# missing make rule for a file that used to be vendored.
|
|
|
|
|
#
|
|
|
|
|
# The last line is the meson/cmake round, and every entry is a tool those
|
|
|
|
|
# two need to describe themselves: setuptools-scm and yaml for meson's own
|
|
|
|
|
# build, sphinx for libuv's docs, rhash and nlohmann-json for cmake and
|
|
|
|
|
# cppdap. Note what they are NOT: none is a dependency of the software
|
|
|
|
|
# being ported. They are the cost of the build system, which is why the
|
|
|
|
|
# dependency resolver never mentioned one of them.
|
|
|
|
|
#
|
|
|
|
|
# strictyaml, not yaml: meson's docs/meson.build asks for the module by
|
|
|
|
|
# name and PyYAML does not answer to it. `python3-yaml` was installed
|
|
|
|
|
# first, the error did not move, and only makedepends said which one --
|
|
|
|
|
# `python-strictyaml`. Reading the PKGBUILD would have been quicker than
|
|
|
|
|
# reading the error.
|
|
|
|
|
#
|
|
|
|
|
# cmake asked for four of these one at a time -- rhash, then jsoncpp, then
|
|
|
|
|
# cppdap -- because its bootstrap prefers a system copy of everything it
|
|
|
|
|
# bundles. That is a queue, and the rule says a queue is a feature to
|
|
|
|
|
# disable. It is not applied here for once, and deliberately: each one
|
|
|
|
|
# exists as an Ubuntu -dev package, so the queue terminates. The rule is
|
|
|
|
|
# about queues with no end, like dbus asking for a third documentation
|
|
|
|
|
# tool that needed Qt.
|
[ADD] bootstrap pacman, makepkg and repo-add natively on s390x
The README lists pacman, bash and coreutils as three missing pieces.
They are not three tasks: pacman is the only one that matters, because
its source tree also ships makepkg and repo-add. Once those run, every
remaining package stops being hand-work and becomes makepkg on the
upstream PKGBUILD.
pacman 7.1.0 builds unpatched on s390x. No cross-compilation is
involved: on native hardware the whole userspace builds at full speed,
which removes the z/VM round-trip the other scripts need.
Measured end to end: zlib built from the official PKGBUILD yields
zlib, zlib-static and minizip, all tagged arch = s390x, the library
reporting "ELF 64-bit MSB shared object, IBM S/390", and repo-add
indexing them into a usable core.db.
--- FR ---
Le README annonce pacman, bash et coreutils comme trois pieces
manquantes. Ce ne sont pas trois travaux : seul pacman compte, parce
que son arbre source livre aussi makepkg et repo-add. Des qu ils
tournent, chaque paquet restant cesse d etre du travail manuel et
devient un makepkg sur le PKGBUILD amont.
pacman 7.1.0 se compile sans correctif sur s390x. Aucune compilation
croisee n intervient : sur du materiel natif tout l espace utilisateur
se batit a pleine vitesse, ce qui supprime l aller-retour z/VM dont
dependent les autres scripts.
Mesure de bout en bout : zlib bati depuis le PKGBUILD officiel produit
zlib, zlib-static et minizip, tous marques arch = s390x, la
bibliotheque se declarant « ELF 64-bit MSB shared object, IBM S/390 »,
et repo-add les indexant dans un core.db utilisable.
Assisted-by: Claude Opus 5
2026-08-15 03:18:47 -04:00
|
|
|
sudo apt-get -o DPkg::Lock::Timeout=600 install -y -qq \
|
|
|
|
|
meson ninja-build pkg-config gettext \
|
|
|
|
|
libarchive-dev libcurl4-openssl-dev libgpgme-dev libssl-dev \
|
|
|
|
|
libarchive-tools fakeroot \
|
|
|
|
|
build-essential autoconf automake libtool m4 patch texinfo bison flex \
|
[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
2026-08-15 20:40:17 -04:00
|
|
|
zstd xz-utils bzip2 \
|
|
|
|
|
systemtap-sdt-dev asciidoc autopoint gperf help2man rsync \
|
|
|
|
|
libgmp-dev libmpfr-dev libmpc-dev python3-docutils \
|
|
|
|
|
libseccomp-dev libpcre2-dev \
|
[ADD] host deps: the tools six packages needed and nobody declared
--nodeps means every makedepend must be named here by hand. Seven builds
stopped on one, each naming a different tool: itstool, convert, fig2dev,
asciidoctor, libnsl, python -m build, libbpf, history.
The list was also a lie by omission. libreadline-dev, libncurses-dev,
zlib1g-dev, python3-dev, doxygen, xsltproc, docbook-xsl, elinks and
libcap2-bin were on this VM by hand and never declared. They made the
builds pass here and would fail on a fresh Ubuntu, for reasons that have
nothing to do with s390x.
history.pc is generated rather than copied: our own readline package
ships a correct one, but its libdir names /usr/lib, which on a multiarch
host holds no libhistory. The .pc has to describe THIS host.
Three hooks for what apt cannot buy. systemd asks for an EFI arch s390x
does not have -- and says "python3 is missing modules: elftools", which
sends you to apt for four lines before admitting the real reason.
--- FR ---
--nodeps veut dire que chaque makedepend doit être nommé ici à la main.
Sept compilations se sont arrêtées sur l'une d'elles, chacune désignant
un outil différent : itstool, convert, fig2dev, asciidoctor, libnsl,
python -m build, libbpf, history.
La liste mentait aussi par omission. libreadline-dev, libncurses-dev,
zlib1g-dev, python3-dev, doxygen, xsltproc, docbook-xsl, elinks et
libcap2-bin étaient posés à la main sur cette VM, jamais déclarés. Ils
faisaient passer les compilations ici et auraient échoué sur un Ubuntu
neuf, pour des raisons étrangères à s390x.
history.pc est généré et non copié : notre propre paquet readline en
livre un correct, mais son libdir nomme /usr/lib, qui sur un hôte
multiarch ne contient aucun libhistory. Le .pc doit décrire CET hôte-ci.
Trois crochets pour ce qu'apt n'achète pas. systemd réclame une
architecture EFI que s390x n'a pas — et annonce « python3 is missing
modules: elftools », ce qui envoie chez apt pour quatre lignes avant
d'avouer la vraie raison.
Assisted-by: Claude Opus 5
2026-08-17 01:33:41 -04:00
|
|
|
po4a gnat libdebuginfod-dev libjansson-dev \
|
|
|
|
|
libreadline-dev libncurses-dev zlib1g-dev python3-dev \
|
|
|
|
|
doxygen xsltproc docbook-xsl libcap2-bin \
|
|
|
|
|
imagemagick fig2dev librsvg2-bin \
|
|
|
|
|
itstool asciidoctor \
|
|
|
|
|
libtirpc-dev libnsl-dev docbook5-xml docbook-xsl-ns elinks \
|
|
|
|
|
cmake python3-build python3-installer python3-pkgconfig \
|
|
|
|
|
python3-setuptools python3-wheel \
|
|
|
|
|
libicu-dev \
|
|
|
|
|
libbpf-dev clang libapparmor-dev libfdisk-dev libkmod-dev libdw-dev \
|
|
|
|
|
libpwquality-dev libxkbcommon-dev libdbus-1-dev libqrencode-dev \
|
|
|
|
|
libfido2-dev libtss2-dev libmicrohttpd-dev libaudit-dev \
|
[FIX] host defaults: apt was deciding what got built
--auto-features enabled turns every auto feature into a requirement, so
installing a tool switches on code that never compiled here. Three of the
fifty host packages did exactly that, and only one failed for the reason
it named.
expat had built clean the day before. asciidoc pulled docbook-utils in as
an automatic dependency; it owns docbook2man, the third name in expat's
find_program list, so docs defaulted ON twenty-nine hours before anything
rebuilt. That tool is the SGML pipeline: on DocBook XML it writes nothing
and still exits 0, and the mv it feeds is what reported the failure. Arch
ships no xmlwf.1 either, so OFF is parity.
systemd's split-bin probes the BUILD host's /usr/sbin. Ubuntu's is a real
directory, so six binaries went where package() does not look -- and
arch-meson's --sbindir is ignored, systemd computes its own.
util-linux needed no option: poman-translate.sh greps po4a for the English
"Discard" and this host answers "Rejet de". The locale belongs to the host,
so it is pinned once on the makepkg line.
--- FR ---
--auto-features enabled fait de chaque fonction « auto » une exigence :
installer un outil active donc du code jamais compilé ici. Trois des
cinquante paquets hôte l'ont fait, et un seul a échoué pour la raison
qu'il annonçait.
expat compilait proprement la veille. asciidoc avait tiré docbook-utils en
dépendance automatique ; il fournit docbook2man, troisième nom de la liste
find_program d'expat, et la doc est passée à ON vingt-neuf heures avant
toute reconstruction. Cet outil est le pipeline SGML : sur du DocBook XML
il n'écrit rien et sort quand même 0, et le mv qu'il alimente est ce qui a
signalé la panne. Arch ne livre pas xmlwf.1 non plus : OFF, c'est la parité.
Le split-bin de systemd sonde le /usr/sbin de la machine de BUILD. Celui
d'Ubuntu est un vrai répertoire, donc six binaires sont partis là où
package() ne regarde pas — et le --sbindir d'arch-meson est ignoré, systemd
calcule le sien.
util-linux n'avait besoin d'aucune option : poman-translate.sh cherche le
« Discard » anglais de po4a, et cet hôte répond « Rejet de ». La locale
appartient à l'hôte : elle est épinglée une fois, sur la ligne makepkg.
Assisted-by: Claude Opus 5
2026-08-17 02:37:46 -04:00
|
|
|
libcryptsetup-dev libgcrypt20-dev libgnutls28-dev libpam0g-dev \
|
[ADD] the closure pacman's resolver named
Everything in stage 1 until now was added because a BUILD stopped. These were
added because test-chroot.sh ran the resolver with --nodeps OFF -- the check
the whole bootstrap skips -- and it listed exactly what the repository owed.
Nothing here is speculative.
Thirty-five packages, then five rounds of failures that each got further than
the last: 12 failed, then 7, then 4, then 0. The pattern was almost always a
host tool nobody had declared, and the fix for one uncovered the next --
ducktype then yelp-build, ss then lmdb, autoconf-archive then cmocka.
Two corrections worth keeping. libargon2-dev was the wrong package: openldap
passes --with-argon2=libsodium, so the error named argon2 and the answer was
sodium. And apt-cache reported NONE for all eight candidates because this host
answers `Candidat :`, not `Candidate:` -- the same locale trap that had broken
util-linux hours earlier, met again inside the script written to verify its
fix. Query apt under LC_ALL=C.
--- FR ---
Tout ce qui composait l'étage 1 jusqu'ici avait été ajouté parce qu'une
COMPILATION s'arrêtait. Ceux-ci l'ont été parce que test-chroot.sh a lancé le
résolveur avec --nodeps DÉSACTIVÉ — le contrôle que tout l'amorçage saute — et
qu'il a listé exactement ce que le dépôt devait. Rien ici n'est spéculatif.
Trente-cinq paquets, puis cinq tours d'échecs allant chacun plus loin que le
précédent : 12, puis 7, puis 4, puis 0. Le motif était presque toujours un
outil hôte que personne n'avait déclaré, et corriger l'un dévoilait le
suivant — ducktype puis yelp-build, ss puis lmdb, autoconf-archive puis
cmocka.
Deux corrections à garder. libargon2-dev était le mauvais paquet : openldap
passe --with-argon2=libsodium, l'erreur nommait donc argon2 quand la réponse
était sodium. Et apt-cache annonçait NONE pour les huit candidats parce que
cet hôte répond « Candidat : » et non « Candidate: » — le piège de locale même
qui avait cassé util-linux quelques heures plus tôt, retrouvé dans le script
écrit pour en vérifier le correctif. Interroger apt sous LC_ALL=C.
Assisted-by: Claude Opus 5
2026-08-19 05:28:32 -04:00
|
|
|
libpopt-dev scdoc libgpg-error-dev cython3 tcl-dev libsodium-dev \
|
|
|
|
|
autoconf-archive ducktype \
|
[ADD] closure rounds two and three, and the CA bundle
Thirty-five packages pulled in nineteen more, and those two. The resolver
named each round as precisely as the first, and it now reports satisfied:
101 packages, --nodeps off.
THE MEASUREMENT THAT CHANGED ITS ANSWER. Four of round two were going to be
avoided by dropping sub-packages -- sqlite-tcl, sqlite-analyzer, the openldap
server, debuginfod -- reasoning that had been right for python-brotli.
Measured instead: tcl, unixodbc and libmicrohttpd each cost ZERO new
packages, because the closure had filled in around them. Building them beats
four hooks, and it does not leave sqlite shipping an sqltclsh that cannot
start. The arithmetic that was right at forty packages was wrong at a hundred
and thirty.
ca-certificates-mozilla is the only entry here that is not a library: it is
the root certificate list itself, and ca-certificates is only the machinery
around it. Without it the target trusts nothing and every HTTPS verification
fails. It has no packaging repo -- nss produces it -- so nss and nspr came
too, measured first: nspr free, nss needing only mercurial on the host, and
hg.mozilla.org answering in 0.3s. 172 certificates shipped.
--- FR ---
Trente-cinq paquets en ont tiré dix-neuf autres, puis ces deux-là. Le
résolveur a nommé chaque tour aussi précisément que le premier, et il se
déclare maintenant satisfait : 101 paquets, --nodeps désactivé.
LA MESURE QUI A CHANGÉ SA RÉPONSE. Quatre paquets du deuxième tour allaient
être évités en écartant des sous-paquets — sqlite-tcl, sqlite-analyzer, le
serveur openldap, debuginfod — par un raisonnement juste pour python-brotli.
Mesuré plutôt que supposé : tcl, unixodbc et libmicrohttpd coûtent ZÉRO
paquet nouveau, la fermeture s'étant refermée autour d'eux. Les bâtir vaut
mieux que quatre crochets, et évite de livrer un sqlite contenant un sqltclsh
incapable de démarrer. L'arithmétique juste à quarante paquets était fausse à
cent trente.
ca-certificates-mozilla est la seule entrée ici qui ne soit pas une
bibliothèque : c'est la liste des certificats racine elle-même, et
ca-certificates n'en est que la mécanique. Sans lui la cible ne fait
confiance à rien et toute vérification HTTPS échoue. Il n'a pas de dépôt de
packaging — nss le produit — donc nss et nspr ont suivi, mesurés d'abord :
nspr gratuit, nss ne réclamant que mercurial sur l'hôte, et hg.mozilla.org
répondant en 0,3 s. 172 certificats livrés.
Assisted-by: Claude Opus 5
2026-08-19 06:24:11 -04:00
|
|
|
yelp-tools liblmdb-dev libcmocka-dev libverto-dev uthash-dev \
|
[ADD] stage 2: the rebuild loop, and git to feed it
The loop applies each hook on the HOST -- /build is the same directory from
both sides, so makepkg in the chroot reads the patched PKGBUILD and nothing is
duplicated inside. It drops --nocheck: stage 1 skipped the test suites because
they ran against the host's libraries, and here they test what was built.
Each rebuilt package is installed into the chroot before the next one, with
the host's pacman and --root, because the chroot's own pacman will not start
until stage 2 has rebuilt it.
Two hooks must NOT run there, and both for the same satisfying reason: the
condition they work around does not exist in the chroot. libgcrypt.sh points
at a host prefix holding our libgpg-error, which the chroot has installed
properly. git.sh drops ZLIB_NG=1 because Ubuntu ships no zlib-ng headers,
while our own zlib-ng package ships them.
git is here because STAGE 2 needs it, not the repository: 51 of the 159
PKGBUILDs take their sources from git+https, and makepkg validates that clone
even under --noextract. Nothing depends on git. Its three -- perl-error,
perl-mailtools with perl-timedate, zlib-ng -- were read from the depends array
rather than from my own tool, which had reported `zsh` as a dependency of git.
It is not; the tool's regex was catching a neighbouring array.
--- FR ---
La boucle applique chaque crochet sur l'HÔTE — /build est le même répertoire
des deux côtés, donc makepkg dans le chroot lit le PKGBUILD corrigé et rien
n'est dupliqué dedans. Elle abandonne --nocheck : l'étage 1 sautait les suites
de tests parce qu'elles s'exécutaient contre les bibliothèques de l'hôte ; ici
elles éprouvent ce qui a été bâti. Chaque paquet reconstruit est installé dans
le chroot avant le suivant, avec le pacman de l'hôte et --root, celui du
chroot ne démarrant pas avant que l'étage 2 ne l'ait reconstruit.
Deux crochets ne doivent PAS y tourner, et pour la même raison satisfaisante :
la condition qu'ils contournent n'existe pas dans le chroot. libgcrypt.sh
pointe sur un préfixe hôte contenant notre libgpg-error, que le chroot a
installé correctement. git.sh retire ZLIB_NG=1 parce qu'Ubuntu ne livre pas
les en-têtes zlib-ng, alors que notre propre paquet zlib-ng les livre.
git est là parce que l'ÉTAGE 2 en a besoin, pas le dépôt : 51 des 159
PKGBUILD prennent leurs sources en git+https, et makepkg valide ce clone même
sous --noextract. Rien ne dépend de git. Ses trois dépendances — perl-error,
perl-mailtools avec perl-timedate, zlib-ng — ont été lues dans le tableau
depends plutôt que dans mon propre outil, qui annonçait `zsh` comme dépendance
de git. Elle ne l'est pas : la regex de l'outil attrapait un tableau voisin.
Assisted-by: Claude Opus 5
2026-08-19 08:56:41 -04:00
|
|
|
libtasn1-bin libevent-dev libaio-dev mercurial libnspr4-dev \
|
[ADD] the build systems stage 2 rebuilds with
Ten of the 159 PKGBUILDs call arch-meson and four call cmake, so a chroot
without them could rebuild most of the repository and then stop. Neither is a
dependency of anything in the repository, which is why no closure round ever
named them -- the same shape as fakeroot and bison, one layer up.
python returns with meson, and that is not the earlier decision being
reversed. Dropping python at stage 1 was about what the REPOSITORY must
supply: it was wanted only by two wheels Arch's own python could not load.
This is about what the BUILD ENVIRONMENT must contain, and meson is written in
Python. Different question, different answer.
python needed two fixes of its own. Its xvfb loop is in build() AND in
check(); stage 1 never ran the second because of --nocheck, but stage 2 drops
--nocheck on purpose, so it would have spun there too. And Python 3.13 removed
the vendored libmpdec, so --with-system-libmpdec is the only way to build and
needs the host headers -- reported nine hundred lines in as a missing make
rule for a file that used to be vendored.
cmake wanted rhash, then jsoncpp, then cppdap, one at a time. That is a queue,
and the rule in install_host_deps says a queue is a feature to disable. Not
applied here, deliberately: each exists as an Ubuntu package, so the queue
ends. The rule is for queues that do not, like dbus reaching a documentation
tool that needed Qt. Its Qt GUI is dropped -- a dialog box on a headless
mainframe.
--- FR ---
Dix des 159 PKGBUILD appellent arch-meson et quatre appellent cmake : un
chroot sans eux pourrait reconstruire l'essentiel du dépôt puis s'arrêter.
Aucun des deux n'est une dépendance de quoi que ce soit dans le dépôt, ce qui
explique qu'aucun tour de fermeture ne les ait nommés — même forme que
fakeroot et bison, une couche plus haut.
python revient avec meson, et ce n'est pas un revirement. L'écarter à l'étage
1 portait sur ce que le DÉPÔT doit fournir : il n'était voulu que par deux
roues que le python d'Arch ne pouvait pas charger. Ici il s'agit de ce que
l'ENVIRONNEMENT DE BUILD doit contenir, et meson est écrit en Python. Autre
question, autre réponse.
python a demandé deux correctifs propres. Sa boucle xvfb est dans build() ET
dans check() ; l'étage 1 n'a jamais exécuté la seconde grâce à --nocheck, mais
l'étage 2 l'abandonne exprès — elle y aurait tourné aussi. Et Python 3.13 a
retiré le libmpdec embarqué : --with-system-libmpdec est la seule voie et
réclame les en-têtes de l'hôte, signalé neuf cents lignes plus loin comme une
règle make manquante pour un fichier autrefois embarqué.
cmake a réclamé rhash, puis jsoncpp, puis cppdap, un par un. C'est une file, et
la règle d'install_host_deps dit qu'une file est une fonctionnalité à
désactiver. Non appliquée ici, délibérément : chacun existe en paquet Ubuntu,
donc la file se termine. La règle vise celles qui ne terminent pas, comme dbus
atteignant un outil de documentation qui exigeait Qt. Son interface Qt est
retirée — une boîte de dialogue sur un mainframe sans écran.
Assisted-by: Claude Opus 5
2026-08-19 19:53:46 -04:00
|
|
|
libglib2.0-dev libsecret-1-dev libmpdec-dev \
|
|
|
|
|
python3-setuptools-scm python3-yaml python3-sphinx \
|
|
|
|
|
librhash-dev nlohmann-json3-dev python3-strictyaml libjsoncpp-dev \
|
|
|
|
|
libcppdap-dev
|
[FIX] libdir: the Debian host hid the libraries from Arch
meson and cmake both ask the HOST where libraries go. On Ubuntu the
answer is lib/s390x-linux-gnu, so five packages already in the repository
ship theirs where Arch's ld.so and pkgconf never look. Measured:
expat 12 lz4 6 pacman 6 pkgconf 6 zstd 12 entries
Nothing failed. util-linux is where it finally shouted, and even there
the rm was the first victim, not the cause.
pacman is the one that matters: libalpm.so.16 landed where pacman's own
binary cannot load it, and a target installed from that package has no
working package manager left to repair itself with.
arch-meson now states the libdir devtools has no need to state, and is
reinstalled on every run -- editing the copy here changed nothing while
/usr/local/bin held a stale one. Four packages call bare meson or cmake
and get their own hook. util-linux's old hook chased lib64, which never
existed here; it is deleted.
--- FR ---
meson et cmake demandent tous deux à l'HÔTE où vont les bibliothèques.
Sous Ubuntu la réponse est lib/s390x-linux-gnu : cinq paquets déjà dans
le dépôt livrent donc les leurs là où ld.so et pkgconf d'Arch ne
regarderont jamais. Mesuré :
expat 12 lz4 6 pacman 6 pkgconf 6 zstd 12 entrées
Rien n'a échoué. util-linux est l'endroit où cela a fini par crier, et
même là le rm était la première victime, pas la cause.
pacman est celui qui compte : libalpm.so.16 atterrissait là où le binaire
de pacman ne peut pas la charger, et une cible installée depuis ce paquet
n'a plus de gestionnaire de paquets pour se réparer.
arch-meson énonce désormais le libdir que devtools n'a pas besoin
d'énoncer, et se réinstalle à chaque exécution : éditer la copie du dépôt
ne changeait rien tant que /usr/local/bin en gardait une périmée. Quatre
paquets appellent meson ou cmake nu et reçoivent leur crochet. L'ancien
crochet util-linux poursuivait un lib64 qui n'a jamais existé ici : il
est supprimé.
Assisted-by: Claude Opus 5
2026-08-17 01:33:41 -04:00
|
|
|
install_host_shims
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# The parts of "make the host look enough like Arch" that apt cannot express.
|
|
|
|
|
#
|
|
|
|
|
# Called from install_host_deps AND from build-stage1.sh, deliberately. The
|
|
|
|
|
# stand-ins are only consulted through /usr/local/bin, so editing the copy in
|
|
|
|
|
# this repository changes NOTHING until it is installed -- and a stale
|
|
|
|
|
# /usr/local copy is invisible: the build succeeds and ships the wrong paths.
|
|
|
|
|
# Re-installing them on every stage-1 run makes the repository the source of
|
|
|
|
|
# truth in fact, not just in intent. Both operations are idempotent.
|
|
|
|
|
install_host_shims() {
|
|
|
|
|
log "Host shims"
|
|
|
|
|
local d="$HERE_DIR/devtools"
|
|
|
|
|
sudo install -m755 "$d/arch-meson" "$d/arch-cmake" /usr/local/bin/
|
[ADD] host deps: the tools six packages needed and nobody declared
--nodeps means every makedepend must be named here by hand. Seven builds
stopped on one, each naming a different tool: itstool, convert, fig2dev,
asciidoctor, libnsl, python -m build, libbpf, history.
The list was also a lie by omission. libreadline-dev, libncurses-dev,
zlib1g-dev, python3-dev, doxygen, xsltproc, docbook-xsl, elinks and
libcap2-bin were on this VM by hand and never declared. They made the
builds pass here and would fail on a fresh Ubuntu, for reasons that have
nothing to do with s390x.
history.pc is generated rather than copied: our own readline package
ships a correct one, but its libdir names /usr/lib, which on a multiarch
host holds no libhistory. The .pc has to describe THIS host.
Three hooks for what apt cannot buy. systemd asks for an EFI arch s390x
does not have -- and says "python3 is missing modules: elftools", which
sends you to apt for four lines before admitting the real reason.
--- FR ---
--nodeps veut dire que chaque makedepend doit être nommé ici à la main.
Sept compilations se sont arrêtées sur l'une d'elles, chacune désignant
un outil différent : itstool, convert, fig2dev, asciidoctor, libnsl,
python -m build, libbpf, history.
La liste mentait aussi par omission. libreadline-dev, libncurses-dev,
zlib1g-dev, python3-dev, doxygen, xsltproc, docbook-xsl, elinks et
libcap2-bin étaient posés à la main sur cette VM, jamais déclarés. Ils
faisaient passer les compilations ici et auraient échoué sur un Ubuntu
neuf, pour des raisons étrangères à s390x.
history.pc est généré et non copié : notre propre paquet readline en
livre un correct, mais son libdir nomme /usr/lib, qui sur un hôte
multiarch ne contient aucun libhistory. Le .pc doit décrire CET hôte-ci.
Trois crochets pour ce qu'apt n'achète pas. systemd réclame une
architecture EFI que s390x n'a pas — et annonce « python3 is missing
modules: elftools », ce qui envoie chez apt pour quatre lignes avant
d'avouer la vraie raison.
Assisted-by: Claude Opus 5
2026-08-17 01:33:41 -04:00
|
|
|
# history.pc, which Ubuntu drops and Arch ships.
|
|
|
|
|
#
|
|
|
|
|
# GNU readline generates and installs BOTH readline.pc and history.pc;
|
|
|
|
|
# Debian and Ubuntu keep the first and delete the second, while the
|
|
|
|
|
# library, libhistory.so, is right there in libreadline-dev. libxml2 asks
|
|
|
|
|
# pkg-config for `history` and stops:
|
|
|
|
|
#
|
|
|
|
|
# libxml2/meson.build:353:18: ERROR: Dependency "history" not found
|
|
|
|
|
#
|
|
|
|
|
# THE TRAP: our own readline package in repo/s390x DOES ship a correct
|
|
|
|
|
# history.pc, so copying that one looks like the tidy answer. It is not.
|
|
|
|
|
# Its libdir is ${exec_prefix}/lib -- right for the target rootfs, wrong
|
|
|
|
|
# for a multiarch host where /usr/lib holds no libhistory. The .pc has to
|
|
|
|
|
# describe THIS host, so it is generated from the host's own readline.pc.
|
|
|
|
|
local multiarch version
|
|
|
|
|
multiarch="$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
|
|
|
|
|
version="$(pkg-config --modversion readline)"
|
|
|
|
|
sudo mkdir -p /usr/local/lib/pkgconfig
|
|
|
|
|
printf '%s\n' \
|
|
|
|
|
"prefix=/usr" \
|
|
|
|
|
"exec_prefix=\${prefix}" \
|
|
|
|
|
"libdir=/usr/lib/$multiarch" \
|
|
|
|
|
"includedir=\${prefix}/include" \
|
|
|
|
|
"" \
|
|
|
|
|
"Name: History" \
|
|
|
|
|
"Description: GNU History library" \
|
|
|
|
|
"Version: $version" \
|
|
|
|
|
"Requires.private: tinfo" \
|
|
|
|
|
"Libs: -L\${libdir} -lhistory" \
|
|
|
|
|
"Cflags: -I\${includedir}" \
|
|
|
|
|
| sudo tee /usr/local/lib/pkgconfig/history.pc > /dev/null
|
|
|
|
|
pkg-config --exists history || {
|
|
|
|
|
echo "history.pc still not visible to pkg-config" >&2; return 1; }
|
[ADD] bootstrap pacman, makepkg and repo-add natively on s390x
The README lists pacman, bash and coreutils as three missing pieces.
They are not three tasks: pacman is the only one that matters, because
its source tree also ships makepkg and repo-add. Once those run, every
remaining package stops being hand-work and becomes makepkg on the
upstream PKGBUILD.
pacman 7.1.0 builds unpatched on s390x. No cross-compilation is
involved: on native hardware the whole userspace builds at full speed,
which removes the z/VM round-trip the other scripts need.
Measured end to end: zlib built from the official PKGBUILD yields
zlib, zlib-static and minizip, all tagged arch = s390x, the library
reporting "ELF 64-bit MSB shared object, IBM S/390", and repo-add
indexing them into a usable core.db.
--- FR ---
Le README annonce pacman, bash et coreutils comme trois pieces
manquantes. Ce ne sont pas trois travaux : seul pacman compte, parce
que son arbre source livre aussi makepkg et repo-add. Des qu ils
tournent, chaque paquet restant cesse d etre du travail manuel et
devient un makepkg sur le PKGBUILD amont.
pacman 7.1.0 se compile sans correctif sur s390x. Aucune compilation
croisee n intervient : sur du materiel natif tout l espace utilisateur
se batit a pleine vitesse, ce qui supprime l aller-retour z/VM dont
dependent les autres scripts.
Mesure de bout en bout : zlib bati depuis le PKGBUILD officiel produit
zlib, zlib-static et minizip, tous marques arch = s390x, la
bibliotheque se declarant « ELF 64-bit MSB shared object, IBM S/390 »,
et repo-add les indexant dans un core.db utilisable.
Assisted-by: Claude Opus 5
2026-08-15 03:18:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_pacman() {
|
|
|
|
|
log "pacman + makepkg + repo-add"
|
|
|
|
|
mkdir -p "$WORK"
|
|
|
|
|
[ -d "$WORK/pacman" ] || git clone --depth 1 "$PACMAN_GIT" "$WORK/pacman"
|
[FIX] driver: a failed clone rebuilt the package before it
libselinux does not exist in Arch, so its clone 404'd. GitLab answers a
404 by asking for credentials, which is why the log read "could not read
Username" rather than "no such project" -- the first wrong culprit.
The second was mine. Neither the clone nor the cd that follows it was
guarded, so makepkg ran in whatever directory the previous package had
left. It rebuilt util-linux, wrote 119 KB of util-linux output into
log-libselinux.txt, and copied the artefact back into the repository.
The lesson is the repository's oldest one, one level up: an exit code
proves nothing, and neither does a log file's name. Verified by checking
every log against the "==> Making package:" line inside it.
--- FR ---
libselinux n'existe pas dans Arch, son clone a donc rendu un 404. GitLab
répond à un 404 en réclamant des identifiants : d'où le « could not read
Username » du journal, plutôt qu'un « projet inconnu ». Premier faux
coupable.
Le second était de mon fait. Ni le clone ni le cd qui le suit n'étaient
gardés, alors makepkg tournait dans le répertoire laissé par le paquet
précédent. Il a reconstruit util-linux, versé 119 ko de sortie util-linux
dans log-libselinux.txt, puis recopié l'artefact dans le dépôt.
La leçon est la plus ancienne du dépôt, d'un cran plus haut : un code de
sortie ne prouve rien, et le NOM d'un journal non plus. Vérifié en
confrontant chaque journal à la ligne « ==> Making package: » qu'il porte.
Assisted-by: Claude Opus 5
2026-08-17 01:33:41 -04:00
|
|
|
cd "$WORK/pacman" || return 1
|
[ADD] bootstrap pacman, makepkg and repo-add natively on s390x
The README lists pacman, bash and coreutils as three missing pieces.
They are not three tasks: pacman is the only one that matters, because
its source tree also ships makepkg and repo-add. Once those run, every
remaining package stops being hand-work and becomes makepkg on the
upstream PKGBUILD.
pacman 7.1.0 builds unpatched on s390x. No cross-compilation is
involved: on native hardware the whole userspace builds at full speed,
which removes the z/VM round-trip the other scripts need.
Measured end to end: zlib built from the official PKGBUILD yields
zlib, zlib-static and minizip, all tagged arch = s390x, the library
reporting "ELF 64-bit MSB shared object, IBM S/390", and repo-add
indexing them into a usable core.db.
--- FR ---
Le README annonce pacman, bash et coreutils comme trois pieces
manquantes. Ce ne sont pas trois travaux : seul pacman compte, parce
que son arbre source livre aussi makepkg et repo-add. Des qu ils
tournent, chaque paquet restant cesse d etre du travail manuel et
devient un makepkg sur le PKGBUILD amont.
pacman 7.1.0 se compile sans correctif sur s390x. Aucune compilation
croisee n intervient : sur du materiel natif tout l espace utilisateur
se batit a pleine vitesse, ce qui supprime l aller-retour z/VM dont
dependent les autres scripts.
Mesure de bout en bout : zlib bati depuis le PKGBUILD officiel produit
zlib, zlib-static et minizip, tous marques arch = s390x, la
bibliotheque se declarant « ELF 64-bit MSB shared object, IBM S/390 »,
et repo-add les indexant dans un core.db utilisable.
Assisted-by: Claude Opus 5
2026-08-15 03:18:47 -04:00
|
|
|
# /usr/local, never /usr: this host is Ubuntu and /usr belongs to dpkg.
|
|
|
|
|
# makepkg resolves its own libraries from the configured prefix, so the
|
|
|
|
|
# prefix has to be real -- running it from the build tree fails with
|
|
|
|
|
# "/usr/share/makepkg/*.sh: No such file or directory".
|
|
|
|
|
rm -rf build
|
|
|
|
|
meson setup build --prefix=/usr/local --buildtype=release \
|
|
|
|
|
-Ddoc=disabled -Ddoxygen=disabled -Di18n=false
|
|
|
|
|
ninja -C build -j"$(nproc)"
|
|
|
|
|
sudo ninja -C build install
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
configure_makepkg() {
|
|
|
|
|
log "makepkg configuration"
|
|
|
|
|
# CARCH is already detected as s390x by meson; CHOST must stay the
|
|
|
|
|
# auto-detected triplet -- configure scripts are matched against it, and
|
|
|
|
|
# inventing "s390x-pc-linux-gnu" breaks them.
|
|
|
|
|
sudo sed -i "s|^#\?MAKEFLAGS=.*|MAKEFLAGS=\"-j$(nproc)\"|" /etc/makepkg.conf
|
|
|
|
|
# pacman refuses to initialise alpm without its database directory. The
|
|
|
|
|
# error is only a warning during packaging, but it hides real ones.
|
|
|
|
|
sudo mkdir -p /var/lib/pacman
|
[FIX] give the build host Arch's group ids
install: invalid group: '11'
The filesystem package creates directories with `install -g 11`, and
GNU coreutils rejects a gid that resolves to nothing. gid 11 is `ftp`
on Arch; Ubuntu leaves it free.
This is the circular corner of any bootstrap: the package that DEFINES
/etc/group needs groups that do not exist yet. The way out is to give
the build host the target's id map, not to work around the check --
rewriting the install call to force a numeric gid would produce
directories owned by a group the target does not have.
Only the ids Arch uses and Ubuntu lacks are created, and only when
missing, so a host that is already correct is left alone. Checked one
by one: of 1, 2, 10, 11, 12 and 50, only 11 was absent.
--- FR ---
install: invalid group: '11'
Le paquet filesystem cree des repertoires avec « install -g 11 », et
GNU coreutils refuse un gid qui ne resout vers rien. Le gid 11 est
« ftp » sur Arch ; Ubuntu le laisse libre.
C est le coin circulaire de tout amorcage : le paquet qui DEFINIT
/etc/group reclame des groupes qui n existent pas encore. La sortie est
de donner a l hote de compilation la table d identifiants de la cible,
non de contourner la verification -- forcer l interpretation numerique
produirait des repertoires appartenant a un groupe que la cible n a
pas.
Seuls les identifiants qu Arch utilise et qu Ubuntu n a pas sont crees,
et seulement s ils manquent : un hote deja correct n est pas touche.
Verifie un a un : sur 1, 2, 10, 11, 12 et 50, seul le 11 etait absent.
Assisted-by: Claude Opus 5
2026-08-16 22:41:50 -04:00
|
|
|
# Arch's numeric group ids must EXIST on the build host.
|
|
|
|
|
#
|
|
|
|
|
# The filesystem package creates directories with `install -g 11`, and
|
|
|
|
|
# GNU coreutils rejects a gid that resolves to nothing:
|
|
|
|
|
#
|
|
|
|
|
# install: invalid group: '11'
|
|
|
|
|
#
|
|
|
|
|
# gid 11 is `ftp` on Arch; Ubuntu leaves it free. This is the circular
|
|
|
|
|
# corner of any bootstrap -- the package that DEFINES /etc/group needs
|
|
|
|
|
# groups that do not exist yet -- and the way out is to give the build
|
|
|
|
|
# host the target's id map rather than to work around the check.
|
|
|
|
|
#
|
|
|
|
|
# Only the ids Arch uses and Ubuntu lacks are created, and only when
|
|
|
|
|
# missing, so an already-correct host is left alone.
|
|
|
|
|
if ! getent group 11 > /dev/null 2>&1; then
|
|
|
|
|
sudo groupadd -g 11 ftp
|
|
|
|
|
echo "created group ftp (gid 11), required by the filesystem package"
|
|
|
|
|
fi
|
[FIX] canonical CHOST, and a reachable libassuan source
CHOST was the Debian-style triplet. gcc -dumpmachine reports
s390x-linux-gnu on this host, but config.sub canonicalises that to
s390x-ibm-linux-gnu and GCC builds its tree under the canonical name.
Arch PKGBUILDs assume the canonical form -- theirs is
x86_64-pc-linux-gnu, vendor field present -- so gcc's own PKGBUILD
looked for $CHOST/libstdc++-v3/doc and found nothing:
make: *** s390x-linux-gnu/libstdc++-v3/doc: No such file or directory
while the build had created s390x-ibm-linux-gnu/libstdc++-v3/doc. This
is a port-wide setting, not a gcc quirk: every PKGBUILD that derives a
path from CHOST was pointing one directory sideways.
libassuan fetches from dev.gnupg.org, which is unreachable from this
build host -- measured HTTP 000, while github.com/gpg/libassuan.git and
gnupg.org/ftp both answer. That is a network fact, not a port problem,
so only the transport changes: the pinned tag is untouched and what
gets built is what Arch specifies.
Host dependencies again: doxygen for xz, libunistring for libpsl,
systemd-dev for util-linux. Every one of them was invisible until a
build stopped on it, because --nodeps means pacman never checks
makedepends.
--- FR ---
CHOST portait le triplet de style Debian. Sur cet hote, gcc
-dumpmachine rend s390x-linux-gnu, mais config.sub le canonise en
s390x-ibm-linux-gnu, et GCC batit son arbre sous le nom canonique.
Les PKGBUILD d Arch supposent la forme canonique -- la leur est
x86_64-pc-linux-gnu, champ constructeur present -- si bien que le
PKGBUILD de gcc cherchait $CHOST/libstdc++-v3/doc sans rien trouver :
make: *** s390x-linux-gnu/libstdc++-v3/doc: No such file or directory
alors que la compilation avait cree s390x-ibm-linux-gnu/libstdc++-v3/doc.
C est un reglage de portage, pas une bizarrerie de gcc : tout PKGBUILD
derivant un chemin de CHOST visait un repertoire a cote.
libassuan se telecharge depuis dev.gnupg.org, injoignable depuis cet
hote -- mesure : HTTP 000, quand github.com/gpg/libassuan.git et
gnupg.org/ftp repondent tous deux. C est un fait de reseau, pas un
probleme de portage : seul le transport change, l etiquette epinglee
reste intacte et ce qui se batit est ce qu Arch specifie.
Dependances d hote, encore : doxygen pour xz, libunistring pour libpsl,
systemd-dev pour util-linux. Chacune est restee invisible jusqu a ce
qu une compilation s y arrete, parce que --nodeps interdit a pacman de
verifier les makedepends.
Assisted-by: Claude Opus 5
2026-08-16 00:45:50 -04:00
|
|
|
# CHOST must be the CANONICAL triplet, not the Debian-style one.
|
|
|
|
|
#
|
|
|
|
|
# gcc -dumpmachine reports s390x-linux-gnu here, but config.sub
|
|
|
|
|
# canonicalises that to s390x-ibm-linux-gnu, and GCC builds its tree
|
|
|
|
|
# under the canonical name. Arch PKGBUILDs assume the canonical form --
|
|
|
|
|
# theirs is x86_64-pc-linux-gnu, with the vendor field present -- so
|
|
|
|
|
# gcc's own PKGBUILD looked for $CHOST/libstdc++-v3/doc and found
|
|
|
|
|
# nothing:
|
|
|
|
|
#
|
|
|
|
|
# make: *** s390x-linux-gnu/libstdc++-v3/doc: No such file or directory
|
|
|
|
|
#
|
|
|
|
|
# while the build had created s390x-ibm-linux-gnu/libstdc++-v3/doc.
|
|
|
|
|
sudo sed -i 's|^CHOST=.*|CHOST="s390x-ibm-linux-gnu"|' /etc/makepkg.conf
|
[FIX] makepkg.conf: .la files in a third of the repository
This host was configured with `libtool staticlibs`, which KEEPS what Arch
strips. Fifty-six of a hundred and fifty-nine packages carried .la files, and
nothing reported it until two sub-packages of one source both claimed the
same file:
/usr/lib/libcrypt.la exists in both 'libxcrypt' and 'libxcrypt-compat'
That is what .la files are for -- they record a link line -- so a split
library produces two descriptions of itself. Arch removes them because
nothing in a modern toolchain reads them and the paths they record are wrong
as soon as a package moves. OPTIONS now matches Arch, minus debug and lto:
debug wants a source-package pipeline this bootstrap has no use for, and lto
doubles a stage whose output stage 2 discards.
libnspr4-dev and mercurial came with nss. The nspr distinction is worth
keeping: the host had NOTHING, which the ordinary stage-1 rule fixes with a
host package. libgcrypt needed a hook because the host had something too OLD
-- 1.51 against a floor of 1.56 -- and no installation fixes that.
--- FR ---
Cet hôte était configuré avec `libtool staticlibs`, qui CONSERVE ce qu'Arch
retire. Cinquante-six paquets sur cent cinquante-neuf portaient des fichiers
.la, et rien ne l'avait signalé jusqu'à ce que deux sous-paquets d'une même
source réclament le même fichier :
/usr/lib/libcrypt.la exists in both 'libxcrypt' et 'libxcrypt-compat'
C'est à cela que servent les .la — ils consignent une ligne de liaison — donc
une bibliothèque scindée produit deux descriptions d'elle-même. Arch les
supprime parce que rien dans une chaîne moderne ne les lit et que les chemins
qu'ils consignent sont faux dès qu'un paquet se déplace. OPTIONS suit
désormais Arch, sauf debug et lto : debug réclame un pipeline de paquets
sources dont cet amorçage n'a que faire, et lto double une étape dont l'étage
2 jette la sortie.
libnspr4-dev et mercurial sont venus avec nss. La distinction sur nspr mérite
d'être gardée : l'hôte n'avait RIEN, ce que la règle ordinaire de l'étage 1
corrige par un paquet hôte. libgcrypt a exigé un crochet parce que l'hôte
avait quelque chose de trop VIEUX — 1.51 contre un plancher de 1.56 — et
qu'aucune installation ne corrige cela.
Assisted-by: Claude Opus 5
2026-08-19 08:30:49 -04:00
|
|
|
# OPTIONS, aligned with Arch's own defaults.
|
|
|
|
|
#
|
|
|
|
|
# This host was configured with `libtool staticlibs`, which KEEPS the .la
|
|
|
|
|
# files and the .a archives that Arch strips. Fifty-six of a hundred and
|
|
|
|
|
# fifty-nine packages carried .la files as a result -- a third of the
|
|
|
|
|
# repository diverging from Arch in a way nothing reported, until two
|
|
|
|
|
# sub-packages of the same source both claimed one:
|
|
|
|
|
#
|
|
|
|
|
# error: failed to commit transaction (conflicting files)
|
|
|
|
|
# /usr/lib/libcrypt.la exists in both 'libxcrypt' and 'libxcrypt-compat'
|
|
|
|
|
#
|
|
|
|
|
# That is what .la files are for: they record a link line, so two packages
|
|
|
|
|
# splitting one library both want to describe it. Arch removes them
|
|
|
|
|
# because nothing in a modern toolchain reads them and the paths they
|
|
|
|
|
# record are wrong the moment a package is relocated.
|
|
|
|
|
#
|
|
|
|
|
# debug and lto stay OFF, unlike Arch: debug wants a source-package
|
|
|
|
|
# pipeline this bootstrap has no use for, and lto doubles compile time on
|
|
|
|
|
# a stage whose output stage 2 discards anyway. autodeps stays off because
|
|
|
|
|
# it is makepkg's own default; TODO.md records what that costs.
|
|
|
|
|
sudo sed -i 's|^OPTIONS=.*|OPTIONS=(strip docs !libtool !staticlibs emptydirs zipman purge !debug !lto !autodeps)|' /etc/makepkg.conf
|
|
|
|
|
grep -E '^(CARCH|CHOST|MAKEFLAGS|OPTIONS)=' /etc/makepkg.conf
|
[ADD] bootstrap pacman, makepkg and repo-add natively on s390x
The README lists pacman, bash and coreutils as three missing pieces.
They are not three tasks: pacman is the only one that matters, because
its source tree also ships makepkg and repo-add. Once those run, every
remaining package stops being hand-work and becomes makepkg on the
upstream PKGBUILD.
pacman 7.1.0 builds unpatched on s390x. No cross-compilation is
involved: on native hardware the whole userspace builds at full speed,
which removes the z/VM round-trip the other scripts need.
Measured end to end: zlib built from the official PKGBUILD yields
zlib, zlib-static and minizip, all tagged arch = s390x, the library
reporting "ELF 64-bit MSB shared object, IBM S/390", and repo-add
indexing them into a usable core.db.
--- FR ---
Le README annonce pacman, bash et coreutils comme trois pieces
manquantes. Ce ne sont pas trois travaux : seul pacman compte, parce
que son arbre source livre aussi makepkg et repo-add. Des qu ils
tournent, chaque paquet restant cesse d etre du travail manuel et
devient un makepkg sur le PKGBUILD amont.
pacman 7.1.0 se compile sans correctif sur s390x. Aucune compilation
croisee n intervient : sur du materiel natif tout l espace utilisateur
se batit a pleine vitesse, ce qui supprime l aller-retour z/VM dont
dependent les autres scripts.
Mesure de bout en bout : zlib bati depuis le PKGBUILD officiel produit
zlib, zlib-static et minizip, tous marques arch = s390x, la
bibliotheque se declarant « ELF 64-bit MSB shared object, IBM S/390 »,
et repo-add les indexant dans un core.db utilisable.
Assisted-by: Claude Opus 5
2026-08-15 03:18:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# build_package <name> -- fetch the official PKGBUILD and build it for s390x.
|
|
|
|
|
#
|
|
|
|
|
# --ignorearch: upstream PKGBUILDs carry arch=(x86_64) and nothing else.
|
|
|
|
|
# --skipchecksums: GitLab regenerates .patch URLs, so their checksums drift
|
|
|
|
|
# from what the PKGBUILD recorded. Release tarballs still validate; only
|
|
|
|
|
# the generated patches are skipped.
|
[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
2026-08-15 20:40:17 -04:00
|
|
|
# --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.
|
[ADD] bootstrap pacman, makepkg and repo-add natively on s390x
The README lists pacman, bash and coreutils as three missing pieces.
They are not three tasks: pacman is the only one that matters, because
its source tree also ships makepkg and repo-add. Once those run, every
remaining package stops being hand-work and becomes makepkg on the
upstream PKGBUILD.
pacman 7.1.0 builds unpatched on s390x. No cross-compilation is
involved: on native hardware the whole userspace builds at full speed,
which removes the z/VM round-trip the other scripts need.
Measured end to end: zlib built from the official PKGBUILD yields
zlib, zlib-static and minizip, all tagged arch = s390x, the library
reporting "ELF 64-bit MSB shared object, IBM S/390", and repo-add
indexing them into a usable core.db.
--- FR ---
Le README annonce pacman, bash et coreutils comme trois pieces
manquantes. Ce ne sont pas trois travaux : seul pacman compte, parce
que son arbre source livre aussi makepkg et repo-add. Des qu ils
tournent, chaque paquet restant cesse d etre du travail manuel et
devient un makepkg sur le PKGBUILD amont.
pacman 7.1.0 se compile sans correctif sur s390x. Aucune compilation
croisee n intervient : sur du materiel natif tout l espace utilisateur
se batit a pleine vitesse, ce qui supprime l aller-retour z/VM dont
dependent les autres scripts.
Mesure de bout en bout : zlib bati depuis le PKGBUILD officiel produit
zlib, zlib-static et minizip, tous marques arch = s390x, la
bibliotheque se declarant « ELF 64-bit MSB shared object, IBM S/390 »,
et repo-add les indexant dans un core.db utilisable.
Assisted-by: Claude Opus 5
2026-08-15 03:18:47 -04:00
|
|
|
build_package() {
|
|
|
|
|
local name="$1"
|
|
|
|
|
log "Building $name"
|
[ADD] driver: refuse to build below 8 GiB free
A full disk does not say so. gcc's bootstrap reported
genattrtab: cannot close file tmp-attrtab.cc: No space left on device
seventeen thousand lines into its log, behind two hundred lines of make
recursion. Everything visible pointed at gcc, and the first grep for
"error:" matched cpp_error() -- a function name in gcc's own source, the
documented trap of grepping a whole file instead of the right part.
df would have said it in one line, before the forty minutes.
This host is shared, and the free margin is not stable, so it is checked per
package rather than assumed once. 8 GiB clears gcc, the largest build here;
smaller packages never trip it. The message names the reclaim command,
because the answer is not obvious either: the src trees are regenerable,
makepkg -C wipes them anyway.
--- FR ---
Un disque plein ne le dit pas. L'amorçage de gcc a signalé
genattrtab: cannot close file tmp-attrtab.cc: No space left on device
dix-sept mille lignes plus bas dans son journal, derrière deux cents lignes
de récursion make. Tout ce qui était visible accusait gcc, et le premier
grep sur « error: » est tombé sur cpp_error() — un nom de fonction dans les
sources de gcc, précisément le piège documenté qui consiste à grep un
fichier entier plutôt que le bon endroit.
df l'aurait dit en une ligne, avant les quarante minutes.
Cet hôte est partagé et la marge libre n'est pas stable : la vérification se
fait donc par paquet, sans rien supposer. 8 GiB suffisent à gcc, le plus
gros build ici ; les petits paquets ne la déclencheront jamais. Le message
nomme la commande de récupération, car la réponse n'est pas évidente non
plus : les arbres src se régénèrent, makepkg -C les efface de toute façon.
Assisted-by: Claude Opus 5
2026-08-17 03:14:40 -04:00
|
|
|
# Free space, checked before the build rather than discovered inside it.
|
|
|
|
|
#
|
|
|
|
|
# A full disk does not say so. gcc's stage-2 bootstrap reported
|
|
|
|
|
#
|
|
|
|
|
# genattrtab: cannot close file tmp-attrtab.cc: No space left on device
|
|
|
|
|
#
|
|
|
|
|
# seventeen thousand lines into its log, behind two hundred lines of make
|
|
|
|
|
# recursion -- and the first grep for "error:" matched cpp_error(), a
|
|
|
|
|
# function name in gcc's own source. Every symptom pointed at gcc.
|
|
|
|
|
#
|
|
|
|
|
# This host is shared with running VMs whose disk images grow, so the
|
|
|
|
|
# margin is not stable and cannot be assumed. 8 GiB clears gcc, the
|
|
|
|
|
# largest build here; a smaller package will simply never trip it.
|
|
|
|
|
local free_mb
|
|
|
|
|
free_mb=$(df -Pm "$WORK" | awk 'NR==2 {print $4}')
|
|
|
|
|
if [ "${free_mb:-0}" -lt 8192 ]; then
|
|
|
|
|
echo "only ${free_mb} MiB free under $WORK; need 8192" >&2
|
|
|
|
|
echo "reclaim with: rm -rf $WORK/pkg/*/src (makepkg -C re-extracts)" >&2
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
[ADD] bootstrap pacman, makepkg and repo-add natively on s390x
The README lists pacman, bash and coreutils as three missing pieces.
They are not three tasks: pacman is the only one that matters, because
its source tree also ships makepkg and repo-add. Once those run, every
remaining package stops being hand-work and becomes makepkg on the
upstream PKGBUILD.
pacman 7.1.0 builds unpatched on s390x. No cross-compilation is
involved: on native hardware the whole userspace builds at full speed,
which removes the z/VM round-trip the other scripts need.
Measured end to end: zlib built from the official PKGBUILD yields
zlib, zlib-static and minizip, all tagged arch = s390x, the library
reporting "ELF 64-bit MSB shared object, IBM S/390", and repo-add
indexing them into a usable core.db.
--- FR ---
Le README annonce pacman, bash et coreutils comme trois pieces
manquantes. Ce ne sont pas trois travaux : seul pacman compte, parce
que son arbre source livre aussi makepkg et repo-add. Des qu ils
tournent, chaque paquet restant cesse d etre du travail manuel et
devient un makepkg sur le PKGBUILD amont.
pacman 7.1.0 se compile sans correctif sur s390x. Aucune compilation
croisee n intervient : sur du materiel natif tout l espace utilisateur
se batit a pleine vitesse, ce qui supprime l aller-retour z/VM dont
dependent les autres scripts.
Mesure de bout en bout : zlib bati depuis le PKGBUILD officiel produit
zlib, zlib-static et minizip, tous marques arch = s390x, la
bibliotheque se declarant « ELF 64-bit MSB shared object, IBM S/390 »,
et repo-add les indexant dans un core.db utilisable.
Assisted-by: Claude Opus 5
2026-08-15 03:18:47 -04:00
|
|
|
mkdir -p "$WORK/pkg"
|
[FIX] driver: a failed clone rebuilt the package before it
libselinux does not exist in Arch, so its clone 404'd. GitLab answers a
404 by asking for credentials, which is why the log read "could not read
Username" rather than "no such project" -- the first wrong culprit.
The second was mine. Neither the clone nor the cd that follows it was
guarded, so makepkg ran in whatever directory the previous package had
left. It rebuilt util-linux, wrote 119 KB of util-linux output into
log-libselinux.txt, and copied the artefact back into the repository.
The lesson is the repository's oldest one, one level up: an exit code
proves nothing, and neither does a log file's name. Verified by checking
every log against the "==> Making package:" line inside it.
--- FR ---
libselinux n'existe pas dans Arch, son clone a donc rendu un 404. GitLab
répond à un 404 en réclamant des identifiants : d'où le « could not read
Username » du journal, plutôt qu'un « projet inconnu ». Premier faux
coupable.
Le second était de mon fait. Ni le clone ni le cd qui le suit n'étaient
gardés, alors makepkg tournait dans le répertoire laissé par le paquet
précédent. Il a reconstruit util-linux, versé 119 ko de sortie util-linux
dans log-libselinux.txt, puis recopié l'artefact dans le dépôt.
La leçon est la plus ancienne du dépôt, d'un cran plus haut : un code de
sortie ne prouve rien, et le NOM d'un journal non plus. Vérifié en
confrontant chaque journal à la ligne « ==> Making package: » qu'il porte.
Assisted-by: Claude Opus 5
2026-08-17 01:33:41 -04:00
|
|
|
# Both guards are load-bearing, and their absence cost a whole run.
|
|
|
|
|
#
|
|
|
|
|
# gitlab.archlinux.org answers a 404 by asking for credentials, so a
|
|
|
|
|
# package that does not exist fails as
|
|
|
|
|
#
|
|
|
|
|
# fatal: could not read Username for 'https://gitlab.archlinux.org'
|
|
|
|
|
#
|
|
|
|
|
# GIT_TERMINAL_PROMPT=0 turns that into an immediate error instead of a
|
|
|
|
|
# process waiting on a terminal that is not there.
|
|
|
|
|
#
|
|
|
|
|
# Then the cd. With neither guarded, a failed clone left makepkg running
|
|
|
|
|
# in whatever directory the PREVIOUS package used -- it rebuilt that
|
|
|
|
|
# package, wrote the output into THIS package's log, and copied the
|
|
|
|
|
# artefact back into the repository. log-libselinux.txt was 119 KB of
|
|
|
|
|
# util-linux. The lesson is the repository's oldest one, one level up:
|
|
|
|
|
# an exit code proves nothing, and neither does a log file's NAME.
|
|
|
|
|
if [ ! -d "$WORK/pkg/$name" ]; then
|
|
|
|
|
GIT_TERMINAL_PROMPT=0 \
|
|
|
|
|
git clone --depth 1 "$PKG_GIT_BASE/$name.git" "$WORK/pkg/$name" || {
|
|
|
|
|
rm -rf "$WORK/pkg/$name"
|
|
|
|
|
echo "clone failed: $PKG_GIT_BASE/$name.git" >&2
|
|
|
|
|
return 1
|
|
|
|
|
}
|
|
|
|
|
fi
|
|
|
|
|
cd "$WORK/pkg/$name" || return 1
|
[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
2026-08-15 20:40:17 -04:00
|
|
|
# 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.
|
[FIX] clean the source tree between attempts; strip gcc _pick lines
Four packages -- grep, gnupg, pacman and curl -- were failing on my own
driver, not on the port. makepkg -f rebuilds but does not wipe $srcdir,
so a re-run re-entered the previous attempt's tree:
patch: ... already exists! Skipping patch.
1 out of 1 hunk ignored
mkdir: build-curl-compat: File exists
makepkg -C now cleans first. Worth stating plainly: those four looked
like port problems for two full rounds, and were not.
gcc: dropping sub-packages from pkgname was not enough. package_gcc()
_picks files out for every front end regardless of what was requested,
and _pick is a mv, so it fails on what was never built:
mv: cannot stat 'usr/bin/gnat': No such file or directory
The _pick lines for the disabled front ends are removed too.
shadow needed libaudit-dev on the host -- one more makedepend that
--nodeps hides until a build stops on it.
--- FR ---
Quatre paquets -- grep, gnupg, pacman et curl -- echouaient a cause de
mon propre pilote, pas du portage. makepkg -f reconstruit mais ne vide
pas $srcdir, si bien qu une reprise revenait dans l arbre de la
tentative precedente :
patch: ... already exists! Skipping patch.
1 out of 1 hunk ignored
mkdir: build-curl-compat: File exists
makepkg -C nettoie desormais d abord. A dire clairement : ces quatre-la
ont eu l air de problemes de portage pendant deux tours entiers, et ne
l etaient pas.
gcc : retirer les sous-paquets de pkgname ne suffisait pas.
package_gcc() extrait des fichiers pour chaque frontal quoi qu on ait
demande, et _pick est un mv, donc il echoue sur ce qui n a jamais ete
bati :
mv: cannot stat 'usr/bin/gnat': No such file or directory
Les lignes _pick des frontaux desactives sont retirees aussi.
shadow reclamait libaudit-dev sur l hote -- un makedepend de plus que
--nodeps masque jusqu a ce qu une compilation s y arrete.
Assisted-by: Claude Opus 5
2026-08-16 02:23:01 -04:00
|
|
|
# -C wipes $srcdir first. Without it a re-run inherits the previous
|
|
|
|
|
# attempt's tree, and prepare() fails on work it already did:
|
|
|
|
|
# patch: ... already exists! Skipping patch.
|
|
|
|
|
# 1 out of 1 hunk ignored
|
|
|
|
|
# mkdir: build-curl-compat: File exists
|
|
|
|
|
# grep, gnupg, pacman and curl all failed this way -- not on the
|
|
|
|
|
# port, but on my own driver re-entering a dirty directory.
|
[FIX] host defaults: apt was deciding what got built
--auto-features enabled turns every auto feature into a requirement, so
installing a tool switches on code that never compiled here. Three of the
fifty host packages did exactly that, and only one failed for the reason
it named.
expat had built clean the day before. asciidoc pulled docbook-utils in as
an automatic dependency; it owns docbook2man, the third name in expat's
find_program list, so docs defaulted ON twenty-nine hours before anything
rebuilt. That tool is the SGML pipeline: on DocBook XML it writes nothing
and still exits 0, and the mv it feeds is what reported the failure. Arch
ships no xmlwf.1 either, so OFF is parity.
systemd's split-bin probes the BUILD host's /usr/sbin. Ubuntu's is a real
directory, so six binaries went where package() does not look -- and
arch-meson's --sbindir is ignored, systemd computes its own.
util-linux needed no option: poman-translate.sh greps po4a for the English
"Discard" and this host answers "Rejet de". The locale belongs to the host,
so it is pinned once on the makepkg line.
--- FR ---
--auto-features enabled fait de chaque fonction « auto » une exigence :
installer un outil active donc du code jamais compilé ici. Trois des
cinquante paquets hôte l'ont fait, et un seul a échoué pour la raison
qu'il annonçait.
expat compilait proprement la veille. asciidoc avait tiré docbook-utils en
dépendance automatique ; il fournit docbook2man, troisième nom de la liste
find_program d'expat, et la doc est passée à ON vingt-neuf heures avant
toute reconstruction. Cet outil est le pipeline SGML : sur du DocBook XML
il n'écrit rien et sort quand même 0, et le mv qu'il alimente est ce qui a
signalé la panne. Arch ne livre pas xmlwf.1 non plus : OFF, c'est la parité.
Le split-bin de systemd sonde le /usr/sbin de la machine de BUILD. Celui
d'Ubuntu est un vrai répertoire, donc six binaires sont partis là où
package() ne regarde pas — et le --sbindir d'arch-meson est ignoré, systemd
calcule le sien.
util-linux n'avait besoin d'aucune option : poman-translate.sh cherche le
« Discard » anglais de po4a, et cet hôte répond « Rejet de ». La locale
appartient à l'hôte : elle est épinglée une fois, sur la ligne makepkg.
Assisted-by: Claude Opus 5
2026-08-17 02:37:46 -04:00
|
|
|
# LC_ALL=C.UTF-8, because build systems parse their tools' output.
|
|
|
|
|
#
|
|
|
|
|
# This host runs LANG=fr_FR.UTF-8. util-linux's poman-translate.sh reads
|
|
|
|
|
# po4a's report and skips what it says it discarded:
|
|
|
|
|
#
|
|
|
|
|
# DISCARDED_TRANSLATION=$(echo "$line" | awk '/Discard/ {print $2;}')
|
|
|
|
|
#
|
|
|
|
|
# -- an English word matched against a gettext-translated message. In
|
|
|
|
|
# French po4a prints "Rejet de ar/..." instead, so the skip list came out
|
|
|
|
|
# empty, asciidoctor was handed 852 files po4a had never written, and the
|
|
|
|
|
# build died on the first. Note $2 is "de" in French: even a locale-aware
|
|
|
|
|
# pattern would take the wrong field.
|
|
|
|
|
#
|
|
|
|
|
# It went unseen for a second reason -- the script captures po4a in
|
|
|
|
|
# `output=$(...)`, so none of those 852 lines reach the log at all.
|
|
|
|
|
#
|
|
|
|
|
# The locale is a property of THIS host, not of any one package, and any
|
|
|
|
|
# build that greps English tool output is exposed. So it is pinned here,
|
|
|
|
|
# once, rather than in a hook per package. C.UTF-8 and not C: the Arabic
|
|
|
|
|
# and Ukrainian pages must stay valid UTF-8. Arch's own build chroot runs
|
|
|
|
|
# in this locale, so this makes us match it rather than diverge.
|
[FIX] python packages: /usr/local, once, for all of them
Debian patches sysconfig to prefer the "posix_local" scheme, so every
wheel-installing PKGBUILD ships /usr/local -- a tree Arch reserves and whose
every path the filesystem package owns. pacman refuses the transaction:
error: failed to commit transaction (conflicting files)
/usr/local/share/man exists in both 'filesystem' and 'meson'
Four packages hit it. Two were dropped for other reasons. Rather than write a
third and fourth relocation hook, build_package now exports
DEB_PYTHON_INSTALL_LAYOUT=deb_system, which moves the default from
/usr/local/lib/python3.13/dist-packages to /usr/lib/python3/dist-packages and
scripts from /usr/local/bin to /usr/bin. One line, every python package,
including ones not built yet.
It does not finish the job: deb_system still says dist-packages and Arch reads
site-packages. That move stays per-package, because only modules actually
imported on the target need it. meson does, and its hook does it -- targeting
the version of the python PACKAGE in repo/s390x, not the interpreter running
the build. Installed under the host's 3.13, /usr/bin/meson runs in the chroot
and then says ModuleNotFoundError, because the chroot's python is our 3.14 and
never looks in 3.13.
--- FR ---
Debian modifie sysconfig pour préférer le schéma « posix_local » : tout
PKGBUILD installant une roue livre donc /usr/local, arbre qu'Arch réserve et
dont le paquet filesystem possède chaque chemin. pacman refuse la transaction :
error: failed to commit transaction (conflicting files)
/usr/local/share/man exists in both 'filesystem' et 'meson'
Quatre paquets l'ont rencontré. Deux ont été écartés pour d'autres raisons.
Plutôt que d'écrire un troisième et un quatrième crochet de relocalisation,
build_package exporte désormais DEB_PYTHON_INSTALL_LAYOUT=deb_system, qui
déplace le défaut de /usr/local/lib/python3.13/dist-packages vers
/usr/lib/python3/dist-packages, et les scripts de /usr/local/bin vers /usr/bin.
Une ligne, tous les paquets python, y compris ceux pas encore bâtis.
Cela ne termine pas le travail : deb_system dit encore dist-packages quand
Arch lit site-packages. Ce déplacement reste par paquet, car seuls les modules
réellement importés sur la cible en ont besoin. meson en fait partie, et son
crochet le fait — en visant la version du PAQUET python de repo/s390x, non
l'interpréteur qui exécute la compilation. Installé sous le 3.13 de l'hôte,
/usr/bin/meson démarre dans le chroot puis annonce ModuleNotFoundError, le
python du chroot étant notre 3.14, qui ne regarde jamais dans 3.13.
Assisted-by: Claude Opus 5
2026-08-19 20:19:37 -04:00
|
|
|
# DEB_PYTHON_INSTALL_LAYOUT=deb_system, because Debian's python installs
|
|
|
|
|
# into /usr/local and an Arch package may not ship that tree.
|
|
|
|
|
#
|
|
|
|
|
# $ python3 -c 'import sysconfig; print(sysconfig.get_default_scheme(),
|
|
|
|
|
# sysconfig.get_path("purelib"), sysconfig.get_path("scripts"))'
|
|
|
|
|
# posix_local /usr/local/lib/python3.13/dist-packages /usr/local/bin
|
|
|
|
|
# $ DEB_PYTHON_INSTALL_LAYOUT=deb_system python3 -c '...'
|
|
|
|
|
# deb_system /usr/lib/python3/dist-packages /usr/bin
|
|
|
|
|
#
|
|
|
|
|
# Without it every wheel-installing PKGBUILD ships /usr/local, and the
|
|
|
|
|
# filesystem package owns every path in there -- including
|
|
|
|
|
# usr/local/share/man, which it ships as a SYMLINK. pacman then refuses the
|
|
|
|
|
# whole transaction:
|
|
|
|
|
#
|
|
|
|
|
# error: failed to commit transaction (conflicting files)
|
|
|
|
|
# /usr/local/share/man exists in both 'filesystem' and 'meson'
|
|
|
|
|
#
|
|
|
|
|
# Four packages hit this before it was fixed here rather than in each of
|
|
|
|
|
# them: python-brotli and python-libseccomp (both dropped for other
|
|
|
|
|
# reasons), meson and python-tqdm. Setting it once covers every python
|
|
|
|
|
# package, including ones not built yet.
|
|
|
|
|
#
|
|
|
|
|
# It does NOT finish the job: deb_system still says dist-packages, and
|
|
|
|
|
# Arch's python reads site-packages. That last move stays per-package,
|
|
|
|
|
# because only the packages whose modules are actually IMPORTED on the
|
|
|
|
|
# target need it -- meson does, and its hook does it.
|
[FIX] host defaults: apt was deciding what got built
--auto-features enabled turns every auto feature into a requirement, so
installing a tool switches on code that never compiled here. Three of the
fifty host packages did exactly that, and only one failed for the reason
it named.
expat had built clean the day before. asciidoc pulled docbook-utils in as
an automatic dependency; it owns docbook2man, the third name in expat's
find_program list, so docs defaulted ON twenty-nine hours before anything
rebuilt. That tool is the SGML pipeline: on DocBook XML it writes nothing
and still exits 0, and the mv it feeds is what reported the failure. Arch
ships no xmlwf.1 either, so OFF is parity.
systemd's split-bin probes the BUILD host's /usr/sbin. Ubuntu's is a real
directory, so six binaries went where package() does not look -- and
arch-meson's --sbindir is ignored, systemd computes its own.
util-linux needed no option: poman-translate.sh greps po4a for the English
"Discard" and this host answers "Rejet de". The locale belongs to the host,
so it is pinned once on the makepkg line.
--- FR ---
--auto-features enabled fait de chaque fonction « auto » une exigence :
installer un outil active donc du code jamais compilé ici. Trois des
cinquante paquets hôte l'ont fait, et un seul a échoué pour la raison
qu'il annonçait.
expat compilait proprement la veille. asciidoc avait tiré docbook-utils en
dépendance automatique ; il fournit docbook2man, troisième nom de la liste
find_program d'expat, et la doc est passée à ON vingt-neuf heures avant
toute reconstruction. Cet outil est le pipeline SGML : sur du DocBook XML
il n'écrit rien et sort quand même 0, et le mv qu'il alimente est ce qui a
signalé la panne. Arch ne livre pas xmlwf.1 non plus : OFF, c'est la parité.
Le split-bin de systemd sonde le /usr/sbin de la machine de BUILD. Celui
d'Ubuntu est un vrai répertoire, donc six binaires sont partis là où
package() ne regarde pas — et le --sbindir d'arch-meson est ignoré, systemd
calcule le sien.
util-linux n'avait besoin d'aucune option : poman-translate.sh cherche le
« Discard » anglais de po4a, et cet hôte répond « Rejet de ». La locale
appartient à l'hôte : elle est épinglée une fois, sur la ligne makepkg.
Assisted-by: Claude Opus 5
2026-08-17 02:37:46 -04:00
|
|
|
LC_ALL=C.UTF-8 \
|
[FIX] python packages: /usr/local, once, for all of them
Debian patches sysconfig to prefer the "posix_local" scheme, so every
wheel-installing PKGBUILD ships /usr/local -- a tree Arch reserves and whose
every path the filesystem package owns. pacman refuses the transaction:
error: failed to commit transaction (conflicting files)
/usr/local/share/man exists in both 'filesystem' and 'meson'
Four packages hit it. Two were dropped for other reasons. Rather than write a
third and fourth relocation hook, build_package now exports
DEB_PYTHON_INSTALL_LAYOUT=deb_system, which moves the default from
/usr/local/lib/python3.13/dist-packages to /usr/lib/python3/dist-packages and
scripts from /usr/local/bin to /usr/bin. One line, every python package,
including ones not built yet.
It does not finish the job: deb_system still says dist-packages and Arch reads
site-packages. That move stays per-package, because only modules actually
imported on the target need it. meson does, and its hook does it -- targeting
the version of the python PACKAGE in repo/s390x, not the interpreter running
the build. Installed under the host's 3.13, /usr/bin/meson runs in the chroot
and then says ModuleNotFoundError, because the chroot's python is our 3.14 and
never looks in 3.13.
--- FR ---
Debian modifie sysconfig pour préférer le schéma « posix_local » : tout
PKGBUILD installant une roue livre donc /usr/local, arbre qu'Arch réserve et
dont le paquet filesystem possède chaque chemin. pacman refuse la transaction :
error: failed to commit transaction (conflicting files)
/usr/local/share/man exists in both 'filesystem' et 'meson'
Quatre paquets l'ont rencontré. Deux ont été écartés pour d'autres raisons.
Plutôt que d'écrire un troisième et un quatrième crochet de relocalisation,
build_package exporte désormais DEB_PYTHON_INSTALL_LAYOUT=deb_system, qui
déplace le défaut de /usr/local/lib/python3.13/dist-packages vers
/usr/lib/python3/dist-packages, et les scripts de /usr/local/bin vers /usr/bin.
Une ligne, tous les paquets python, y compris ceux pas encore bâtis.
Cela ne termine pas le travail : deb_system dit encore dist-packages quand
Arch lit site-packages. Ce déplacement reste par paquet, car seuls les modules
réellement importés sur la cible en ont besoin. meson en fait partie, et son
crochet le fait — en visant la version du PAQUET python de repo/s390x, non
l'interpréteur qui exécute la compilation. Installé sous le 3.13 de l'hôte,
/usr/bin/meson démarre dans le chroot puis annonce ModuleNotFoundError, le
python du chroot étant notre 3.14, qui ne regarde jamais dans 3.13.
Assisted-by: Claude Opus 5
2026-08-19 20:19:37 -04:00
|
|
|
DEB_PYTHON_INSTALL_LAYOUT=deb_system \
|
[FIX] clean the source tree between attempts; strip gcc _pick lines
Four packages -- grep, gnupg, pacman and curl -- were failing on my own
driver, not on the port. makepkg -f rebuilds but does not wipe $srcdir,
so a re-run re-entered the previous attempt's tree:
patch: ... already exists! Skipping patch.
1 out of 1 hunk ignored
mkdir: build-curl-compat: File exists
makepkg -C now cleans first. Worth stating plainly: those four looked
like port problems for two full rounds, and were not.
gcc: dropping sub-packages from pkgname was not enough. package_gcc()
_picks files out for every front end regardless of what was requested,
and _pick is a mv, so it fails on what was never built:
mv: cannot stat 'usr/bin/gnat': No such file or directory
The _pick lines for the disabled front ends are removed too.
shadow needed libaudit-dev on the host -- one more makedepend that
--nodeps hides until a build stops on it.
--- FR ---
Quatre paquets -- grep, gnupg, pacman et curl -- echouaient a cause de
mon propre pilote, pas du portage. makepkg -f reconstruit mais ne vide
pas $srcdir, si bien qu une reprise revenait dans l arbre de la
tentative precedente :
patch: ... already exists! Skipping patch.
1 out of 1 hunk ignored
mkdir: build-curl-compat: File exists
makepkg -C nettoie desormais d abord. A dire clairement : ces quatre-la
ont eu l air de problemes de portage pendant deux tours entiers, et ne
l etaient pas.
gcc : retirer les sous-paquets de pkgname ne suffisait pas.
package_gcc() extrait des fichiers pour chaque frontal quoi qu on ait
demande, et _pick est un mv, donc il echoue sur ce qui n a jamais ete
bati :
mv: cannot stat 'usr/bin/gnat': No such file or directory
Les lignes _pick des frontaux desactives sont retirees aussi.
shadow reclamait libaudit-dev sur l hote -- un makedepend de plus que
--nodeps masque jusqu a ce qu une compilation s y arrete.
Assisted-by: Claude Opus 5
2026-08-16 02:23:01 -04:00
|
|
|
makepkg --nodeps --ignorearch --skippgpcheck --skipchecksums --nocheck \
|
|
|
|
|
-C -f || return 1
|
[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
2026-08-15 20:40:17 -04:00
|
|
|
# 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
|
[ADD] bootstrap pacman, makepkg and repo-add natively on s390x
The README lists pacman, bash and coreutils as three missing pieces.
They are not three tasks: pacman is the only one that matters, because
its source tree also ships makepkg and repo-add. Once those run, every
remaining package stops being hand-work and becomes makepkg on the
upstream PKGBUILD.
pacman 7.1.0 builds unpatched on s390x. No cross-compilation is
involved: on native hardware the whole userspace builds at full speed,
which removes the z/VM round-trip the other scripts need.
Measured end to end: zlib built from the official PKGBUILD yields
zlib, zlib-static and minizip, all tagged arch = s390x, the library
reporting "ELF 64-bit MSB shared object, IBM S/390", and repo-add
indexing them into a usable core.db.
--- FR ---
Le README annonce pacman, bash et coreutils comme trois pieces
manquantes. Ce ne sont pas trois travaux : seul pacman compte, parce
que son arbre source livre aussi makepkg et repo-add. Des qu ils
tournent, chaque paquet restant cesse d etre du travail manuel et
devient un makepkg sur le PKGBUILD amont.
pacman 7.1.0 se compile sans correctif sur s390x. Aucune compilation
croisee n intervient : sur du materiel natif tout l espace utilisateur
se batit a pleine vitesse, ce qui supprime l aller-retour z/VM dont
dependent les autres scripts.
Mesure de bout en bout : zlib bati depuis le PKGBUILD officiel produit
zlib, zlib-static et minizip, tous marques arch = s390x, la
bibliotheque se declarant « ELF 64-bit MSB shared object, IBM S/390 »,
et repo-add les indexant dans un core.db utilisable.
Assisted-by: Claude Opus 5
2026-08-15 03:18:47 -04:00
|
|
|
mkdir -p "$REPO"
|
[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
2026-08-15 20:40:17 -04:00
|
|
|
cp -f "${produced[@]}" "$REPO/" || return 1
|
|
|
|
|
# Only the new packages. Globbing the whole repository made repo-add
|
|
|
|
|
# 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
|
[ADD] bootstrap pacman, makepkg and repo-add natively on s390x
The README lists pacman, bash and coreutils as three missing pieces.
They are not three tasks: pacman is the only one that matters, because
its source tree also ships makepkg and repo-add. Once those run, every
remaining package stops being hand-work and becomes makepkg on the
upstream PKGBUILD.
pacman 7.1.0 builds unpatched on s390x. No cross-compilation is
involved: on native hardware the whole userspace builds at full speed,
which removes the z/VM round-trip the other scripts need.
Measured end to end: zlib built from the official PKGBUILD yields
zlib, zlib-static and minizip, all tagged arch = s390x, the library
reporting "ELF 64-bit MSB shared object, IBM S/390", and repo-add
indexing them into a usable core.db.
--- FR ---
Le README annonce pacman, bash et coreutils comme trois pieces
manquantes. Ce ne sont pas trois travaux : seul pacman compte, parce
que son arbre source livre aussi makepkg et repo-add. Des qu ils
tournent, chaque paquet restant cesse d etre du travail manuel et
devient un makepkg sur le PKGBUILD amont.
pacman 7.1.0 se compile sans correctif sur s390x. Aucune compilation
croisee n intervient : sur du materiel natif tout l espace utilisateur
se batit a pleine vitesse, ce qui supprime l aller-retour z/VM dont
dependent les autres scripts.
Mesure de bout en bout : zlib bati depuis le PKGBUILD officiel produit
zlib, zlib-static et minizip, tous marques arch = s390x, la
bibliotheque se declarant « ELF 64-bit MSB shared object, IBM S/390 »,
et repo-add les indexant dans un core.db utilisable.
Assisted-by: Claude Opus 5
2026-08-15 03:18:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
main() {
|
|
|
|
|
install_host_deps
|
|
|
|
|
build_pacman
|
|
|
|
|
configure_makepkg
|
|
|
|
|
for p in "$@"; do build_package "$p"; done
|
|
|
|
|
log "Done"
|
|
|
|
|
command -v pacman makepkg repo-add
|
|
|
|
|
}
|
|
|
|
|
|
[ADD] stage 1: build a self-hosting core for s390x
Forty-odd packages in link-time order, from linux-api-headers to
pacman itself. The order follows what a compiler actually needs, not
pacman metadata: --nodeps means nothing is ever checked, so anything
required at link time has to exist already.
A failure does not stop the run. One missing package must not hide the
state of the forty that follow, so failures are collected and reported
at the end, each with its own log. A state file makes the run
resumable, which matters when a single gcc build is measured in tens
of minutes.
The header states why stage 1 is not the port: everything here links
against the host glibc, because Arch glibc needs an Arch gcc which
needs an Arch glibc. Stages 2 and 3 break that circle.
bootstrap-pacman.sh now guards its own main so it can be sourced for
build_package without re-running the whole bootstrap.
--- FR ---
Une quarantaine de paquets dans l ordre des dependances de lien, de
linux-api-headers a pacman lui-meme. L ordre suit ce dont un
compilateur a reellement besoin, pas les metadonnees de pacman :
--nodeps ne verifie jamais rien, donc tout ce qui sert au lien doit
deja exister.
Un echec n arrete pas la course. Un paquet manquant ne doit pas
masquer l etat des quarante suivants : les echecs sont collectes et
rapportes a la fin, chacun avec son journal. Un fichier d etat rend la
reprise possible, ce qui compte quand un seul gcc se compte en
dizaines de minutes.
L en-tete dit pourquoi l etage 1 n est pas le portage : tout s y lie a
la glibc de l hote, parce que la glibc d Arch reclame un gcc d Arch
qui reclame une glibc d Arch. Les etages 2 et 3 brisent ce cercle.
bootstrap-pacman.sh garde desormais son main pour etre sourcable et
fournir build_package sans relancer tout l amorcage.
Assisted-by: Claude Opus 5
2026-08-15 15:48:30 -04:00
|
|
|
# Only run when executed, never when sourced: build-stage1.sh reuses
|
[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
2026-08-15 20:40:17 -04:00
|
|
|
# build_package and must not re-run the whole bootstrap to get it.
|
[ADD] stage 1: build a self-hosting core for s390x
Forty-odd packages in link-time order, from linux-api-headers to
pacman itself. The order follows what a compiler actually needs, not
pacman metadata: --nodeps means nothing is ever checked, so anything
required at link time has to exist already.
A failure does not stop the run. One missing package must not hide the
state of the forty that follow, so failures are collected and reported
at the end, each with its own log. A state file makes the run
resumable, which matters when a single gcc build is measured in tens
of minutes.
The header states why stage 1 is not the port: everything here links
against the host glibc, because Arch glibc needs an Arch gcc which
needs an Arch glibc. Stages 2 and 3 break that circle.
bootstrap-pacman.sh now guards its own main so it can be sourced for
build_package without re-running the whole bootstrap.
--- FR ---
Une quarantaine de paquets dans l ordre des dependances de lien, de
linux-api-headers a pacman lui-meme. L ordre suit ce dont un
compilateur a reellement besoin, pas les metadonnees de pacman :
--nodeps ne verifie jamais rien, donc tout ce qui sert au lien doit
deja exister.
Un echec n arrete pas la course. Un paquet manquant ne doit pas
masquer l etat des quarante suivants : les echecs sont collectes et
rapportes a la fin, chacun avec son journal. Un fichier d etat rend la
reprise possible, ce qui compte quand un seul gcc se compte en
dizaines de minutes.
L en-tete dit pourquoi l etage 1 n est pas le portage : tout s y lie a
la glibc de l hote, parce que la glibc d Arch reclame un gcc d Arch
qui reclame une glibc d Arch. Les etages 2 et 3 brisent ce cercle.
bootstrap-pacman.sh garde desormais son main pour etre sourcable et
fournir build_package sans relancer tout l amorcage.
Assisted-by: Claude Opus 5
2026-08-15 15:48:30 -04:00
|
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
|
|
|
main "$@"
|
|
|
|
|
fi
|