archlinux-s390x/patches/pkgbuild/binutils.sh
Mathieu Benoit ca355190c0 [FIX] binutils' extra targets were x86_64's, and gcc only wanted man pages
gold failed to link with

  s390.cc: undefined reference to `void gold::gold_error_at_location<32, true>'

Its s390 target file compiles code for both s390 and s390x and references
<32, true> instantiations, which exist only when a 32-bit s390 target is
configured. The PKGBUILD asks for --enable-targets=x86_64-pep,bpf-unknown-none.
x86_64-pep is the PE+ target for x86_64: it means nothing here, and on x86_64 it
is what happens to bring in the 32-bit instantiations gold's target files want.
So this was never a gold bug -- it is the -march=x86-64 story one layer further
in. s390-linux-gnu is the honest translation of that line.

gcc now compiles, Fortran front end included, and stopped in package_gcc() on
libstdc++'s doxygen man pages -- two places, build and install, the eighth time
this port has met that shape.

--- FR ---

gold ne se liait pas :

  s390.cc: undefined reference to `void gold::gold_error_at_location<32, true>'

Son fichier de cible s390 compile pour s390 et s390x et référence des
instanciations <32, true>, qui n'existent que si une cible s390 32 bits est
configurée. Le PKGBUILD demande --enable-targets=x86_64-pep,bpf-unknown-none.
x86_64-pep est la cible PE+ d'x86_64 : elle ne veut rien dire ici, et sur x86_64
c'est elle qui amène par hasard les instanciations 32 bits que gold réclame. Ce
n'était donc pas un défaut de gold — c'est l'histoire du -march=x86-64 une couche
plus loin. s390-linux-gnu est la traduction honnête de cette ligne.

gcc compile désormais, front-end Fortran compris, et s'arrêtait dans
package_gcc() sur les pages de manuel doxygen de libstdc++ — deux endroits,
construction et installation, huitième fois que ce portage rencontre cette forme.

Assisted-by: Claude Opus 5
2026-08-22 21:52:39 -04:00

133 lines
6.6 KiB
Bash
Executable file

#!/usr/bin/env bash
# binutils: install into /usr/lib, not /usr/lib64.
#
# THIS IS THE ROOT OF A CHAIN, and the chain is worth writing down because
# nothing in it looks related to anything else in it:
#
# 1. On s390x, GCC's and binutils' default MULTILIB_OSDIRNAME is lib64, so
# binutils installs libiberty.a into /usr/lib64 -- creating that directory
# as a REAL directory. On Arch, /usr/lib64 is a SYMLINK to lib.
# 2. meson chooses its default libdir by looking at the system: 64-bit plus a
# real /usr/lib64 means "lib64". A symlink does not count, which is why
# Arch never sees this and arch-meson passes no --libdir at all.
# 3. pkgconf is a meson package, so it installed into /usr/lib64 -- and
# COMPILED IN its search path as /usr/lib64/pkgconfig.
# 4. Every .pc file in the distribution is in /usr/lib/pkgconfig. So every
# pkg-config lookup inside the chroot failed. libxslt reported it as
#
# configure: error: Package requirements (python-3.14) were not met:
# Package 'python-3.14' not found
#
# with python 3.14.7 installed and /usr/lib/pkgconfig/python-3.14.pc
# sitting right there.
#
# Step 4 reads as a missing dependency. Step 1 is a linker library nobody
# thinks about. Fixing only the visible end -- pkgconf's search path -- would
# leave the real /usr/lib64 there, and the next meson package would land in it.
#
# --libdir is set explicitly rather than left to the target default, which is
# what Arch's layout means: one library directory, /usr/lib, with lib64 as a
# compatibility symlink.
set -euo pipefail
python3 - <<'ZZPY'
import io, re
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
hit = [i for i, l in enumerate(lines) if re.search(r"/configure\b", l) and "#" not in l.split("/configure")[0]]
assert len(hit) == 1, "binutils: expected one configure call, got %d" % len(hit)
i = hit[0]
indent = re.match(r"^[ \t]*", lines[i]).group(0)
assert lines[i].rstrip().endswith("\\"), "binutils: configure does not continue"
lines.insert(i + 1, indent + " --libdir=/usr/lib \\")
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
ZZPY
grep -A1 -E "/configure( |\\\\)" PKGBUILD | grep -q -- '--libdir=/usr/lib' || {
echo "binutils: --libdir is not on the configure line" >&2; exit 1; }
echo "binutils: libdir pinned to /usr/lib (keeps /usr/lib64 a symlink)"
# --- no PGO+LTO build ---------------------------------------------------------
#
# binutils built at stage 1 and failed at stage 2, in gold:
#
# <artificial>:(.text+0xc44e): undefined reference to
# `void gold::gold_error_at_location<32, true>(...)'
# collect2: error: ld returned 1 exit status
#
# `<artificial>` and the .ltrans object names are LTO's. It does not come from
# makepkg -- the chroot's OPTIONS carry !lto and LTOFLAGS is empty. It comes
# from the PKGBUILD itself: --enable-pgo-build=lto, a profile-guided build with
# link-time optimisation, which passes -flto=jobserver. gold's
# explicitly-instantiated templates do not survive it here.
#
# Stage 1 got away with it because the host's GCC did the work. Stage 2 uses
# ours, on s390x, at -O2 -march=z13 where stage 1 passed no flags at all.
#
# PGO and LTO are BUILD-TIME optimisations: dropping them changes how long
# binutils takes to compile and how fast the resulting linker runs, not what it
# can do. The alternatives were disabling gold -- removing a linker Arch ships
# -- or debugging an LTO template instantiation bug in a linker upstream has
# deprecated. For a bootstrap, a binutils that works beats a binutils that is
# five percent faster; PGO also roughly triples the build, which this port pays
# for on every stage.
python3 - <<'ZZPY'
import io
# DELETED, not commented.
#
# The first version replaced the line with a comment, and binutils then failed
# with
#
# /build/binutils/PKGBUILD: line 107: --enable-plugins: command not found
#
# because the line ended in a backslash. A comment inside a continued command
# does not comment out an option -- it breaks the continuation, and the NEXT
# option becomes a command of its own. The documented trap in this port was the
# mirror image (commenting the first line of a multi-line assignment leaves the
# continuations live); this is the same fact from the other side.
#
# Nothing is left in its place: the explanation belongs in this hook, and any
# comment placed inside the configure invocation would break it again.
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
hit = [i for i, l in enumerate(lines) if "--enable-pgo-build" in l]
assert len(hit) == 1, "binutils: expected one --enable-pgo-build line, got %d" % len(hit)
i = hit[0]
assert lines[i].strip().startswith("--enable-pgo-build"), \
"binutils: --enable-pgo-build shares its line: %r" % lines[i]
del lines[i]
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
ZZPY
grep -qE "^[[:space:]]*--enable-pgo-build" PKGBUILD && {
echo "binutils: an active --enable-pgo-build line survived" >&2; exit 1; }
echo "binutils: PGO+LTO build dropped"
# --- the extra targets are x86_64's --------------------------------------------
#
# s390.cc:(.text+0x2d76): undefined reference to
# `void gold::gold_error_at_location<32, true>(...)'
#
# gold's s390 target file compiles code for BOTH s390 (32-bit) and s390x, and
# references template instantiations for <32, true>. Those exist only if a
# 32-bit s390 target is configured -- and the PKGBUILD asks for
#
# --enable-targets=x86_64-pep,bpf-unknown-none
#
# x86_64-pep is the PE+ target for x86_64. It means nothing on this machine, and
# its presence is why gold linked on Arch and not here: on x86_64 that line
# happens to bring in the 32-bit instantiations gold's target files want.
#
# So this is not a workaround for a gold bug -- it is the same x86_64 assumption
# as the -march=x86-64 in makepkg.conf, one layer further in. s390-linux-gnu is
# the honest translation of that line, and it is what makes the templates exist.
# bpf-unknown-none stays: it is architecture-neutral.
set -euo pipefail
python3 - <<'ZZPY'
import io
s = io.open("PKGBUILD", encoding="utf-8").read()
old = "--enable-targets=x86_64-pep,bpf-unknown-none"
assert s.count(old) == 1, "binutils: expected one --enable-targets, got %d" % s.count(old)
s = s.replace(old, "--enable-targets=s390-linux-gnu,bpf-unknown-none", 1)
io.open("PKGBUILD", "w", encoding="utf-8").write(s)
ZZPY
grep -q -- "--enable-targets=s390-linux-gnu" PKGBUILD || {
echo "binutils: the target list was not translated" >&2; exit 1; }
grep -q "x86_64-pep" PKGBUILD && {
echo "binutils: an x86_64 target survived" >&2; exit 1; }
echo "binutils: extra targets translated to s390 (gold needs the 32-bit one)"