[ADD] devtools stand-ins, and lib32 removal for glibc and gcc

The same x86 assumption keeps returning in a different disguise: a
32-bit multilib split package. libtool had it, and so do glibc and gcc.
On x86_64 multilib means i686 and Arch wants it; on Z it means the
31-bit ESA/390 ABI that GCC is actively removing:

  configure: error: Support for -m31 is deprecated and will be removed.

glibc is the clearest case. The whole compile SUCCEEDS and the glibc
package is written -- then makepkg aborts in package_lib32-glibc() with
"No rule to make target install", because the 32-bit tree was never
configured. The work was done; only the packaging of a tree nobody
built failed.

gcc needed three cuts: front ends written in themselves (Ada, D,
Modula-2, COBOL have no bootstrap compiler here), multilib, and every
lib32 reference including the _pick lines that split out usr/lib32.

arch-meson and arch-cmake are provided as stand-ins. Several PKGBUILDs
call them, they ship in devtools, and devtools is itself an Arch
package -- so during a bootstrap they cannot exist yet and every
PKGBUILD using them stops on "command not found".

A verification lesson, learned twice: grepping a whole PKGBUILD for
"lib32" declares false failures, because the string survives in
comments and in functions that are never called. Only the pkgname array
matters, since that is what makepkg iterates.

--- FR ---

La meme hypothese x86 revient sans cesse sous un autre deguisement : un
paquet scinde multilib 32 bits. libtool l avait, glibc et gcc aussi.
Sur x86_64 le multilib signifie i686 et Arch le veut ; sur Z il designe
l ABI 31 bits ESA/390 que GCC est en train de retirer.

glibc est le cas le plus net. Toute la compilation REUSSIT et le paquet
glibc est ecrit -- puis makepkg abandonne dans package_lib32-glibc()
sur « No rule to make target install », parce que l arbre 32 bits n a
jamais ete configure. Le travail etait fait ; seul l empaquetage d un
arbre que personne n avait bati a echoue.

gcc demandait trois coupes : les frontaux ecrits en eux-memes (Ada, D,
Modula-2 et COBOL n ont ici aucun compilateur d amorcage), le multilib,
et toute reference a lib32 y compris les lignes _pick qui extraient
usr/lib32.

arch-meson et arch-cmake sont fournis en substituts. Plusieurs PKGBUILD
les appellent, ils vivent dans devtools, et devtools est lui-meme un
paquet Arch -- pendant un amorcage ils ne peuvent donc pas exister, et
chaque PKGBUILD qui les utilise s arrete sur « command not found ».

Une lecon de verification, apprise deux fois : chercher « lib32 » dans
tout un PKGBUILD declare de faux echecs, car la chaine survit dans les
commentaires et dans des fonctions jamais appelees. Seul le tableau
pkgname compte, puisque c est lui que makepkg parcourt.

Assisted-by: Claude Opus 5
This commit is contained in:
Mathieu Benoit 2026-08-15 21:15:01 -04:00
parent f87502622a
commit c9cc17bd01
4 changed files with 140 additions and 27 deletions

View file

@ -1,24 +1,79 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# gcc: keep only the front ends that bootstrap without an existing compiler # gcc: three x86 assumptions, all fatal on s390x.
# of the same language.
# #
# configure: error: GNAT is required to build ada # 1. Front ends written in themselves.
# configure: error: GDC is required to build d
# #
# Ada and D are written in themselves: building their front ends needs an # configure: error: GNAT is required to build ada
# existing Ada or D compiler of a compatible vintage. Ubuntu ships gnat, but # configure: error: GDC is required to build d
# not one GCC 15 accepts, and D has no bootstrap compiler here at all.
# Modula-2 and COBOL have the same shape of problem.
# #
# Nothing in a core bootstrap -- and nothing in ERPLibre -- is written in any # Ada and D need an existing compiler of the same language; Modula-2 and
# of them. C, C++, Fortran, LTO and the Objective-C front ends cover # COBOL have the same shape. Nothing in a core bootstrap, and nothing in
# everything the rest of this port compiles. # ERPLibre, is written in any of them.
# #
# STAGE 1 CONCESSION, not a permanent one. Once the port is self-hosting its # 2. Multilib, which on Z means the 31-bit ABI:
# own gcc can bootstrap the others, and this hook should be revisited. #
# configure: error: Support for -m31 is deprecated and will be removed.
# Specify --enable-obsolete to build it anyway.
#
# On x86_64 multilib means i686 and Arch wants it. Here it means the
# 31-bit ESA/390 ABI that GCC is actively removing. Disabled rather than
# resurrected as obsolete.
#
# 3. The lib32 split package and every _pick that feeds it.
#
# The front-end reduction is a STAGE 1 CONCESSION: once the port is
# self-hosting, its own gcc can bootstrap Ada and D. The multilib and lib32
# removals are permanent -- they are architectural.
set -euo pipefail set -euo pipefail
sed -i 's/^\(\s*--enable-languages=\).*\\$/\1c,c++,fortran,lto,objc,obj-c++ \\/' PKGBUILD sed -i 's/^\(\s*--enable-languages=\).*\\$/\1c,c++,fortran,lto,objc,obj-c++ \\/' PKGBUILD
if grep -qE 'enable-languages=[^ ]*(ada|,d,|m2|cobol)' PKGBUILD; then
echo "gcc: a self-hosted front end is still enabled" >&2; exit 1
fi
if grep -q -- '--enable-multilib' PKGBUILD; then
sed -i 's/--enable-multilib/--disable-multilib/' PKGBUILD
else
sed -i 's/^\(\s*\)--enable-languages=\(.*\)$/\1--disable-multilib \\\n\1--enable-languages=\2/' PKGBUILD
fi
grep -q -- '--disable-multilib' PKGBUILD || { echo "gcc: multilib not disabled" >&2; exit 1; }
# The pkgname array lists one sub-package per front end. makepkg calls
# package_<name>() for every entry, so those whose language is now off would
# package an empty tree. Names absent from the array are never called, so
# pruning it is enough -- the functions themselves can stay.
python3 - <<'PY'
import io, re
drop = {
"gcc-ada", "gcc-d", "gcc-gcobol", "gcc-go", "gcc-m2", "gcc-rust",
"libgm2", "libgo", "libgphobos", "libgcobol",
"lib32-gcc-libs",
# Hardware-assisted ASan exists on x86_64 and aarch64 only.
"libhwasan",
}
s = io.open("PKGBUILD", encoding="utf-8").read()
m = re.search(r"^pkgname=\(\n(.*?)^\)$", s, re.S | re.M)
assert m, "pkgname array not found"
kept = [ln for ln in m.group(1).splitlines() if ln.strip() not in drop]
s = s[:m.start(1)] + "\n".join(kept) + "\n" + s[m.end(1):]
s = re.sub(r"\npackage_lib32-gcc-libs\(\)\s*\{.*?\n\}\n", "\n", s, flags=re.S)
io.open("PKGBUILD", "w", encoding="utf-8").write(s)
print("gcc: sub-packages kept -> %d" % len(kept))
PY
# Two lingering references outside the array: a makedepends entry on a
# package that does not exist for this architecture, and a run of
# `_pick lib32-gcc-libs usr/lib32/...` splitting out files multilib would
# have produced. With multilib off, usr/lib32 is empty.
sed -i '/^\s*lib32-gcc-libs\s*$/d' PKGBUILD
sed -i '/_pick lib32-gcc-libs/d' PKGBUILD
sed -i '/lib32-gcc-libs: for generating code/d' PKGBUILD
# Verify what matters: the array makepkg iterates. Grepping the whole file
# for the bare name declared a false failure once already, on libtool and
# then here -- the string survives in comments and in unused functions.
if sed -n '/^pkgname=(/,/^)/p' PKGBUILD | grep -q 'lib32'; then
echo "gcc: lib32 still in pkgname array" >&2; exit 1
fi
grep -m1 -- '--enable-languages' PKGBUILD grep -m1 -- '--enable-languages' PKGBUILD
grep -qE 'enable-languages=[^ ]*(ada|,d,|m2|cobol)' PKGBUILD && { echo "gcc: front ends reduced, multilib off, lib32 removed"
echo "gcc: a self-hosted front end is still enabled" >&2; exit 1; }
echo "gcc: front ends reduced to those that bootstrap from C"

View file

@ -1,18 +1,44 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# glibc: SFrame does not exist on s390x. # glibc: two x86-only assumptions, both fatal on s390x.
# #
# Arch's PKGBUILD passes --enable-sframe, added when x86_64 gained SFrame # 1. SFrame.
# stack tracing. glibc's own configure rejects it outright on this
# architecture:
# #
# configure: error: the architecture doesn't support SFrame # Arch passes --enable-sframe, added when x86_64 gained SFrame stack
# tracing. glibc's configure rejects it outright here:
# #
# This is not a build-environment problem and no host package fixes it: the # configure: error: the architecture doesn't support SFrame
# feature is genuinely absent from s390x. Dropping the flag is what a port #
# does -- and it must be dropped surgically, leaving every other configure # No host package fixes this: the feature is genuinely absent from s390x.
# option untouched, so that a future Arch change to this PKGBUILD is not #
# silently discarded. # 2. lib32-glibc.
#
# glibc is a split package whose second half is the 32-bit multilib
# build. The main glibc package builds and packages perfectly -- measured,
# the whole compile succeeds -- and then makepkg aborts in
# package_lib32-glibc() with "No rule to make target 'install'", because
# the 32-bit tree was never configured.
#
# lib32 is i686-on-x86_64. On s390x there is no 32-bit userspace to build
# against, and the deprecated 31-bit ABI is not it either.
#
# Both are removed rather than repaired: what is being removed is
# architecture-specific by nature.
set -euo pipefail set -euo pipefail
sed -i '/--enable-sframe/d' PKGBUILD sed -i '/--enable-sframe/d' PKGBUILD
grep -q -- '--enable-sframe' PKGBUILD && { echo "glibc: sframe flag still present" >&2; exit 1; } grep -q -- '--enable-sframe' PKGBUILD && { echo "glibc: sframe flag still present" >&2; exit 1; }
echo "glibc: --enable-sframe removed (unsupported on s390x)"
# Drop the lib32 half: package list, its build steps and its package function.
sed -i 's/^pkgname=(glibc lib32-glibc\(.*\))$/pkgname=(glibc\1)/' PKGBUILD
sed -i '/lib32-gcc-libs/d' PKGBUILD
python3 - <<'PY'
import io, re
s = io.open("PKGBUILD", encoding="utf-8").read()
# The package function, and the build block guarded by the 32-bit tree.
s = re.sub(r"\npackage_lib32-glibc\(\)\s*\{.*?\n\}\n", "\n", s, flags=re.S)
io.open("PKGBUILD", "w", encoding="utf-8").write(s)
PY
grep -q 'package_lib32-glibc' PKGBUILD && { echo "glibc: lib32 package function remains" >&2; exit 1; }
grep -qE '^pkgname=\(glibc( |\))' PKGBUILD || { echo "glibc: pkgname not reduced" >&2; exit 1; }
grep -m1 '^pkgname=' PKGBUILD
echo "glibc: --enable-sframe removed, lib32 split package removed"

11
scripts/devtools/arch-cmake Executable file
View file

@ -0,0 +1,11 @@
#!/usr/bin/env bash
# Minimal stand-in for devtools' arch-cmake, same reasoning as arch-meson.
exec cmake \
-DCMAKE_BUILD_TYPE=None \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_INSTALL_LIBEXECDIR=lib \
-DCMAKE_INSTALL_SBINDIR=bin \
-DBUILD_SHARED_LIBS=ON \
-Wno-dev \
"$@"

21
scripts/devtools/arch-meson Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Minimal stand-in for devtools' arch-meson.
#
# A number of Arch PKGBUILDs call arch-meson rather than meson directly. It
# ships in the `devtools` package, which is itself an Arch package -- so
# during a bootstrap it does not exist yet, and every PKGBUILD that uses it
# stops on "arch-meson: command not found".
#
# This reproduces the options devtools passes, which are what the PKGBUILDs
# assume: /usr prefix, plain buildtype so makepkg's CFLAGS are honoured
# verbatim, and no network access for subprojects.
exec meson setup \
--prefix /usr \
--libexecdir lib \
--sbindir bin \
--buildtype plain \
--auto-features enabled \
--wrap-mode nodownload \
-D b_pie=true \
-D python.bytecompile=1 \
"$@"