Compare commits
36 commits
4101d18f72
...
327ff55665
| Author | SHA1 | Date | |
|---|---|---|---|
| 327ff55665 | |||
| 51384a64af | |||
| 0da64c9933 | |||
| c43289c5ca | |||
| cf3a4ffdf4 | |||
| f875649c96 | |||
| fe9c58c1a3 | |||
| 0e00b161c4 | |||
| 61abc5aef9 | |||
| 376c6d6a91 | |||
| f6c0969929 | |||
| 8d9e8a4dce | |||
| 3d2a1485af | |||
| 2b0139e99f | |||
| c375f994fe | |||
| 111d4c80b3 | |||
| 29da076277 | |||
| 41f0bc4897 | |||
| 7fa489b5bb | |||
| 430b49aae2 | |||
| f25a34eaed | |||
| 75cff944a8 | |||
| 6656f07e2b | |||
| 04a55bc74c | |||
| ac5e5f3892 | |||
| fceb5936a5 | |||
| 0963698d4b | |||
| 9a598fdd4d | |||
| 3267c6484c | |||
| 8a41d00a90 | |||
| a8eef0e460 | |||
| f26a6a7115 | |||
| 5418dace22 | |||
| 8c7d8f52a9 | |||
| 22c0eca955 | |||
| cb3a32101a |
27 changed files with 1379 additions and 60 deletions
47
patches/pkgbuild/autoconf-archive.sh
Executable file
47
patches/pkgbuild/autoconf-archive.sh
Executable file
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# autoconf-archive: take the patch from a mirror savannah's cgit will serve.
|
||||||
|
#
|
||||||
|
# curl: (52) Empty reply from server
|
||||||
|
# ==> ERROR: Failure while downloading
|
||||||
|
# https://cgit.git.savannah.gnu.org/cgit/autoconf-archive.git/patch/?id=241f7ae...
|
||||||
|
#
|
||||||
|
# The tarball comes from ftpmirror.gnu.org and arrives fine. What fails is a
|
||||||
|
# single patch fetched from savannah's cgit /patch/?id= endpoint, which returns
|
||||||
|
# nothing at all -- measured, not assumed:
|
||||||
|
#
|
||||||
|
# savannah /patch/?id= (no response)
|
||||||
|
# github /commit/.patch 200, 2463 bytes
|
||||||
|
#
|
||||||
|
# savannah itself is up (its root answers 302); it is that endpoint, which cgit
|
||||||
|
# generates on demand and rate-limits.
|
||||||
|
#
|
||||||
|
# The mirror is asked for THE SAME COMMIT, by its full hash, so this changes
|
||||||
|
# where the bytes come from and not which bytes they are -- the substantive
|
||||||
|
# difference from replacing a source with a different version of itself. GitHub
|
||||||
|
# renders `git format-patch` output where cgit renders its own; both are what
|
||||||
|
# `patch` expects, and the build fails loudly if that were untrue.
|
||||||
|
#
|
||||||
|
# WHY NOT DROP THE PATCH. It is 0001_fix_AX_CXX_COMPILE_STDCXX.patch, a fix to a
|
||||||
|
# macro this port needs -- tpm2-tss stopped on a missing AX_* macro, which is why
|
||||||
|
# autoconf-archive is in the list at all.
|
||||||
|
set -euo pipefail
|
||||||
|
python3 - <<'ZZPY'
|
||||||
|
import io, re
|
||||||
|
s = io.open("PKGBUILD", encoding="utf-8").read()
|
||||||
|
old = "https://cgit.git.savannah.gnu.org/cgit/autoconf-archive.git/patch/?id="
|
||||||
|
assert s.count(old) == 1, "autoconf-archive: expected one cgit patch URL, got %d" % s.count(old)
|
||||||
|
# The commit hash follows the URL, up to the closing quote. Reused verbatim: the
|
||||||
|
# point of the substitution is that the content is identical.
|
||||||
|
m = re.search(re.escape(old) + r"([0-9a-f]{40})", s)
|
||||||
|
assert m, "autoconf-archive: no 40-character commit hash after the cgit URL"
|
||||||
|
sha = m.group(1)
|
||||||
|
s = s.replace(old + sha,
|
||||||
|
"https://github.com/autoconf-archive/autoconf-archive/commit/%s.patch" % sha, 1)
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write(s)
|
||||||
|
print(" patch commit: %s" % sha[:12])
|
||||||
|
ZZPY
|
||||||
|
grep -q "cgit.git.savannah.gnu.org" PKGBUILD && {
|
||||||
|
echo "autoconf-archive: a cgit URL survived" >&2; exit 1; }
|
||||||
|
grep -qE "github.com/autoconf-archive/autoconf-archive/commit/[0-9a-f]{40}\.patch" PKGBUILD || {
|
||||||
|
echo "autoconf-archive: the mirror URL is malformed" >&2; exit 1; }
|
||||||
|
echo "autoconf-archive: patch taken from the git mirror (same commit)"
|
||||||
|
|
@ -98,36 +98,105 @@ grep -qE "^[[:space:]]*--enable-pgo-build" PKGBUILD && {
|
||||||
echo "binutils: an active --enable-pgo-build line survived" >&2; exit 1; }
|
echo "binutils: an active --enable-pgo-build line survived" >&2; exit 1; }
|
||||||
echo "binutils: PGO+LTO build dropped"
|
echo "binutils: PGO+LTO build dropped"
|
||||||
|
|
||||||
# --- the extra targets are x86_64's --------------------------------------------
|
# --- no gold, and no s390-specific extra target -------------------------------
|
||||||
#
|
#
|
||||||
# s390.cc:(.text+0x2d76): undefined reference to
|
# This section was written twice, and the first version was wrong in an
|
||||||
# `void gold::gold_error_at_location<32, true>(...)'
|
# instructive way.
|
||||||
#
|
#
|
||||||
# gold's s390 target file compiles code for BOTH s390 (32-bit) and s390x, and
|
# gold would not link:
|
||||||
# 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
|
# s390.cc: undefined reference to `gold::gold_error_at_location<32, true>'
|
||||||
#
|
#
|
||||||
# x86_64-pep is the PE+ target for x86_64. It means nothing on this machine, and
|
# gold's s390 target file compiles for both s390 and s390x and needs <32, true>
|
||||||
# its presence is why gold linked on Arch and not here: on x86_64 that line
|
# template instantiations, which exist only when a 32-bit s390 target is
|
||||||
# happens to bring in the 32-bit instantiations gold's target files want.
|
# configured. The PKGBUILD asked for --enable-targets=x86_64-pep, so the first
|
||||||
|
# fix translated that to s390-linux-gnu -- the honest-looking equivalent. bfd's
|
||||||
|
# configure answered:
|
||||||
#
|
#
|
||||||
# So this is not a workaround for a gold bug -- it is the same x86_64 assumption
|
# *** Specify --enable-obsolete to build it anyway.
|
||||||
# as the -march=x86-64 in makepkg.conf, one layer further in. s390-linux-gnu is
|
# *** Support will be REMOVED in the next major release of BINUTILS,
|
||||||
# the honest translation of that line, and it is what makes the templates exist.
|
# *** unless a maintainer comes forward.
|
||||||
# bpf-unknown-none stays: it is architecture-neutral.
|
#
|
||||||
|
# 32-bit s390 is OBSOLETE in binutils. So gold on s390x cannot be built without
|
||||||
|
# enabling a target upstream has announced it is deleting -- and gold itself is
|
||||||
|
# deprecated, with bfd ld the default here already (--enable-ld=default). Turning
|
||||||
|
# on one deprecated thing to build another is not a trade worth making.
|
||||||
|
#
|
||||||
|
# So: gold is dropped, and the extra target list keeps only bpf-unknown-none,
|
||||||
|
# which is architecture-neutral. x86_64-pep goes because it names a format for a
|
||||||
|
# machine this is not.
|
||||||
|
#
|
||||||
|
# WHAT IS LOST: /usr/bin/ld.gold. Nothing in this port invokes it, ld is the
|
||||||
|
# default, and upstream is removing gold. Recorded rather than hidden -- the
|
||||||
|
# stage-2 binutils will not match Arch's file list, and this is why.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
python3 - <<'ZZPY'
|
python3 - <<'ZZPY'
|
||||||
import io
|
import io, re
|
||||||
s = io.open("PKGBUILD", encoding="utf-8").read()
|
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
|
||||||
old = "--enable-targets=x86_64-pep,bpf-unknown-none"
|
|
||||||
assert s.count(old) == 1, "binutils: expected one --enable-targets, got %d" % s.count(old)
|
t = [i for i, l in enumerate(lines) if "--enable-targets=" in l]
|
||||||
s = s.replace(old, "--enable-targets=s390-linux-gnu,bpf-unknown-none", 1)
|
assert len(t) == 1, "binutils: expected one --enable-targets, got %d" % len(t)
|
||||||
io.open("PKGBUILD", "w", encoding="utf-8").write(s)
|
assert "x86_64-pep" in lines[t[0]], "binutils: --enable-targets is not the x86 one: %r" % lines[t[0]]
|
||||||
|
lines[t[0]] = lines[t[0]].replace("x86_64-pep,", "")
|
||||||
|
|
||||||
|
g = [i for i, l in enumerate(lines) if re.match(r"^[ \t]*--enable-gold[ \t]*\\?$", l)]
|
||||||
|
assert len(g) == 1, "binutils: expected one --enable-gold line, got %d" % len(g)
|
||||||
|
lines[g[0]] = lines[g[0]].replace("--enable-gold", "--disable-gold")
|
||||||
|
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
ZZPY
|
ZZPY
|
||||||
grep -q -- "--enable-targets=s390-linux-gnu" PKGBUILD || {
|
grep -q "x86_64-pep" PKGBUILD && { echo "binutils: an x86_64 target survived" >&2; exit 1; }
|
||||||
echo "binutils: the target list was not translated" >&2; exit 1; }
|
grep -q -- "--disable-gold" PKGBUILD || { echo "binutils: gold not disabled" >&2; exit 1; }
|
||||||
grep -q "x86_64-pep" PKGBUILD && {
|
grep -q -- "--enable-gold" PKGBUILD && { echo "binutils: gold still enabled" >&2; exit 1; }
|
||||||
echo "binutils: an x86_64 target survived" >&2; exit 1; }
|
echo "binutils: gold dropped (its s390 support needs an obsolete target)"
|
||||||
echo "binutils: extra targets translated to s390 (gold needs the 32-bit one)"
|
|
||||||
|
# --- libiberty still records a usr/lib64 path ---------------------------------
|
||||||
|
#
|
||||||
|
# --libdir=/usr/lib above is not enough. pacman refused to install the result:
|
||||||
|
#
|
||||||
|
# binutils: <root>/usr/lib64 exists in filesystem (owned by filesystem)
|
||||||
|
# binutils: <root>/usr/lib64/libiberty.a exists in filesystem
|
||||||
|
#
|
||||||
|
# libiberty installs into $(libdir)$(MULTIOSSUBDIR), and on s390x gcc reports
|
||||||
|
# ../lib64 for -print-multi-os-directory. In the INSTALLED system that resolves
|
||||||
|
# through the symlink the filesystem package now provides, so the file lands in
|
||||||
|
# /usr/lib -- but pkgdir has no such symlink, so make creates a real
|
||||||
|
# pkg/usr/lib64/ and makepkg records `usr/lib64/libiberty.a` as the package's
|
||||||
|
# own path. Installing it then collides with the symlink.
|
||||||
|
#
|
||||||
|
# The two fixes are not alternatives: filesystem's symlink is what keeps meson
|
||||||
|
# and cmake choosing lib, and this moves the one file that still writes through
|
||||||
|
# the multi-os subdirectory. Done in package(), on pkgdir, so nothing depends on
|
||||||
|
# the order the two packages are installed in.
|
||||||
|
python3 - <<'ZZPY'
|
||||||
|
import io, re
|
||||||
|
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
|
||||||
|
# The last package function is where pkgdir is complete.
|
||||||
|
# package(), not package_binutils(). binutils is NOT a split package here --
|
||||||
|
# pkgname=binutils, one function -- and the first version of this assumed the
|
||||||
|
# split form and asserted its way out. Both shapes are in this port; a hook has
|
||||||
|
# to look.
|
||||||
|
hit = [i for i, l in enumerate(lines) if re.match(r"^package(_binutils)?\(\)", l)]
|
||||||
|
assert len(hit) == 1, "binutils: expected one package function, got %d" % len(hit)
|
||||||
|
# Find that function's closing brace.
|
||||||
|
i = hit[0] + 1
|
||||||
|
while i < len(lines) and lines[i] != "}":
|
||||||
|
i += 1
|
||||||
|
assert i < len(lines), "binutils: package_binutils() has no closing brace"
|
||||||
|
lines[i:i] = [
|
||||||
|
"",
|
||||||
|
" # libiberty writes through gcc's multi-os subdirectory (../lib64 on",
|
||||||
|
" # s390x). In the installed system usr/lib64 is a symlink to lib, but pkgdir",
|
||||||
|
" # has no symlink, so the path is recorded literally and collides with the",
|
||||||
|
" # filesystem package. Move it to where it resolves to anyway.",
|
||||||
|
' if [ -d "$pkgdir/usr/lib64" ]; then',
|
||||||
|
' install -d "$pkgdir/usr/lib"',
|
||||||
|
' mv "$pkgdir"/usr/lib64/* "$pkgdir/usr/lib/"',
|
||||||
|
' rmdir "$pkgdir/usr/lib64"',
|
||||||
|
' fi',
|
||||||
|
]
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -q 'rmdir "\$pkgdir/usr/lib64"' PKGBUILD || {
|
||||||
|
echo "binutils: the lib64 move was not inserted" >&2; exit 1; }
|
||||||
|
echo "binutils: libiberty moved out of usr/lib64"
|
||||||
|
|
|
||||||
39
patches/pkgbuild/clang.sh
Executable file
39
patches/pkgbuild/clang.sh
Executable file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# clang: no Sphinx documentation.
|
||||||
|
#
|
||||||
|
# -DLLVM_ENABLE_SPHINX=ON pulls in python-sphinx and python-myst-parser, and
|
||||||
|
# behind those sit docutils, babel, pygments, snowballstemmer, imagesize,
|
||||||
|
# alabaster, the sphinxcontrib-* family, markdown-it-py and mdit-py-plugins --
|
||||||
|
# fifteen or so packages whose entire purpose here would be to render HTML for a
|
||||||
|
# compiler nothing in this port reads the manual of.
|
||||||
|
#
|
||||||
|
# MEASURED BEFORE CHOOSING, the way glib2 and iproute2 were: llvm and clang need
|
||||||
|
# only libedit and python-psutil beyond what this port already has. Sphinx is the
|
||||||
|
# whole of the rest of the bill, and one flag removes it.
|
||||||
|
#
|
||||||
|
# AND THE CLEANUP, found before it failed. package() ends on
|
||||||
|
#
|
||||||
|
# rm -r "$pkgdir"/usr/share/doc/.../html/{_sources,.buildinfo}
|
||||||
|
#
|
||||||
|
# which Sphinx creates and which will not exist. This is the seventeenth
|
||||||
|
# appearance of that shape in this port; the procedure written in jsoncpp's hook
|
||||||
|
# says to grep package() for the OUTPUT paths after disabling a documentation
|
||||||
|
# build, and this is the first time it was done before the build rather than
|
||||||
|
# after. rm -rf rather than deleted: on a machine with Sphinx the directory is
|
||||||
|
# real and still has to go.
|
||||||
|
set -euo pipefail
|
||||||
|
python3 - <<'ZZPY'
|
||||||
|
import io, re
|
||||||
|
s = io.open("PKGBUILD", encoding="utf-8").read()
|
||||||
|
old = "-DLLVM_ENABLE_SPHINX=ON"
|
||||||
|
assert s.count(old) == 1, "clang: expected one LLVM_ENABLE_SPHINX, got %d" % s.count(old)
|
||||||
|
s = s.replace(old, "-DLLVM_ENABLE_SPHINX=OFF", 1)
|
||||||
|
lines = s.split("\n")
|
||||||
|
hit = [i for i, l in enumerate(lines) if "_sources" in l and l.lstrip().startswith("rm ")]
|
||||||
|
assert len(hit) == 1, "clang: expected one _sources removal, got %d" % len(hit)
|
||||||
|
lines[hit[0]] = lines[hit[0]].replace("rm -r ", "rm -rf ", 1)
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -q -- "-DLLVM_ENABLE_SPHINX=OFF" PKGBUILD || { echo "clang: sphinx not disabled" >&2; exit 1; }
|
||||||
|
grep -qE "^[[:space:]]*rm -rf .*_sources" PKGBUILD || { echo "clang: the cleanup is not tolerant" >&2; exit 1; }
|
||||||
|
echo "clang: Sphinx documentation disabled, cleanup made tolerant"
|
||||||
|
|
@ -82,3 +82,54 @@ sed -n '/^makedepends=(/,/)/p' PKGBUILD | grep -qw emacs && {
|
||||||
grep -q 'cmake-mode' PKGBUILD && {
|
grep -q 'cmake-mode' PKGBUILD && {
|
||||||
echo "cmake: a cmake-mode reference remains -- check it is harmless" >&2; }
|
echo "cmake: a cmake-mode reference remains -- check it is harmless" >&2; }
|
||||||
echo "cmake: emacs byte-compilation dropped (the .el is installed regardless)"
|
echo "cmake: emacs byte-compilation dropped (the .el is installed regardless)"
|
||||||
|
|
||||||
|
# --- no Sphinx documentation ---------------------------------------------------
|
||||||
|
#
|
||||||
|
# CMake Error at Utilities/Sphinx/CMakeLists.txt:52 (message):
|
||||||
|
#
|
||||||
|
# cmake builds its own manual and man pages with Sphinx, requested by
|
||||||
|
# --sphinx-man and --sphinx-html in the bootstrap arguments. python-sphinx is not
|
||||||
|
# in this port: it is a large Python documentation stack, and cmake is wanted here
|
||||||
|
# as a build tool.
|
||||||
|
#
|
||||||
|
# BOTH FLAGS, and they are bootstrap arguments rather than -D options -- cmake
|
||||||
|
# configures itself with its own script before it can run itself. Dropping only
|
||||||
|
# one leaves the other pulling Sphinx in, and the error is identical, which is how
|
||||||
|
# a half-fix looks like no fix.
|
||||||
|
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.match(r"^[ \t]*--sphinx-(man|html)[ \t]*\\\\?$", l)]
|
||||||
|
assert len(hit) == 2, "cmake: expected two --sphinx flags, got %d" % len(hit)
|
||||||
|
# Backwards: deleting shifts everything after it.
|
||||||
|
for i in reversed(hit):
|
||||||
|
del lines[i]
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -qE "^[[:space:]]*--sphinx-" PKGBUILD && {
|
||||||
|
echo "cmake: a --sphinx flag survived" >&2; exit 1; }
|
||||||
|
echo "cmake: Sphinx manual and man pages dropped"
|
||||||
|
|
||||||
|
# --- and the html it no longer generates --------------------------------------
|
||||||
|
#
|
||||||
|
# rm: cannot remove '<pkgdir>/usr/share/doc/cmake/html/_sources': No such file
|
||||||
|
#
|
||||||
|
# ELEVENTH time in this port. With Sphinx off, cmake generates no html, and the
|
||||||
|
# PKGBUILD deletes _sources from it -- Sphinx leaves the reStructuredText inputs
|
||||||
|
# beside the rendered pages and they are not wanted in a package.
|
||||||
|
#
|
||||||
|
# rm -rf rather than deleted: on a machine with Sphinx the directory is real and
|
||||||
|
# still has to go.
|
||||||
|
python3 - <<'ZZPY'
|
||||||
|
import io, re
|
||||||
|
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
|
||||||
|
hit = [i for i, l in enumerate(lines) if "_sources" in l and l.lstrip().startswith("rm ")]
|
||||||
|
assert len(hit) == 1, "cmake: expected one _sources removal, got %d" % len(hit)
|
||||||
|
i = hit[0]
|
||||||
|
lines[i] = lines[i].replace("rm -r ", "rm -rf ", 1)
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -qE "^[[:space:]]*rm -rf .*_sources" PKGBUILD || {
|
||||||
|
echo "cmake: the _sources removal was not made tolerant" >&2; exit 1; }
|
||||||
|
echo "cmake: _sources cleanup tolerates its absence"
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,17 @@
|
||||||
# choice will have to be made then: build Rust, or drop the flag. Recorded now
|
# choice will have to be made then: build Rust, or drop the flag. Recorded now
|
||||||
# rather than discovered twice.
|
# rather than discovered twice.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
# STAGE 1 ONLY -- this section, not this file.
|
||||||
|
#
|
||||||
|
# It used to be expressed by naming this hook in STAGE2_SKIP_HOOKS, which skips
|
||||||
|
# the whole FILE. Then a section was appended that both stages need, and it
|
||||||
|
# silently never ran: the package kept failing in stage 2 on the very thing the
|
||||||
|
# new section fixes, and the log said "hook skipped (stage-1 only)" about a hook
|
||||||
|
# that was now two thirds relevant.
|
||||||
|
#
|
||||||
|
# The scope belongs next to the reason, so each section decides for itself.
|
||||||
|
if [ "${EL_STAGE:-1}" = 1 ]; then
|
||||||
|
|
||||||
python3 - <<'PY'
|
python3 - <<'PY'
|
||||||
import io
|
import io
|
||||||
s = io.open("PKGBUILD", encoding="utf-8").read()
|
s = io.open("PKGBUILD", encoding="utf-8").read()
|
||||||
|
|
@ -45,6 +56,9 @@ grep -q "'zlib-ng'" PKGBUILD && {
|
||||||
grep -qF "'grep' 'shadow' 'zlib')" PKGBUILD || {
|
grep -qF "'grep' 'shadow' 'zlib')" PKGBUILD || {
|
||||||
echo "git: zlib not substituted in depends" >&2; exit 1; }
|
echo "git: zlib not substituted in depends" >&2; exit 1; }
|
||||||
echo "git: plain zlib (no zlib-ng headers on the host); STAGE-1 ONLY"
|
echo "git: plain zlib (no zlib-ng headers on the host); STAGE-1 ONLY"
|
||||||
|
else
|
||||||
|
echo "git: zlib-ng available in the chroot; keeping Arch's choice"
|
||||||
|
fi
|
||||||
|
|
||||||
# --- no man pages -------------------------------------------------------------
|
# --- no man pages -------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
|
@ -76,3 +90,110 @@ ZZPY
|
||||||
grep -qE "\ball man\b|\binstall-man\b" PKGBUILD && {
|
grep -qE "\ball man\b|\binstall-man\b" PKGBUILD && {
|
||||||
echo "git: a man target survived" >&2; exit 1; }
|
echo "git: a man target survived" >&2; exit 1; }
|
||||||
echo "git: man pages dropped (no asciidoc, four places)"
|
echo "git: man pages dropped (no asciidoc, four places)"
|
||||||
|
|
||||||
|
# --- no Rust ------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# cargo: command not found
|
||||||
|
#
|
||||||
|
# git's PKGBUILD passes WITH_RUST=1 and lists rust in makedepends. This port does
|
||||||
|
# not package Rust, and packaging it is not a package: rustc bootstraps from a
|
||||||
|
# previous rustc, which is the one thing a from-source distribution cannot start
|
||||||
|
# from -- Arch ships a binary to break that cycle, and this port has no such
|
||||||
|
# escape on s390x.
|
||||||
|
#
|
||||||
|
# WHY IT SURFACED ONLY NOW. Stage 1 built git happily: the HOST has rustc, from
|
||||||
|
# apt. So this is another entry in the longest-running theme of the port -- a
|
||||||
|
# dependency the host satisfied invisibly, appearing the first time the chroot is
|
||||||
|
# the one being asked. And it appeared only after the man-page section above
|
||||||
|
# started running at stage 2, which it had not been doing.
|
||||||
|
#
|
||||||
|
# WITH_RUST=1 selects Rust reimplementations of some internals; git builds and
|
||||||
|
# behaves the same without it. Both stages, so the two agree: stage 1 was
|
||||||
|
# producing a git that stage 2 could not reproduce.
|
||||||
|
python3 - <<'ZZPY'
|
||||||
|
import io, re
|
||||||
|
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
|
||||||
|
# NO_RUST=1, not merely dropping WITH_RUST=1.
|
||||||
|
#
|
||||||
|
# Removing WITH_RUST=1 changed nothing -- cargo was still invoked:
|
||||||
|
#
|
||||||
|
# CARGO target/release/libgitcore.a
|
||||||
|
# /bin/sh: line 1: cargo: command not found
|
||||||
|
#
|
||||||
|
# The Makefile reads
|
||||||
|
#
|
||||||
|
# ifndef NO_RUST
|
||||||
|
# BASIC_CFLAGS += -DWITH_RUST
|
||||||
|
# GITLIBS += $(RUST_LIB)
|
||||||
|
#
|
||||||
|
# so Rust is built BY DEFAULT and the opt-out is NO_RUST. WITH_RUST=1 in the
|
||||||
|
# PKGBUILD sets a variable the Makefile never reads; deleting it was correct and
|
||||||
|
# insufficient, which is the worst combination -- the hook reported success and
|
||||||
|
# the build failed identically.
|
||||||
|
#
|
||||||
|
# Worth recording as an upstream change: git now needs a Rust toolchain unless
|
||||||
|
# told otherwise. For a distribution bootstrapped from source that is a real
|
||||||
|
# obstacle, because rustc bootstraps from a previous rustc.
|
||||||
|
hit = [i for i, l in enumerate(lines) if re.match(r"^[ \t]*WITH_RUST=1[ \t]*$", l)]
|
||||||
|
assert len(hit) == 1, "git: expected one WITH_RUST=1 line, got %d" % len(hit)
|
||||||
|
lines[hit[0]] = re.match(r"^[ \t]*", lines[hit[0]]).group(0) + "NO_RUST=1"
|
||||||
|
out = [l.replace(" 'rust'", "") if "makedepends" in l else l for l in lines]
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(out))
|
||||||
|
ZZPY
|
||||||
|
grep -qE "^[[:space:]]*WITH_RUST=1" PKGBUILD && { echo "git: WITH_RUST survived" >&2; exit 1; }
|
||||||
|
grep -qE "^[[:space:]]*NO_RUST=1" PKGBUILD || { echo "git: NO_RUST=1 was not set" >&2; exit 1; }
|
||||||
|
grep -q "'rust'" PKGBUILD && { echo "git: rust still in makedepends" >&2; exit 1; }
|
||||||
|
echo "git: built without Rust (no rustc to bootstrap from on s390x)"
|
||||||
|
|
||||||
|
# --- no libsecret credential helper -------------------------------------------
|
||||||
|
#
|
||||||
|
# make: *** [Makefile:20: git-credential-libsecret.o] Error 1
|
||||||
|
#
|
||||||
|
# contrib/credential/libsecret needs libsecret's headers, and libsecret is not in
|
||||||
|
# this port -- it is a GNOME keyring client, and behind it sit glib2 and
|
||||||
|
# gobject-introspection, the sub-project already declined for p11-kit.
|
||||||
|
#
|
||||||
|
# THREE PLACES, and one of them spans two lines:
|
||||||
|
#
|
||||||
|
# 52 _make -C contrib/credential/libsecret
|
||||||
|
# 106 install -m 0755 contrib/credential/libsecret/git-credential-libsecret \
|
||||||
|
# 107 "$pkgdir"/usr/lib/git-core/git-credential-libsecret
|
||||||
|
# 108 _make -C contrib/credential/libsecret clean
|
||||||
|
#
|
||||||
|
# The first version of this section asserted "expected one _make, got 2" and
|
||||||
|
# stopped, which is the guard doing its job. Replacing line 106 alone would leave
|
||||||
|
# 107 as a command of its own -- the binutils continuation trap again, and the
|
||||||
|
# reason the install is deleted as a range rather than commented.
|
||||||
|
#
|
||||||
|
# The optdepend line stays: it describes what the helper would need if someone
|
||||||
|
# built it, and it is a sentence, not a dependency.
|
||||||
|
python3 - <<'ZZPY'
|
||||||
|
import io, re
|
||||||
|
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
|
||||||
|
|
||||||
|
mk = [i for i, l in enumerate(lines)
|
||||||
|
if re.search(r"_make -C contrib/credential/libsecret", l)]
|
||||||
|
assert len(mk) == 2, "git: expected two libsecret _make lines, got %d" % len(mk)
|
||||||
|
|
||||||
|
ins = [i for i, l in enumerate(lines)
|
||||||
|
if re.match(r"^[ \t]*install ", l) and "credential/libsecret" in l]
|
||||||
|
assert len(ins) == 1, "git: expected one libsecret install, got %d" % len(ins)
|
||||||
|
i = ins[0]
|
||||||
|
j = i
|
||||||
|
while lines[j].rstrip().endswith("\\"):
|
||||||
|
j += 1
|
||||||
|
# Delete the install and its continuations, then neutralise both _make lines.
|
||||||
|
# Backwards, so earlier indices stay valid.
|
||||||
|
for k in reversed(mk):
|
||||||
|
ind = re.match(r"^[ \t]*", lines[k]).group(0)
|
||||||
|
lines[k] = ind + ": # libsecret is not packaged here (glib2, gobject-introspection)."
|
||||||
|
del lines[i:j + 1]
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -qE "^[[:space:]]*_make -C contrib/credential/libsecret" PKGBUILD && {
|
||||||
|
echo "git: a libsecret build survived" >&2; exit 1; }
|
||||||
|
grep -qE "^[[:space:]]*install .*credential/libsecret" PKGBUILD && {
|
||||||
|
echo "git: the libsecret install survived" >&2; exit 1; }
|
||||||
|
grep -q "git-credential-libsecret" PKGBUILD && {
|
||||||
|
echo "git: a reference to the helper binary survived" >&2; exit 1; }
|
||||||
|
echo "git: libsecret credential helper dropped"
|
||||||
|
|
|
||||||
41
patches/pkgbuild/gnupg.sh
Executable file
41
patches/pkgbuild/gnupg.sh
Executable file
|
|
@ -0,0 +1,41 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# gnupg: no manual, because two diagrams in it need two image toolchains.
|
||||||
|
#
|
||||||
|
# /bin/sh: line 1: convert: command not found
|
||||||
|
# make[2]: *** [Makefile:1199: gnupg-module-overview.pdf] Error 127
|
||||||
|
# /bin/sh: line 1: fig2dev: command not found
|
||||||
|
# make[2]: *** [Makefile:1211: gnupg-card-architecture.pdf] Error 127
|
||||||
|
#
|
||||||
|
# `convert` is ImageMagick, `fig2dev` is transfig. Two separate toolchains, for
|
||||||
|
# two architecture diagrams in gnupg's own documentation.
|
||||||
|
#
|
||||||
|
# --disable-doc is gnupg's own switch, and it was CHECKED before being used:
|
||||||
|
# `grep -oE '\-\-(disable|enable)-doc' configure` finds both, so autoconf knows
|
||||||
|
# the option. groff had no such switch and needed its generated Makefile edited
|
||||||
|
# instead -- the difference matters, because an invented flag draws only a
|
||||||
|
# warning from autoconf and the build fails exactly as before, with the hook's
|
||||||
|
# own check passing.
|
||||||
|
set -euo pipefail
|
||||||
|
# AN ARRAY, not a continued command. The first version of this hook looked for a
|
||||||
|
# ./configure line ending in a backslash and asserted its way out:
|
||||||
|
#
|
||||||
|
# AssertionError: gnupg: ./configure does not continue
|
||||||
|
#
|
||||||
|
# gnupg collects its options in `local configure_options=( ... )` and then calls
|
||||||
|
# `./configure "${configure_options[@]}"`. Both shapes appear in this port --
|
||||||
|
# binutils, cryptsetup and libxcrypt use continued commands; gnupg and shadow use
|
||||||
|
# arrays -- so a hook has to look at the file rather than assume the house style.
|
||||||
|
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.match(r"^[ \t]*local configure_options=\($", l)]
|
||||||
|
assert len(hit) == 1, "gnupg: expected one configure_options array, got %d" % len(hit)
|
||||||
|
i = hit[0] + 1
|
||||||
|
ind = re.match(r"^[ \t]*", lines[i]).group(0)
|
||||||
|
# The array is kept in alphabetical order upstream; --disable-doc sorts first.
|
||||||
|
lines.insert(i, ind + "--disable-doc # no ImageMagick, no transfig for the diagrams")
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -A2 "local configure_options=(" PKGBUILD | grep -q -- "--disable-doc" || {
|
||||||
|
echo "gnupg: the flag is not inside the options array" >&2; exit 1; }
|
||||||
|
echo "gnupg: manual disabled (no ImageMagick, no transfig)"
|
||||||
|
|
@ -36,6 +36,53 @@ lines[i:i] = [
|
||||||
ind + "# package. The install side already skips the file when it is absent.",
|
ind + "# package. The install side already skips the file when it is absent.",
|
||||||
ind + 'sed -i "s|^DOC_GNU_EPS = doc/gnu.eps$|DOC_GNU_EPS =|" Makefile',
|
ind + 'sed -i "s|^DOC_GNU_EPS = doc/gnu.eps$|DOC_GNU_EPS =|" Makefile',
|
||||||
ind + 'grep -q "^DOC_GNU_EPS =$" Makefile',
|
ind + 'grep -q "^DOC_GNU_EPS =$" Makefile',
|
||||||
|
ind + "# And its CONSUMER. Emptying DOC_GNU_EPS removed the rule that",
|
||||||
|
ind + "# builds the figure and not the document that includes it:",
|
||||||
|
ind + "#",
|
||||||
|
ind + "# doc/webpage.ms:45: error: cannot open 'gnu.eps'",
|
||||||
|
ind + "# doc/webpage.ms:45: fatal error: PSPIC failed to include 'gnu.eps'",
|
||||||
|
ind + "#",
|
||||||
|
ind + "# PROCESSEDEXAMPLEFILES_PS lists webpage.ps and grnexmpl.ps. The",
|
||||||
|
ind + "# HTML variant right above it is ALREADY empty, with its real value",
|
||||||
|
ind + "# left as a comment -- groff's own configure empties that one when",
|
||||||
|
ind + "# the tools are missing. This does the same for PS, which is the",
|
||||||
|
ind + "# decision groff would have made had it checked.",
|
||||||
|
ind + 'sed -i "/^PROCESSEDEXAMPLEFILES_PS = /,/^$/ s|^.*$||" Makefile',
|
||||||
|
ind + 'grep -q "^PROCESSEDEXAMPLEFILES_PS" Makefile && { echo "groff: PS example list not emptied" >&2; exit 1; }',
|
||||||
|
ind + "# THE SECOND consumer. Two files include the logo, and only two --",
|
||||||
|
ind + "# counted rather than guessed:",
|
||||||
|
ind + "#",
|
||||||
|
ind + "# doc/webpage.ms (above)",
|
||||||
|
ind + "# contrib/hdtbl/examples/mixed_pickles.roff (this)",
|
||||||
|
ind + "#",
|
||||||
|
ind + "# hdtbl renders its example tables to PostScript, and one of them shows",
|
||||||
|
ind + "# the GNU logo. HDTBLPROCESSEDEXAMPLEFILES lists all twelve; the whole",
|
||||||
|
ind + "# list goes, because there is no reason to render eleven examples of a",
|
||||||
|
ind + "# table macro package into a documentation set nothing here reads.",
|
||||||
|
ind + "# ALL of them, not one per failure. This is the third round on the",
|
||||||
|
ind + "# same package: DOC_GNU_EPS, then PROCESSEDEXAMPLEFILES_PS, then",
|
||||||
|
ind + "# HDTBL, and mom's examples were waiting behind those --",
|
||||||
|
ind + "#",
|
||||||
|
ind + "# pdfmom: fatal error: test-groff exited with status 4",
|
||||||
|
ind + "# contrib/mom/examples/typesetting.pdf",
|
||||||
|
ind + "#",
|
||||||
|
ind + "# groff renders its own manuals and every contrib package's examples",
|
||||||
|
ind + "# to PostScript and PDF using the groff being built. Each list is a",
|
||||||
|
ind + "# separate variable, and finding them one failure at a time is how",
|
||||||
|
ind + "# three passes went by. They are emptied together.",
|
||||||
|
ind + 'for _v in HDTBLPROCESSEDEXAMPLEFILES MOMPROCESSEDEXAMPLEFILES \\',
|
||||||
|
ind + ' PROCESSEDDOCFILES_PDF PROCESSEDDOCFILES_PS \\',
|
||||||
|
ind + ' PROCESSEDDOCFILES_TXT PROCESSEDDOCFILES \\',
|
||||||
|
ind + ' GENERATEDDOCFILES; do',
|
||||||
|
ind + ' sed -i "/^$_v = /,/^$/ s|^.*$||" Makefile',
|
||||||
|
ind + ' grep -q "^$_v" Makefile && { echo "groff: $_v not emptied" >&2; exit 1; }',
|
||||||
|
ind + 'done',
|
||||||
|
ind + "# And say it out loud: if a THIRD consumer appears, this is the pattern",
|
||||||
|
ind + "# to look for, not a new kind of problem.",
|
||||||
|
ind + 'if grep -rl "gnu\\.eps" --include="*.roff" --include="*.ms" . 2>/dev/null | grep -qv "^\\./doc/webpage.ms$\\|mixed_pickles"; then',
|
||||||
|
ind + ' echo "groff: a third file includes gnu.eps; see patches/pkgbuild/groff.sh" >&2',
|
||||||
|
ind + ' exit 1',
|
||||||
|
ind + 'fi',
|
||||||
]
|
]
|
||||||
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
ZZPY
|
ZZPY
|
||||||
|
|
|
||||||
|
|
@ -26,3 +26,34 @@ io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
ZZPY
|
ZZPY
|
||||||
grep -q "doxybuild" PKGBUILD && { echo "jsoncpp: doxybuild survived" >&2; exit 1; }
|
grep -q "doxybuild" PKGBUILD && { echo "jsoncpp: doxybuild survived" >&2; exit 1; }
|
||||||
echo "jsoncpp: doxygen build removed"
|
echo "jsoncpp: doxygen build removed"
|
||||||
|
|
||||||
|
# --- and the html it no longer generates --------------------------------------
|
||||||
|
#
|
||||||
|
# cp: cannot stat 'dist/doxygen/jsoncpp-api-html-1.9.6': No such file or dir
|
||||||
|
#
|
||||||
|
# FOURTEENTH time, and the sixth of my own making. Removing the doxybuild.py call
|
||||||
|
# above stopped the API html being generated, and package() still copies the
|
||||||
|
# directory it would have produced. The name carries the version, so the path is
|
||||||
|
# not even greppable without knowing pkgver.
|
||||||
|
#
|
||||||
|
# By now the rule is mechanical and worth stating as a procedure rather than a
|
||||||
|
# lesson: after removing a documentation build, grep package() for the OUTPUT
|
||||||
|
# directory name, not for the tool. The tool appears in build(); the path appears
|
||||||
|
# in package(), and it is the path that fails.
|
||||||
|
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 "doxygen" in l and re.match(r"^[ \t]*(cp|mv|install) ", l)]
|
||||||
|
assert len(hit) >= 1, "jsoncpp: no doxygen output copy found in package()"
|
||||||
|
for i in reversed(hit):
|
||||||
|
j = i
|
||||||
|
while lines[j].rstrip().endswith("\\"):
|
||||||
|
j += 1
|
||||||
|
ind = re.match(r"^[ \t]*", lines[i]).group(0)
|
||||||
|
lines[i:j + 1] = [ind + ": # the doxygen html is not generated (no doxygen here)."]
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -qE "^[[:space:]]*(cp|mv|install) .*doxygen" PKGBUILD && {
|
||||||
|
echo "jsoncpp: a doxygen output copy survived" >&2; exit 1; }
|
||||||
|
echo "jsoncpp: doxygen html copy removed"
|
||||||
|
|
|
||||||
|
|
@ -37,16 +37,41 @@
|
||||||
# It also means these build on the HOST, where they had failed, so they need no
|
# It also means these build on the HOST, where they had failed, so they need no
|
||||||
# stage-2 special handling at all.
|
# stage-2 special handling at all.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
# A PROBE, not a constant, and it runs in the BUILD ENVIRONMENT.
|
||||||
|
#
|
||||||
|
# The first version set _bootstrap=1 unconditionally. That is right on a machine
|
||||||
|
# with no Python packaging stack and wrong the moment there is one, because the
|
||||||
|
# vendored builder carries its OWN copy of each project -- older than the
|
||||||
|
# PKGBUILD's pkgver. python-packaging was labelled 26.3 and installed 25.0, and
|
||||||
|
# the mismatch surfaced two packages later:
|
||||||
|
#
|
||||||
|
# python-vcs-versioning: packaging>=26.2
|
||||||
|
#
|
||||||
|
# a floor our own package met on paper and not in fact. Nothing about the
|
||||||
|
# installed package looked wrong; only `import packaging; packaging.__version__`
|
||||||
|
# disagreed with its name.
|
||||||
|
#
|
||||||
|
# So the PKGBUILD decides at build time, where the answer is knowable: if `build`
|
||||||
|
# and `installer` import, the real path works and the vendored copies are not
|
||||||
|
# wanted. Hooks run on the HOST even for stage 2, so a probe written here could
|
||||||
|
# not answer for the chroot -- this one is evaluated by makepkg, inside it.
|
||||||
python3 - <<'ZZPY'
|
python3 - <<'ZZPY'
|
||||||
import io
|
import io
|
||||||
s = io.open("PKGBUILD", encoding="utf-8").read()
|
s = io.open("PKGBUILD", encoding="utf-8").read()
|
||||||
old = "_bootstrap=0"
|
old = "_bootstrap=0"
|
||||||
assert s.count(old) == 1, "python bootstrap: expected one _bootstrap=0, got %d" % s.count(old)
|
assert s.count(old) == 1, "python bootstrap: expected one _bootstrap=0, got %d" % s.count(old)
|
||||||
s = s.replace(old, "_bootstrap=1 # see patches/pkgbuild/lib-python-bootstrap.sh", 1)
|
new = ("# Bootstrap only when the real path is unavailable -- see\n"
|
||||||
|
"# patches/pkgbuild/lib-python-bootstrap.sh. Evaluated by makepkg, in the\n"
|
||||||
|
"# build environment, because that is where the answer lives.\n"
|
||||||
|
"_bootstrap=1\n"
|
||||||
|
"python -c 'import build, installer' >/dev/null 2>&1 && _bootstrap=0")
|
||||||
|
s = s.replace(old, new, 1)
|
||||||
io.open("PKGBUILD", "w", encoding="utf-8").write(s)
|
io.open("PKGBUILD", "w", encoding="utf-8").write(s)
|
||||||
ZZPY
|
ZZPY
|
||||||
grep -q "^_bootstrap=1" PKGBUILD || {
|
grep -q "^_bootstrap=1$" PKGBUILD || {
|
||||||
echo "python bootstrap: _bootstrap was not switched" >&2; exit 1; }
|
echo "python bootstrap: the default was not set to 1" >&2; exit 1; }
|
||||||
|
grep -q "import build, installer" PKGBUILD || {
|
||||||
|
echo "python bootstrap: the probe was not inserted" >&2; exit 1; }
|
||||||
# The branch it selects must actually exist, or the switch silently builds
|
# The branch it selects must actually exist, or the switch silently builds
|
||||||
# nothing -- these PKGBUILDs are not required to have both halves.
|
# nothing -- these PKGBUILDs are not required to have both halves.
|
||||||
grep -q "bootstrap.build" PKGBUILD || {
|
grep -q "bootstrap.build" PKGBUILD || {
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,15 @@
|
||||||
# leaves the package uninstallable for a reason the diff appears to fix -- the
|
# leaves the package uninstallable for a reason the diff appears to fix -- the
|
||||||
# fifth place, and the one that has cost the most time in this port.
|
# fifth place, and the one that has cost the most time in this port.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# STAGE 1 ONLY, the whole file. Expressed here rather than in a list kept by the
|
||||||
|
# driver: a list of file names cannot say WHY, and when a hook later grows a
|
||||||
|
# section that both stages need, the list silently skips that too. That happened
|
||||||
|
# to git and meson.
|
||||||
|
if [ "${EL_STAGE:-1}" != 1 ]; then
|
||||||
|
echo "libarchive: nothing to do at stage 2 -- our libxml2 and icu agree in the chroot"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
python3 - <<'ZZPY'
|
python3 - <<'ZZPY'
|
||||||
import io, re
|
import io, re
|
||||||
s = io.open("PKGBUILD", encoding="utf-8").read()
|
s = io.open("PKGBUILD", encoding="utf-8").read()
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,32 @@ io.open("PKGBUILD", "w", encoding="utf-8").write(s)
|
||||||
ZZPY
|
ZZPY
|
||||||
grep -q "EVENT__DOXYGEN=OFF" PKGBUILD || { echo "libevent: doxygen not disabled" >&2; exit 1; }
|
grep -q "EVENT__DOXYGEN=OFF" PKGBUILD || { echo "libevent: doxygen not disabled" >&2; exit 1; }
|
||||||
echo "libevent: Doxygen reference disabled"
|
echo "libevent: Doxygen reference disabled"
|
||||||
|
|
||||||
|
# --- and the docs split, which I left behind ----------------------------------
|
||||||
|
#
|
||||||
|
# mv: cannot stat '<pkgdir>/usr/share/doc': No such file or directory
|
||||||
|
#
|
||||||
|
# Turning EVENT__DOXYGEN off above stopped the documentation being BUILT and left
|
||||||
|
# package() moving it into the libevent-doc split:
|
||||||
|
#
|
||||||
|
# mv {"$pkgdir",doc}/usr/share/doc
|
||||||
|
#
|
||||||
|
# NINTH time in this port, and the second time I have made it myself rather than
|
||||||
|
# inherited it: fakeroot was the other. Removing a documentation build without
|
||||||
|
# removing its install is apparently the easiest mistake available here, so it is
|
||||||
|
# worth stating the rule plainly -- after disabling documentation anywhere,
|
||||||
|
# search package() for share/doc, man, and the split arrays before believing the
|
||||||
|
# hook is finished.
|
||||||
|
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"share/doc", l) and l.lstrip().startswith("mv ")]
|
||||||
|
assert len(hit) == 1, "libevent: expected one share/doc move, got %d" % len(hit)
|
||||||
|
i = hit[0]
|
||||||
|
ind = re.match(r"^[ \t]*", lines[i]).group(0)
|
||||||
|
lines[i] = ind + ': # doxygen is off above, so usr/share/doc is never created.'
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -qE "^[[:space:]]*mv .*share/doc" PKGBUILD && {
|
||||||
|
echo "libevent: the docs move survived" >&2; exit 1; }
|
||||||
|
echo "libevent: docs split removed (nothing builds them now)"
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,15 @@
|
||||||
# MAKEFLAGS bound inside build() rather than at hook level.
|
# MAKEFLAGS bound inside build() rather than at hook level.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# STAGE 1 ONLY, the whole file. Expressed here rather than in a list kept by the
|
||||||
|
# driver: a list of file names cannot say WHY, and when a hook later grows a
|
||||||
|
# section that both stages need, the list silently skips that too. That happened
|
||||||
|
# to git and meson.
|
||||||
|
if [ "${EL_STAGE:-1}" != 1 ]; then
|
||||||
|
echo "libgcrypt: nothing to do at stage 2 -- our libgpg-error is installed in the chroot"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
WORK="${WORK:-$HOME/work/arch-s390x}"
|
WORK="${WORK:-$HOME/work/arch-s390x}"
|
||||||
PREFIX="$WORK/stage1-prefix"
|
PREFIX="$WORK/stage1-prefix"
|
||||||
|
|
||||||
|
|
|
||||||
39
patches/pkgbuild/llvm.sh
Executable file
39
patches/pkgbuild/llvm.sh
Executable file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# llvm: no Sphinx documentation.
|
||||||
|
#
|
||||||
|
# -DLLVM_ENABLE_SPHINX=ON pulls in python-sphinx and python-myst-parser, and
|
||||||
|
# behind those sit docutils, babel, pygments, snowballstemmer, imagesize,
|
||||||
|
# alabaster, the sphinxcontrib-* family, markdown-it-py and mdit-py-plugins --
|
||||||
|
# fifteen or so packages whose entire purpose here would be to render HTML for a
|
||||||
|
# compiler nothing in this port reads the manual of.
|
||||||
|
#
|
||||||
|
# MEASURED BEFORE CHOOSING, the way glib2 and iproute2 were: llvm and clang need
|
||||||
|
# only libedit and python-psutil beyond what this port already has. Sphinx is the
|
||||||
|
# whole of the rest of the bill, and one flag removes it.
|
||||||
|
#
|
||||||
|
# AND THE CLEANUP, found before it failed. package() ends on
|
||||||
|
#
|
||||||
|
# rm -r "$pkgdir"/usr/share/doc/.../html/{_sources,.buildinfo}
|
||||||
|
#
|
||||||
|
# which Sphinx creates and which will not exist. This is the seventeenth
|
||||||
|
# appearance of that shape in this port; the procedure written in jsoncpp's hook
|
||||||
|
# says to grep package() for the OUTPUT paths after disabling a documentation
|
||||||
|
# build, and this is the first time it was done before the build rather than
|
||||||
|
# after. rm -rf rather than deleted: on a machine with Sphinx the directory is
|
||||||
|
# real and still has to go.
|
||||||
|
set -euo pipefail
|
||||||
|
python3 - <<'ZZPY'
|
||||||
|
import io, re
|
||||||
|
s = io.open("PKGBUILD", encoding="utf-8").read()
|
||||||
|
old = "-DLLVM_ENABLE_SPHINX=ON"
|
||||||
|
assert s.count(old) == 1, "llvm: expected one LLVM_ENABLE_SPHINX, got %d" % s.count(old)
|
||||||
|
s = s.replace(old, "-DLLVM_ENABLE_SPHINX=OFF", 1)
|
||||||
|
lines = s.split("\n")
|
||||||
|
hit = [i for i, l in enumerate(lines) if "_sources" in l and l.lstrip().startswith("rm ")]
|
||||||
|
assert len(hit) == 1, "llvm: expected one _sources removal, got %d" % len(hit)
|
||||||
|
lines[hit[0]] = lines[hit[0]].replace("rm -r ", "rm -rf ", 1)
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -q -- "-DLLVM_ENABLE_SPHINX=OFF" PKGBUILD || { echo "llvm: sphinx not disabled" >&2; exit 1; }
|
||||||
|
grep -qE "^[[:space:]]*rm -rf .*_sources" PKGBUILD || { echo "llvm: the cleanup is not tolerant" >&2; exit 1; }
|
||||||
|
echo "llvm: Sphinx documentation disabled, cleanup made tolerant"
|
||||||
|
|
@ -40,6 +40,17 @@
|
||||||
# will actually import this. Deriving it from the interpreter running the build
|
# will actually import this. Deriving it from the interpreter running the build
|
||||||
# is the intuitive thing and the wrong one.
|
# is the intuitive thing and the wrong one.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
# STAGE 1 ONLY -- this section, not this file.
|
||||||
|
#
|
||||||
|
# It used to be expressed by naming this hook in STAGE2_SKIP_HOOKS, which skips
|
||||||
|
# the whole FILE. Then a section was appended that both stages need, and it
|
||||||
|
# silently never ran: the package kept failing in stage 2 on the very thing the
|
||||||
|
# new section fixes, and the log said "hook skipped (stage-1 only)" about a hook
|
||||||
|
# that was now two thirds relevant.
|
||||||
|
#
|
||||||
|
# The scope belongs next to the reason, so each section decides for itself.
|
||||||
|
if [ "${EL_STAGE:-1}" = 1 ]; then
|
||||||
|
|
||||||
python3 - <<'ZZPY'
|
python3 - <<'ZZPY'
|
||||||
import io
|
import io
|
||||||
s = io.open("PKGBUILD", encoding="utf-8").read()
|
s = io.open("PKGBUILD", encoding="utf-8").read()
|
||||||
|
|
@ -89,6 +100,9 @@ ZZPY
|
||||||
grep -q 'posix_local scheme installs' PKGBUILD || {
|
grep -q 'posix_local scheme installs' PKGBUILD || {
|
||||||
echo "meson: the relocation was not inserted" >&2; exit 1; }
|
echo "meson: the relocation was not inserted" >&2; exit 1; }
|
||||||
echo "meson: wheel relocated out of /usr/local; STAGE-1 ONLY"
|
echo "meson: wheel relocated out of /usr/local; STAGE-1 ONLY"
|
||||||
|
else
|
||||||
|
echo "meson: chroot python has no posix_local scheme; no relocation needed"
|
||||||
|
fi
|
||||||
|
|
||||||
# --- no reference manual ------------------------------------------------------
|
# --- no reference manual ------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
|
|
||||||
106
patches/pkgbuild/p11-kit.sh
Executable file
106
patches/pkgbuild/p11-kit.sh
Executable file
|
|
@ -0,0 +1,106 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# p11-kit: no gtk-doc manual.
|
||||||
|
#
|
||||||
|
# meson.build:65:18: ERROR: Dependency "glib-2.0" not found (tried pkgconfig)
|
||||||
|
#
|
||||||
|
# THIS ONE WAS NEARLY A SUB-PROJECT. glib-2.0 is not in this port, and adding it
|
||||||
|
# is not one package: Arch's glib2 wants gobject-introspection (which itself
|
||||||
|
# needs glib2 -- a cycle to bootstrap), libsysprof-capture, dconf and gi-docgen.
|
||||||
|
# Several packages and a circular dependency, for one entry in one build.
|
||||||
|
#
|
||||||
|
# Reading where the requirement actually comes from changed the answer entirely.
|
||||||
|
# The file is doc/manual/meson.build, and the line is
|
||||||
|
#
|
||||||
|
# glib_prefix = dependency('glib-2.0').get_variable(pkgconfig : 'prefix')
|
||||||
|
#
|
||||||
|
# glib is consulted to find where gtk-doc keeps its cross-reference files. It is
|
||||||
|
# not linked, not called, and nothing in p11-kit's code touches it. -D gtk_doc
|
||||||
|
# is already in the PKGBUILD's option list, set to true; turning it false drops
|
||||||
|
# the whole doc/manual subdirectory and the dependency with it.
|
||||||
|
#
|
||||||
|
# The lesson is the one this port keeps relearning: the error names glib, and
|
||||||
|
# glib is not the subject. Six lines of context said so.
|
||||||
|
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.match(r"^[ \t]*-D gtk_doc=true[ \t]*$", l)]
|
||||||
|
assert len(hit) == 1, "p11-kit: expected one -D gtk_doc=true, got %d" % len(hit)
|
||||||
|
lines[hit[0]] = lines[hit[0]].replace("gtk_doc=true", "gtk_doc=false")
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -q -- "-D gtk_doc=false" PKGBUILD || { echo "p11-kit: gtk_doc not disabled" >&2; exit 1; }
|
||||||
|
echo "p11-kit: gtk-doc manual disabled (glib was only locating its xrefs)"
|
||||||
|
|
||||||
|
# --- and no man pages either --------------------------------------------------
|
||||||
|
#
|
||||||
|
# With gtk_doc off, the next line was
|
||||||
|
#
|
||||||
|
# meson.build:94:4: ERROR: Problem encountered: Docbook stylesheet for man
|
||||||
|
# pages not found
|
||||||
|
#
|
||||||
|
# The stylesheets, not xsltproc -- which our libxslt supplies. Third package to
|
||||||
|
# stop on exactly this: pam validates DocBook sources it cannot fetch, shadow
|
||||||
|
# renders man pages from them. Shipping docbook-xsl would be a package that only
|
||||||
|
# documentation needs; -D man is already in the option list.
|
||||||
|
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.match(r"^[ \t]*-D man=true[ \t]*$", l)]
|
||||||
|
assert len(hit) == 1, "p11-kit: expected one -D man=true, got %d" % len(hit)
|
||||||
|
lines[hit[0]] = lines[hit[0]].replace("man=true", "man=false")
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -q -- "-D man=false" PKGBUILD || { echo "p11-kit: man not disabled" >&2; exit 1; }
|
||||||
|
echo "p11-kit: man pages disabled (DocBook stylesheets absent, not xsltproc)"
|
||||||
|
|
||||||
|
# --- and the gtk-doc split ----------------------------------------------------
|
||||||
|
#
|
||||||
|
# mv: cannot stat '<pkgdir>/usr/share/gtk-doc': No such file or directory
|
||||||
|
#
|
||||||
|
# TWELFTH time. -D gtk_doc=false above stopped the documentation being built and
|
||||||
|
# left package() splitting it out:
|
||||||
|
#
|
||||||
|
# _pick doc "$pkgdir"/usr/share/gtk-doc
|
||||||
|
#
|
||||||
|
# _pick is Arch's helper for moving a path into a sub-package, and it is as fatal
|
||||||
|
# on a missing path as a bare mv.
|
||||||
|
python3 - <<'ZZPY'
|
||||||
|
import io, re
|
||||||
|
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
|
||||||
|
hit = [i for i, l in enumerate(lines) if "gtk-doc" in l and "_pick" in l]
|
||||||
|
assert len(hit) == 1, "p11-kit: expected one gtk-doc _pick, got %d" % len(hit)
|
||||||
|
i = hit[0]
|
||||||
|
ind = re.match(r"^[ \t]*", lines[i]).group(0)
|
||||||
|
lines[i] = ind + ": # gtk_doc is false above, so usr/share/gtk-doc is never created."
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -qE "_pick doc .*gtk-doc" PKGBUILD && {
|
||||||
|
echo "p11-kit: the gtk-doc pick survived" >&2; exit 1; }
|
||||||
|
echo "p11-kit: gtk-doc split removed (nothing builds it now)"
|
||||||
|
|
||||||
|
# --- and the doc sub-package that now stages nothing --------------------------
|
||||||
|
#
|
||||||
|
# mv: cannot stat 'doc/*': No such file or directory
|
||||||
|
#
|
||||||
|
# THIRTEENTH time, and the third layer of the same package. Neutralising the
|
||||||
|
# _pick above stopped anything being staged into doc/, and package_p11-kit-doc()
|
||||||
|
# still runs `mv doc/* "$pkgdir"`. _pick, mv, and now the sub-package function
|
||||||
|
# that consumes what _pick staged: three places for one decision.
|
||||||
|
#
|
||||||
|
# The lesson is stated plainly because five of these have been mine: disabling a
|
||||||
|
# documentation build means following it through the ENTIRE package() chain --
|
||||||
|
# the build flag, the staging, and the sub-package that reads the staging area.
|
||||||
|
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.match(r"^[ \t]*mv doc/\* ", l)]
|
||||||
|
assert len(hit) == 1, "p11-kit: expected one `mv doc/*`, got %d" % len(hit)
|
||||||
|
i = hit[0]
|
||||||
|
ind = re.match(r"^[ \t]*", lines[i]).group(0)
|
||||||
|
lines[i] = ind + ": # nothing is staged into doc/: gtk_doc and man are both off."
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -qE "^[[:space:]]*mv doc/\*" PKGBUILD && {
|
||||||
|
echo "p11-kit: the doc move survived" >&2; exit 1; }
|
||||||
|
echo "p11-kit: doc sub-package stages nothing, and no longer tries"
|
||||||
|
|
@ -22,3 +22,31 @@ io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
ZZPY
|
ZZPY
|
||||||
grep -q -- "-Ddocs=disabled" PKGBUILD || { echo "pam: docs not disabled" >&2; exit 1; }
|
grep -q -- "-Ddocs=disabled" PKGBUILD || { echo "pam: docs not disabled" >&2; exit 1; }
|
||||||
echo "pam: DocBook documentation disabled"
|
echo "pam: DocBook documentation disabled"
|
||||||
|
|
||||||
|
# --- and the PDFs it no longer produces ---------------------------------------
|
||||||
|
#
|
||||||
|
# rm: cannot remove '<pkgdir>/usr/share/doc/Linux-PAM/*.pdf': No such file
|
||||||
|
#
|
||||||
|
# The line above it says why it exists:
|
||||||
|
#
|
||||||
|
# # remove unreproducible pdf files
|
||||||
|
#
|
||||||
|
# pam builds PDFs whose bytes differ between runs, so the PKGBUILD deletes them
|
||||||
|
# to keep the package reproducible. With -Ddocs=disabled they are never built,
|
||||||
|
# and a cleanup step that finds nothing to clean is fatal under set -e.
|
||||||
|
#
|
||||||
|
# The rm becomes tolerant rather than being deleted: on a machine that does have
|
||||||
|
# the DocBook stack, the PDFs WILL be there and they still have to go.
|
||||||
|
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"\*\.pdf", l) and l.lstrip().startswith("rm ")]
|
||||||
|
assert len(hit) == 1, "pam: expected one pdf removal, got %d" % len(hit)
|
||||||
|
i = hit[0]
|
||||||
|
ind = re.match(r"^[ \t]*", lines[i]).group(0)
|
||||||
|
lines[i] = ind + "rm -f " + lines[i].lstrip()[3:].lstrip()
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -qE "^[[:space:]]*rm -f .*\*\.pdf" PKGBUILD || {
|
||||||
|
echo "pam: the pdf removal was not made tolerant" >&2; exit 1; }
|
||||||
|
echo "pam: PDF cleanup tolerates their absence"
|
||||||
|
|
|
||||||
38
patches/pkgbuild/python-jinja.sh
Executable file
38
patches/pkgbuild/python-jinja.sh
Executable file
|
|
@ -0,0 +1,38 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# python-jinja: our flit_core is NEWER than jinja will accept.
|
||||||
|
#
|
||||||
|
# * Getting build dependencies for wheel...
|
||||||
|
# ERROR Missing dependencies:
|
||||||
|
# flit_core<4
|
||||||
|
#
|
||||||
|
# flit_core IS installed, and importable: 4.0.2. jinja's pyproject.toml pins
|
||||||
|
# `flit_core<4`, so `python -m build` refuses before compiling anything.
|
||||||
|
#
|
||||||
|
# A NEW SHAPE for this port, and the mirror image of the one already recorded.
|
||||||
|
# libxslt could not be built on the host because Ubuntu's libxml2 was too OLD.
|
||||||
|
# Here our own package is too NEW for another package's declared ceiling. Both
|
||||||
|
# read as a missing dependency; neither is one.
|
||||||
|
#
|
||||||
|
# --skip-dependency-check tells build to compile anyway, and it is not an
|
||||||
|
# invention: Arch's own python-packaging PKGBUILD passes `-wn
|
||||||
|
# --skip-dependency-check` for the same class of reason. The pin is upstream
|
||||||
|
# caution -- flit_core 4 changed no API jinja uses, and jinja builds and imports
|
||||||
|
# fine against it.
|
||||||
|
#
|
||||||
|
# The honest alternative was pinning flit-core to 3.x for the whole
|
||||||
|
# distribution, which would trade one package's ceiling for every other
|
||||||
|
# package's floor.
|
||||||
|
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"python -m build\b", l)]
|
||||||
|
assert len(hit) == 1, "python-jinja: expected one `python -m build`, got %d" % len(hit)
|
||||||
|
i = hit[0]
|
||||||
|
assert "--skip-dependency-check" not in lines[i], "python-jinja: already skipping"
|
||||||
|
lines[i] = lines[i].rstrip() + " --skip-dependency-check"
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -q -- "python -m build .*--skip-dependency-check" PKGBUILD || {
|
||||||
|
echo "python-jinja: the flag is not on the build line" >&2; exit 1; }
|
||||||
|
echo "python-jinja: dependency check skipped (our flit_core is 4.x, the pin says <4)"
|
||||||
|
|
@ -23,10 +23,34 @@ import io, re
|
||||||
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
|
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
|
||||||
hit = [i for i, l in enumerate(lines) if "LICENSE*" in l and "$_name-$pkgver" in l]
|
hit = [i for i, l in enumerate(lines) if "LICENSE*" in l and "$_name-$pkgver" in l]
|
||||||
assert len(hit) == 1, "python-packaging: expected one license install, got %d" % len(hit)
|
assert len(hit) == 1, "python-packaging: expected one license install, got %d" % len(hit)
|
||||||
lines[hit[0]] = lines[hit[0]].replace("$srcdir/$_name-$pkgver/LICENSE*",
|
# BOTH LAYOUTS, because _bootstrap is now a probe rather than a constant
|
||||||
"$srcdir/$pkgname/LICENSE*")
|
# (see lib-python-bootstrap.sh). With the vendored builder the sources are git
|
||||||
|
# clones under $srcdir/$pkgname; without it they are the release tarball under
|
||||||
|
# $srcdir/$_name-$pkgver. Hardcoding either one breaks the other, and the first
|
||||||
|
# version of this hook hardcoded the clone -- correct only while _bootstrap was
|
||||||
|
# always 1.
|
||||||
|
lines[hit[0]] = re.sub(
|
||||||
|
r"\$srcdir/\$_name-\$pkgver/LICENSE\*",
|
||||||
|
'"$srcdir/$pkgname"/LICENSE* "$srcdir/$_name-$pkgver"/LICENSE*',
|
||||||
|
lines[hit[0]])
|
||||||
|
# install -t with two globs would fail on whichever does not exist, so the
|
||||||
|
# whole line becomes a loop over what is actually there.
|
||||||
|
ind = re.match(r"^[ \t]*", lines[hit[0]]).group(0)
|
||||||
|
lines[hit[0]:hit[0] + 1] = [
|
||||||
|
ind + '# The sources are a git clone under $pkgname when the vendored builder',
|
||||||
|
ind + '# is used, and the release tarball otherwise. Take whichever exists.',
|
||||||
|
ind + 'for _lic in "$srcdir/$pkgname"/LICENSE* "$srcdir/$_name-$pkgver"/LICENSE*; do',
|
||||||
|
ind + ' [ -f "$_lic" ] && install -vDm644 "$_lic" -t "$pkgdir/usr/share/licenses/$pkgname"',
|
||||||
|
ind + 'done',
|
||||||
|
]
|
||||||
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
ZZPY
|
ZZPY
|
||||||
grep -q 'srcdir/\$pkgname/LICENSE\*' PKGBUILD || {
|
grep -q 'Take whichever exists' PKGBUILD || {
|
||||||
echo "python-packaging: the license path was not redirected" >&2; exit 1; }
|
echo "python-packaging: the license loop was not inserted" >&2; exit 1; }
|
||||||
|
# Matched against what is actually written -- the inserted line quotes the
|
||||||
|
# directory, `"$srcdir/$_name-$pkgver"/LICENSE*`, so a pattern expecting the
|
||||||
|
# slash to follow $pkgver directly finds nothing. The first version of this guard
|
||||||
|
# did exactly that and failed on a correct file.
|
||||||
|
grep -q '_name-\$pkgver"/LICENSE\*' PKGBUILD || {
|
||||||
|
echo "python-packaging: the tarball layout was dropped" >&2; exit 1; }
|
||||||
echo "python-packaging: license taken from the bootstrap clone"
|
echo "python-packaging: license taken from the bootstrap clone"
|
||||||
|
|
|
||||||
|
|
@ -79,3 +79,56 @@ grep -qE '^[[:space:]]*mv .*usr/lib/tcl8\.6/sqlite' PKGBUILD && {
|
||||||
echo "sqlite: the hardcoded upstream move survived" >&2; exit 1; }
|
echo "sqlite: the hardcoded upstream move survived" >&2; exit 1; }
|
||||||
grep -q '_tcldir=' PKGBUILD || { echo "sqlite: the tcl dir is not discovered" >&2; exit 1; }
|
grep -q '_tcldir=' PKGBUILD || { echo "sqlite: the tcl dir is not discovered" >&2; exit 1; }
|
||||||
echo "sqlite: upstream tcl move reads the version from the tree"
|
echo "sqlite: upstream tcl move reads the version from the tree"
|
||||||
|
|
||||||
|
# --- tcl 9 keeps its library inside the binary -------------------------------
|
||||||
|
#
|
||||||
|
# The section above discovers whatever tcl directory exists under usr/lib. In
|
||||||
|
# the chroot there was none, and its guard said so:
|
||||||
|
#
|
||||||
|
# sqlite: no tcl dir under usr/lib
|
||||||
|
#
|
||||||
|
# What sqlite had created instead was a directory literally named `zipfs:`:
|
||||||
|
#
|
||||||
|
# <pkgdir>/sqlite/zipfs:/lib/tcl/tcl_library/
|
||||||
|
#
|
||||||
|
# The generated Makefile explains itself:
|
||||||
|
#
|
||||||
|
# # $(TCLLIBDIR) = where to install the tcl plugin. If this is empty, it
|
||||||
|
# TCLLIBDIR = //zipfs:/lib/tcl/tcl_library/sqlite3.53.4
|
||||||
|
#
|
||||||
|
# sqlite asks tcl where its library lives and installs the plugin beside it. In
|
||||||
|
# tcl 8.6 that was a real directory. TCL 9 SHIPS ITS LIBRARY INSIDE THE
|
||||||
|
# EXECUTABLE, in a zipfs mount, so the answer is a path that exists only to tcl
|
||||||
|
# -- and sqlite used it as a filesystem path, creating a directory whose name
|
||||||
|
# contains a colon.
|
||||||
|
#
|
||||||
|
# This is the deferred "libtcl8.6 versus our tcl 9.0" item in its final form: not
|
||||||
|
# a version number to update but a change in what tcl considers a path.
|
||||||
|
#
|
||||||
|
# TCLLIBDIR is set to a real directory, with the version READ from tclsh so the
|
||||||
|
# next tcl release does not need this hook edited again. The section above then
|
||||||
|
# finds it, because usr/lib/tcl<version> is exactly the shape it looks for.
|
||||||
|
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.match(r"^[ \t]*make\b.*\bsqltclsh\b", l)]
|
||||||
|
if not hit:
|
||||||
|
hit = [i for i, l in enumerate(lines) if re.match(r"^[ \t]*make[ \t]*$", l)]
|
||||||
|
assert hit, "sqlite: no make line found in build()"
|
||||||
|
i = hit[0]
|
||||||
|
ind = re.match(r"^[ \t]*", lines[i]).group(0)
|
||||||
|
lines[i:i] = [
|
||||||
|
ind + "# tcl 9 answers with a zipfs path that only tcl can open, and sqlite",
|
||||||
|
ind + "# would install its plugin into a directory named `zipfs:`. Give it a",
|
||||||
|
ind + "# real one, versioned from tclsh rather than written in here.",
|
||||||
|
ind + '_tclver=$(echo "puts [info tclversion]" | tclsh)',
|
||||||
|
ind + '[ -n "$_tclver" ] || { echo "sqlite: tclsh gave no version" >&2; exit 1; }',
|
||||||
|
ind + 'sed -i "s|^TCLLIBDIR = .*|TCLLIBDIR = /usr/lib/tcl${_tclver}/sqlite${pkgver}|" Makefile',
|
||||||
|
ind + 'grep -q "^TCLLIBDIR = /usr/lib/tcl" Makefile || { echo "sqlite: TCLLIBDIR not redirected" >&2; exit 1; }',
|
||||||
|
]
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -q "TCLLIBDIR = /usr/lib/tcl" PKGBUILD || {
|
||||||
|
echo "sqlite: the TCLLIBDIR redirection was not inserted" >&2; exit 1; }
|
||||||
|
echo "sqlite: tcl plugin directed to a real directory (tcl 9 uses zipfs)"
|
||||||
|
|
|
||||||
|
|
@ -286,3 +286,95 @@ io.open("PKGBUILD", "w", encoding="utf-8").write(s)
|
||||||
ZZPY
|
ZZPY
|
||||||
grep -q -- "-Dapparmor=disabled" PKGBUILD || { echo "systemd: apparmor not disabled" >&2; exit 1; }
|
grep -q -- "-Dapparmor=disabled" PKGBUILD || { echo "systemd: apparmor not disabled" >&2; exit 1; }
|
||||||
echo "systemd: AppArmor disabled"
|
echo "systemd: AppArmor disabled"
|
||||||
|
|
||||||
|
# --- no man pages -------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# compilation error: file ../systemd/man/custom-man.xsl line 12 element import
|
||||||
|
#
|
||||||
|
# An XSLT import that cannot resolve: systemd renders its man pages from DocBook,
|
||||||
|
# and the stylesheets its own custom-man.xsl imports are not installed. xsltproc
|
||||||
|
# exists -- our libxslt supplies it -- so this is the FOURTH package to stop on
|
||||||
|
# missing DocBook DATA rather than a missing tool, after pam, shadow and p11-kit.
|
||||||
|
#
|
||||||
|
# systemd has by far the largest man page set of any package here, which is the
|
||||||
|
# strongest argument in the port for shipping docbook-xsl eventually. Not now.
|
||||||
|
set -euo pipefail
|
||||||
|
python3 - <<'ZZPY'
|
||||||
|
import io
|
||||||
|
s = io.open("PKGBUILD", encoding="utf-8").read()
|
||||||
|
old = "-Dman=enabled"
|
||||||
|
assert s.count(old) == 1, "systemd: expected one man option, got %d" % s.count(old)
|
||||||
|
s = s.replace(old, "-Dman=disabled", 1)
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write(s)
|
||||||
|
ZZPY
|
||||||
|
grep -q -- "-Dman=disabled" PKGBUILD || { echo "systemd: man not disabled" >&2; exit 1; }
|
||||||
|
echo "systemd: man pages disabled (DocBook stylesheets absent, not xsltproc)"
|
||||||
|
|
||||||
|
# --- and every man page operation, in every sub-package -----------------------
|
||||||
|
#
|
||||||
|
# -Dman=disabled means NO man page exists, and package() touches them SIXTEEN
|
||||||
|
# times across five sub-package functions. This section was written three times,
|
||||||
|
# each catching more:
|
||||||
|
#
|
||||||
|
# 1st man3 only -> stopped on man8/*nss*
|
||||||
|
# 2nd mv and rm of share/man paths -> stopped on `ln -s ... installkernel.8.gz`
|
||||||
|
# 3rd mv, ln and rm -> stopped on
|
||||||
|
#
|
||||||
|
# install -D -m0644 -t "$pkgdir"/usr/share/man/man1 \
|
||||||
|
# build/man/init.1
|
||||||
|
#
|
||||||
|
# in package_systemd-sysvcompat(), whose SOURCE is under build/ and whose
|
||||||
|
# path contains no "man<digit>" component at all.
|
||||||
|
#
|
||||||
|
# So the pattern is a man path ANYWHERE on the line -- source or destination,
|
||||||
|
# build tree or pkgdir -- and the verbs are mv, ln, rm and install. Treated by
|
||||||
|
# kind:
|
||||||
|
#
|
||||||
|
# mv, ln, install neutralised. Nothing exists to move, link or install.
|
||||||
|
# rm made tolerant with -f. Their intent -- do not ship these --
|
||||||
|
# still holds where the DocBook stack exists, and one of them
|
||||||
|
# also removes a binary that must go.
|
||||||
|
# install -d LEFT ALONE. Creating an empty directory harms nothing, and
|
||||||
|
# other lines in the same functions install real files into
|
||||||
|
# the same trees.
|
||||||
|
#
|
||||||
|
# Written out because three rounds on one package is the cost of guessing the
|
||||||
|
# shape of "all of them" instead of listing them.
|
||||||
|
set -euo pipefail
|
||||||
|
python3 - <<'ZZPY'
|
||||||
|
import io, re
|
||||||
|
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
|
||||||
|
MAN = re.compile(r"(share/man|build/man|\bman[1-8]\b|\bman[1-8]/)")
|
||||||
|
neutral = tolerant = 0
|
||||||
|
for i in range(len(lines) - 1, -1, -1):
|
||||||
|
l = lines[i]
|
||||||
|
if not MAN.search(l):
|
||||||
|
continue
|
||||||
|
# install -d only makes a directory; leave it.
|
||||||
|
if re.match(r"^[ \t]*install +-d", l):
|
||||||
|
continue
|
||||||
|
if re.match(r"^[ \t]*(mv|ln|install) ", l):
|
||||||
|
j = i
|
||||||
|
while lines[j].rstrip().endswith("\\"):
|
||||||
|
j += 1
|
||||||
|
ind = re.match(r"^[ \t]*", l).group(0)
|
||||||
|
lines[i:j + 1] = [ind + ": # no man pages are built: -Dman=disabled above."]
|
||||||
|
neutral += 1
|
||||||
|
elif re.match(r"^[ \t]*rm ", l) and not re.match(r"^[ \t]*rm -[a-z]*f", l):
|
||||||
|
lines[i] = re.sub(r"^([ \t]*)rm ", r"\1rm -f ", l)
|
||||||
|
tolerant += 1
|
||||||
|
assert neutral >= 5, "systemd: expected at least five man operations, got %d" % neutral
|
||||||
|
assert tolerant >= 1, "systemd: no man page removals found"
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
print(" %d neutralised, %d made tolerant" % (neutral, tolerant))
|
||||||
|
ZZPY
|
||||||
|
# Nothing may still act on a man path except `install -d` and a tolerant rm.
|
||||||
|
if grep -nE "^[[:space:]]*(mv|ln|install) .*(share/man|build/man|man[1-8])" PKGBUILD |
|
||||||
|
grep -v "install +-d" | grep -qE "install -d" ; then :; fi
|
||||||
|
grep -nE "^[[:space:]]*(mv|ln) .*(share/man|build/man|man[1-8])" PKGBUILD && {
|
||||||
|
echo "systemd: a man move or link survived" >&2; exit 1; }
|
||||||
|
grep -nE "^[[:space:]]*install +-[^d].*(share/man|build/man)" PKGBUILD && {
|
||||||
|
echo "systemd: a man install survived" >&2; exit 1; }
|
||||||
|
grep -nE "^[[:space:]]*rm [^-].*(share/man|man[1-8])" PKGBUILD && {
|
||||||
|
echo "systemd: an intolerant rm of a man path survived" >&2; exit 1; }
|
||||||
|
echo "systemd: all man page operations handled, in every sub-package"
|
||||||
|
|
|
||||||
66
patches/pkgbuild/tpm2-tss.sh
Executable file
66
patches/pkgbuild/tpm2-tss.sh
Executable file
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# tpm2-tss: no unit tests, because their framework is not here.
|
||||||
|
#
|
||||||
|
# configure: error: Unit test enabled, but cmocka missing or version
|
||||||
|
#
|
||||||
|
# This is the second obstacle in this package, and the first one hid it: before
|
||||||
|
# autoconf-archive existed, configure died on
|
||||||
|
#
|
||||||
|
# configure.ac:139: error: undefined or overquoted macro: AC_MSG_WARN
|
||||||
|
#
|
||||||
|
# which named a macro that exists. An AX_* macro was missing, m4 quoting came
|
||||||
|
# apart, and autoconf blamed the next thing it recognised. With the archive
|
||||||
|
# installed, configure gets far enough to ask for cmocka.
|
||||||
|
#
|
||||||
|
# cmocka is a C unit-test framework, wanted only to build tests that this
|
||||||
|
# bootstrap does not run -- makepkg is invoked with --nocheck for the whole first
|
||||||
|
# pass. --disable-unit is tpm2-tss's own switch; the PKGBUILD passes --enable-unit
|
||||||
|
# in its options array.
|
||||||
|
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.match(r"^[ \t]*--enable-unit[ \t]*$", l)]
|
||||||
|
assert len(hit) == 1, "tpm2-tss: expected one --enable-unit, got %d" % len(hit)
|
||||||
|
lines[hit[0]] = lines[hit[0]].replace("--enable-unit", "--disable-unit")
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -q -- "--disable-unit" PKGBUILD || { echo "tpm2-tss: unit tests not disabled" >&2; exit 1; }
|
||||||
|
grep -qE "^[[:space:]]*--enable-unit[[:space:]]*$" PKGBUILD && {
|
||||||
|
echo "tpm2-tss: --enable-unit survived" >&2; exit 1; }
|
||||||
|
echo "tpm2-tss: unit tests disabled (no cmocka)"
|
||||||
|
|
||||||
|
# --- and no integration tests -------------------------------------------------
|
||||||
|
#
|
||||||
|
# configure: error: Missing required program 'ss': ensure it is installed
|
||||||
|
#
|
||||||
|
# The THIRD obstacle in this package, each hidden by the one before it: a missing
|
||||||
|
# AX_* macro, then cmocka, now `ss`. configure.ac has
|
||||||
|
#
|
||||||
|
# [ERROR_IF_NO_PROG([ss])]
|
||||||
|
#
|
||||||
|
# inside the integration-test branch. `ss` comes from iproute2, and adding
|
||||||
|
# iproute2 was the first idea -- it is in Arch's base group and belongs in this
|
||||||
|
# distribution eventually. It was MEASURED first: iproute2 depends on libbpf,
|
||||||
|
# iptables and linux-atm, none of which are here, and libbpf is the dependency
|
||||||
|
# systemd was already spared for the same reason.
|
||||||
|
#
|
||||||
|
# Three packages to satisfy a test-suite prerequisite, or one flag. The tests are
|
||||||
|
# not run: makepkg gets --nocheck for the whole first pass.
|
||||||
|
python3 - <<'ZZPY'
|
||||||
|
import io, re
|
||||||
|
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
|
||||||
|
en = [i for i, l in enumerate(lines) if re.match(r"^[ \t]*--enable-integration[ \t]*$", l)]
|
||||||
|
if en:
|
||||||
|
lines[en[0]] = lines[en[0]].replace("--enable-integration", "--disable-integration")
|
||||||
|
else:
|
||||||
|
# Put it beside the unit-test switch this hook already set.
|
||||||
|
u = [i for i, l in enumerate(lines) if re.match(r"^[ \t]*--disable-unit[ \t]*$", l)]
|
||||||
|
assert len(u) == 1, "tpm2-tss: expected the --disable-unit line from the section above"
|
||||||
|
ind = re.match(r"^[ \t]*", lines[u[0]]).group(0)
|
||||||
|
lines.insert(u[0] + 1, ind + "--disable-integration")
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -q -- "--disable-integration" PKGBUILD || {
|
||||||
|
echo "tpm2-tss: integration tests not disabled" >&2; exit 1; }
|
||||||
|
echo "tpm2-tss: integration tests disabled (ss would cost three packages)"
|
||||||
|
|
@ -20,3 +20,44 @@ ZZPY
|
||||||
grep -q -- "autogen.sh --no-po4a" PKGBUILD || {
|
grep -q -- "autogen.sh --no-po4a" PKGBUILD || {
|
||||||
echo "xz: --no-po4a was not added" >&2; exit 1; }
|
echo "xz: --no-po4a was not added" >&2; exit 1; }
|
||||||
echo "xz: translated man pages skipped"
|
echo "xz: translated man pages skipped"
|
||||||
|
|
||||||
|
# --- and no doxygen API reference ---------------------------------------------
|
||||||
|
#
|
||||||
|
# Two documentation toolchains in one package: po4a above for the translated man
|
||||||
|
# pages, doxygen for the liblzma API reference.
|
||||||
|
#
|
||||||
|
# ../../../doxygen/update-doxygen: 'doxygen' command not found
|
||||||
|
# make[4]: *** [Makefile:642: ../../../doc/api/index.html] Error 1
|
||||||
|
#
|
||||||
|
# THE FLAG WAS ALREADY THERE, AND LOST. The first version of this section
|
||||||
|
# inserted --disable-doxygen right after ./configure, and config.log recorded what
|
||||||
|
# actually happened:
|
||||||
|
#
|
||||||
|
# $ ./configure --disable-doc --disable-doxygen --prefix=/usr \
|
||||||
|
# --disable-rpath --enable-doxygen --enable-werror
|
||||||
|
#
|
||||||
|
# The PKGBUILD passes --enable-doxygen further along the same line, and autoconf
|
||||||
|
# takes the LAST occurrence. The port had already learned this from the other
|
||||||
|
# side -- the arch-meson wrapper APPENDS --auto-features auto precisely so it
|
||||||
|
# wins -- and this got it backwards.
|
||||||
|
#
|
||||||
|
# The existing option is flipped in place rather than a second one added. One
|
||||||
|
# statement per decision: two contradictory flags on one command line is how the
|
||||||
|
# next reader spends an hour in config.log.
|
||||||
|
#
|
||||||
|
# Note for later: --enable-werror is on that same line. It has not bitten yet.
|
||||||
|
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"--enable-doxygen\b", l)]
|
||||||
|
assert len(hit) == 1, "xz: expected one --enable-doxygen, got %d" % len(hit)
|
||||||
|
lines[hit[0]] = lines[hit[0]].replace("--enable-doxygen", "--disable-doxygen")
|
||||||
|
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
|
||||||
|
ZZPY
|
||||||
|
grep -q -- "--enable-doxygen" PKGBUILD && { echo "xz: --enable-doxygen survived" >&2; exit 1; }
|
||||||
|
grep -q -- "--disable-doxygen" PKGBUILD || { echo "xz: doxygen not disabled" >&2; exit 1; }
|
||||||
|
# One occurrence only: a line carrying both would be decided by position.
|
||||||
|
n=$(grep -c -- "--disable-doxygen" PKGBUILD)
|
||||||
|
[ "$n" = 1 ] || { echo "xz: expected 1 --disable-doxygen, found $n" >&2; exit 1; }
|
||||||
|
echo "xz: doxygen disabled by flipping the flag the PKGBUILD already passes"
|
||||||
|
|
|
||||||
|
|
@ -403,7 +403,11 @@ build_package() {
|
||||||
local hook="$PATCH_DIR/$name.sh"
|
local hook="$PATCH_DIR/$name.sh"
|
||||||
if [ -f "$hook" ]; then
|
if [ -f "$hook" ]; then
|
||||||
git checkout -- PKGBUILD 2>/dev/null || true
|
git checkout -- PKGBUILD 2>/dev/null || true
|
||||||
bash "$hook" || return 1
|
# EL_STAGE tells the hook which stage is asking. Some hooks -- git,
|
||||||
|
# meson, libgcrypt, libarchive -- exist partly or wholly to work around
|
||||||
|
# something about the HOST, and that part must not run in the chroot
|
||||||
|
# where the problem does not exist.
|
||||||
|
EL_STAGE=1 bash "$hook" || return 1
|
||||||
fi
|
fi
|
||||||
rm -f ./*.pkg.tar.*
|
rm -f ./*.pkg.tar.*
|
||||||
# Explicit `|| return 1`. Relying on `set -e` here does NOT work: callers
|
# Explicit `|| return 1`. Relying on `set -e` here does NOT work: callers
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,24 @@ SigLevel = Never
|
||||||
[core]
|
[core]
|
||||||
Server = file://$REPO1
|
Server = file://$REPO1
|
||||||
EOF
|
EOF
|
||||||
|
# NOTHING MAY BE MOUNTED UNDER $ROOT WHEN THIS RUNS.
|
||||||
|
#
|
||||||
|
# `rm -rf` follows a bind mount and deletes what is on the other side. This
|
||||||
|
# function had no such guard, and the cost was the host's /dev: a diagnostic
|
||||||
|
# session left `mount --rbind /dev "$ROOT/dev"` in place, the next run wiped
|
||||||
|
# the rootfs, and the delete went through the mount into the real /dev. Every
|
||||||
|
# device node went -- zero, full, random, urandom, tty, console -- and
|
||||||
|
# /dev/null came back later as a regular file created by a redirection, which
|
||||||
|
# broke every `> /dev/null` on the machine.
|
||||||
|
#
|
||||||
|
# Two guards, because the first one is not enough: unmount, then CHECK, then
|
||||||
|
# refuse. A stale mount is a reason to stop, never a thing to delete through.
|
||||||
|
umount_chroot
|
||||||
|
if findmnt -rno TARGET | grep -qF "$ROOT/"; then
|
||||||
|
printf 'still mounted under %s:\n' "$ROOT" >&2
|
||||||
|
findmnt -rno TARGET | grep -F "$ROOT/" | sed 's/^/ /' >&2
|
||||||
|
die "refusing to rm -rf through a mount"
|
||||||
|
fi
|
||||||
sudo rm -rf "$ROOT" "$CACHE"
|
sudo rm -rf "$ROOT" "$CACHE"
|
||||||
sudo mkdir -p "$ROOT/var/lib/pacman" "$CACHE"
|
sudo mkdir -p "$ROOT/var/lib/pacman" "$CACHE"
|
||||||
# EVERYTHING in stage 1, not a hand-picked core.
|
# EVERYTHING in stage 1, not a hand-picked core.
|
||||||
|
|
@ -221,6 +239,19 @@ EOF
|
||||||
# invocation, so resuming has to be correct rather than approximately
|
# invocation, so resuming has to be correct rather than approximately
|
||||||
# correct.
|
# correct.
|
||||||
#
|
#
|
||||||
|
# --nodeps TWICE, which is not a typo. pacman documents it: `-d` skips
|
||||||
|
# dependency VERSION checks, `-dd` skips dependency checks entirely. With
|
||||||
|
# one, cython could not be installed --
|
||||||
|
#
|
||||||
|
# warning: cannot resolve "python-pygments", a dependency of "cython"
|
||||||
|
# :: unable to satisfy dependency 'python-numpy' required by cython
|
||||||
|
#
|
||||||
|
# -- and the numbers matter: cython is wanted here only as a BUILD tool for
|
||||||
|
# libseccomp's Python binding, and its declared runtime dependencies are
|
||||||
|
# numpy and pygments. numpy brings BLAS and LAPACK. A single -d looked like
|
||||||
|
# it was skipping dependencies and was only skipping their versions, which
|
||||||
|
# nearly bought an entire numerical stack to compile one .pyx file.
|
||||||
|
#
|
||||||
# --nodeps for the same reason the per-package install uses it: a chroot
|
# --nodeps for the same reason the per-package install uses it: a chroot
|
||||||
# halfway through stage 2 is a mixed population, some packages declaring
|
# halfway through stage 2 is a mixed population, some packages declaring
|
||||||
# versioned soname dependencies and some declaring names. -U is fed the
|
# versioned soname dependencies and some declaring names. -U is fed the
|
||||||
|
|
@ -284,7 +315,7 @@ EOF
|
||||||
fi
|
fi
|
||||||
if [ "${#back[@]}" -gt 0 ]; then
|
if [ "${#back[@]}" -gt 0 ]; then
|
||||||
sudo pacman --root "$ROOT" --config "$CONF" --cachedir "$CACHE" \
|
sudo pacman --root "$ROOT" --config "$CONF" --cachedir "$CACHE" \
|
||||||
--noconfirm --nodeps -U "${back[@]}" \
|
--noconfirm --nodeps --nodeps -U "${back[@]}" \
|
||||||
> "$WORK/stage2-restore.txt" 2>&1 \
|
> "$WORK/stage2-restore.txt" 2>&1 \
|
||||||
|| { tail -20 "$WORK/stage2-restore.txt" >&2; die "restoring stage-2 output failed"; }
|
|| { tail -20 "$WORK/stage2-restore.txt" >&2; die "restoring stage-2 output failed"; }
|
||||||
printf ' %s stage-2 package(s) restored\n' "${#back[@]}"
|
printf ' %s stage-2 package(s) restored\n' "${#back[@]}"
|
||||||
|
|
@ -362,6 +393,24 @@ configure_chroot() {
|
||||||
# zz- so it sorts last: the drop-ins are read in glob order, and this has to
|
# zz- so it sorts last: the drop-ins are read in glob order, and this has to
|
||||||
# be the final word. Owned by no package, and remade on every run since
|
# be the final word. Owned by no package, and remade on every run since
|
||||||
# make_rootfs wipes the tree.
|
# make_rootfs wipes the tree.
|
||||||
|
# DownloadUser, which the rebuilt pacman brings with it. nss failed on
|
||||||
|
#
|
||||||
|
# error: problem setting DownloadUser 'alpm' (user does not exist)
|
||||||
|
# ==> ERROR: 'pacman' returned a fatal error (1)
|
||||||
|
#
|
||||||
|
# Arch's pacman.conf drops privileges to `alpm` for downloads, and that user
|
||||||
|
# exists on a real Arch system because the package creates it via sysusers.d
|
||||||
|
# -- which `pacman --root` does not run, the same reason the CA bundle was
|
||||||
|
# never generated. Nothing in this chroot downloads anything (every source is
|
||||||
|
# already in /build, every package installed with -U from a local file), so
|
||||||
|
# the setting has no purpose here and its absence is fatal only because
|
||||||
|
# pacman checks it at startup.
|
||||||
|
if [ -f "$ROOT/etc/pacman.conf" ]; then
|
||||||
|
sudo sed -i 's/^\s*DownloadUser/#DownloadUser/' "$ROOT/etc/pacman.conf"
|
||||||
|
sudo grep -q '^#DownloadUser' "$ROOT/etc/pacman.conf" &&
|
||||||
|
printf ' pacman: DownloadUser disabled (no such user in a chroot)\n'
|
||||||
|
fi
|
||||||
|
|
||||||
sudo install -d -m0755 "$ROOT/etc/makepkg.conf.d"
|
sudo install -d -m0755 "$ROOT/etc/makepkg.conf.d"
|
||||||
sudo tee "$ROOT/etc/makepkg.conf.d/zz-s390x.conf" > /dev/null <<'EOC'
|
sudo tee "$ROOT/etc/makepkg.conf.d/zz-s390x.conf" > /dev/null <<'EOC'
|
||||||
# stage 2: every flag variable, because Arch's are x86_64's and the drop-ins
|
# stage 2: every flag variable, because Arch's are x86_64's and the drop-ins
|
||||||
|
|
@ -485,13 +534,42 @@ mount_chroot() {
|
||||||
# /dev/pts is not optional: without it any build step that opens a pty --
|
# /dev/pts is not optional: without it any build step that opens a pty --
|
||||||
# and gcc's testsuite driver does -- fails in a way that names the pty and
|
# and gcc's testsuite driver does -- fails in a way that names the pty and
|
||||||
# not the missing mount.
|
# not the missing mount.
|
||||||
for m in proc sys dev dev/pts; do
|
for m in proc sys dev; do
|
||||||
sudo mkdir -p "$ROOT/$m"
|
sudo mkdir -p "$ROOT/$m"
|
||||||
done
|
done
|
||||||
mountpoint -q "$ROOT/proc" || sudo mount -t proc proc "$ROOT/proc"
|
mountpoint -q "$ROOT/proc" || sudo mount -t proc proc "$ROOT/proc"
|
||||||
mountpoint -q "$ROOT/sys" || sudo mount -t sysfs sys "$ROOT/sys"
|
mountpoint -q "$ROOT/sys" || sudo mount -t sysfs sys "$ROOT/sys"
|
||||||
mountpoint -q "$ROOT/dev" || sudo mount --bind /dev "$ROOT/dev"
|
# /dev by --rbind, then --make-rslave. Not a plain --bind, and nothing under
|
||||||
mountpoint -q "$ROOT/dev/pts" || sudo mount -t devpts devpts "$ROOT/dev/pts"
|
# it is ever modified.
|
||||||
|
#
|
||||||
|
# A plain --bind does NOT carry submounts, so the chroot saw /dev/shm as the
|
||||||
|
# empty 0755 stub inside devtmpfs rather than the host's tmpfs. That cost
|
||||||
|
# three passes: CPython runs sem_open at configure time, got EACCES, decided
|
||||||
|
# the platform has no POSIX semaphores, and compiled _multiprocessing without
|
||||||
|
# SemLock -- after which every consumer failed with a message blaming the
|
||||||
|
# platform, days after the cause.
|
||||||
|
#
|
||||||
|
# The first fix mounted a separate tmpfs at $ROOT/dev/shm and chmod'ed it.
|
||||||
|
# That was wrong in a way worth recording: $ROOT/dev was a bind of the HOST's
|
||||||
|
# /dev, so writes under it reach the real /dev -- and the host's /dev/null
|
||||||
|
# ended up replaced by a regular file, which broke every redirection on the
|
||||||
|
# machine until it was recreated with mknod.
|
||||||
|
#
|
||||||
|
# --rbind brings the host's /dev/shm along as it is: already a tmpfs, already
|
||||||
|
# drwxrwxrwt. Nothing to create, nothing to chmod, nothing of the host's to
|
||||||
|
# touch. --make-rslave then stops any mount this chroot makes from
|
||||||
|
# propagating back out.
|
||||||
|
mountpoint -q "$ROOT/dev" || {
|
||||||
|
sudo mount --rbind /dev "$ROOT/dev"
|
||||||
|
sudo mount --make-rslave "$ROOT/dev"
|
||||||
|
}
|
||||||
|
# PROVED from inside, as the build user. Every earlier check of this was made
|
||||||
|
# as root and passed while the build kept failing.
|
||||||
|
if ! sudo chroot --userspec="$BUILD_UID:$BUILD_GID" "$ROOT" \
|
||||||
|
/usr/bin/env -i PATH=/usr/bin sh -c \
|
||||||
|
'f=/dev/shm/.el-probe.$$; : > "$f" && rm -f "$f"'; then
|
||||||
|
die "/dev/shm is not writable by the build user; python would build without POSIX semaphores"
|
||||||
|
fi
|
||||||
# Sources and PKGBUILDs, already fetched by stage 1. Bind-mounting them
|
# Sources and PKGBUILDs, already fetched by stage 1. Bind-mounting them
|
||||||
# means the chroot needs no network at all, which is worth having: this
|
# means the chroot needs no network at all, which is worth having: this
|
||||||
# host cannot reach dev.gnupg.org, and a build that silently re-fetches
|
# host cannot reach dev.gnupg.org, and a build that silently re-fetches
|
||||||
|
|
@ -501,7 +579,9 @@ mount_chroot() {
|
||||||
}
|
}
|
||||||
|
|
||||||
umount_chroot() {
|
umount_chroot() {
|
||||||
for m in repo2 build dev/pts dev sys proc; do
|
# -R for dev, because --rbind brought its submounts with it.
|
||||||
|
mountpoint -q "$ROOT/dev" && sudo umount -R -l "$ROOT/dev"
|
||||||
|
for m in repo2 build sys proc; do
|
||||||
mountpoint -q "$ROOT/$m" && sudo umount -l "$ROOT/$m"
|
mountpoint -q "$ROOT/$m" && sudo umount -l "$ROOT/$m"
|
||||||
done
|
done
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -687,7 +767,7 @@ NOTE
|
||||||
# backstop.
|
# backstop.
|
||||||
#
|
#
|
||||||
# libxml2 -- because the xar cycle reformed INSIDE stage 2. libarchive is in
|
# libxml2 -- because the xar cycle reformed INSIDE stage 2. libarchive is in
|
||||||
# STAGE2_SKIP_HOOKS, so stage 2 rebuilt it as Arch does, with xar, linking the
|
# a hook that runs at stage 1 only, so stage 2 rebuilt it as Arch does, with
|
||||||
# libxml2 that happened to be installed at that moment: the stage-1 one, which
|
# libxml2 that happened to be installed at that moment: the stage-1 one, which
|
||||||
# wants the host's libicuuc.so.76. bsdtar then could not start, and bsdtar is
|
# wants the host's libicuuc.so.76. bsdtar then could not start, and bsdtar is
|
||||||
# what makepkg uses to extract sources and write packages -- so 39 of 39
|
# what makepkg uses to extract sources and write packages -- so 39 of 39
|
||||||
|
|
@ -718,7 +798,10 @@ NOTE
|
||||||
STAGE2_FIRST=(texinfo libxml2 binutils pkgconf wget libxslt
|
STAGE2_FIRST=(texinfo libxml2 binutils pkgconf wget libxslt
|
||||||
python-packaging python-pyproject-hooks python-build
|
python-packaging python-pyproject-hooks python-build
|
||||||
python-installer python-setuptools python-wheel
|
python-installer python-setuptools python-wheel
|
||||||
python-setuptools-scm)
|
python-setuptools-scm python-markupsafe python-jinja
|
||||||
|
python-pkgconfig cython python-poetry-core
|
||||||
|
python-vcs-versioning python-fastjsonschema gyp
|
||||||
|
python-psutil)
|
||||||
|
|
||||||
# Packages the chroot needs that can only come from repo2.
|
# Packages the chroot needs that can only come from repo2.
|
||||||
#
|
#
|
||||||
|
|
@ -779,10 +862,11 @@ CHROOT_STAGE2_PKGS=(
|
||||||
python-packaging python-pyproject-hooks python-build
|
python-packaging python-pyproject-hooks python-build
|
||||||
python-installer python-setuptools python-wheel
|
python-installer python-setuptools python-wheel
|
||||||
python-setuptools-scm
|
python-setuptools-scm
|
||||||
|
python-markupsafe python-jinja python-pkgconfig cython
|
||||||
|
python-poetry-core python-vcs-versioning python-fastjsonschema gyp
|
||||||
|
python-psutil
|
||||||
)
|
)
|
||||||
|
|
||||||
STAGE2_SKIP_HOOKS=(libgcrypt git meson libarchive)
|
|
||||||
|
|
||||||
# Packages whose sources must be extracted on the HOST, because the chroot
|
# Packages whose sources must be extracted on the HOST, because the chroot
|
||||||
# cannot extract anything until they are rebuilt.
|
# cannot extract anything until they are rebuilt.
|
||||||
#
|
#
|
||||||
|
|
@ -817,7 +901,17 @@ STAGE2_SKIP_HOOKS=(libgcrypt git meson libarchive)
|
||||||
# Five more packages -- coreutils, sed, grep, findutils, diffutils -- fetch PO
|
# Five more packages -- coreutils, sed, grep, findutils, diffutils -- fetch PO
|
||||||
# files the same way and are unblocked by this one rebuild, which is why wget is
|
# files the same way and are unblocked by this one rebuild, which is why wget is
|
||||||
# also hoisted into STAGE2_FIRST.
|
# also hoisted into STAGE2_FIRST.
|
||||||
STAGE2_HOST_EXTRACT=(libxml2 wget)
|
# nss joins them, for the cheapest of the three reasons: its source is
|
||||||
|
#
|
||||||
|
# hg+https://hg.mozilla.org/projects/nss#tag=NSS_..._RTM
|
||||||
|
#
|
||||||
|
# a MERCURIAL checkout, and the chroot has no hg -- it stopped on
|
||||||
|
# `hg: command not found`. Packaging Mercurial would work and is not needed: the
|
||||||
|
# host has it, and this mechanism exists precisely to let the host do the
|
||||||
|
# fetching. Considered and rejected: mercurial itself is cheap (a Python
|
||||||
|
# application), but it drags python-docutils in for its man pages and would sit
|
||||||
|
# in the chroot forever to serve one package's source URL.
|
||||||
|
STAGE2_HOST_EXTRACT=(libxml2 wget nss)
|
||||||
|
|
||||||
host_extract() {
|
host_extract() {
|
||||||
local n="$1" h
|
local n="$1" h
|
||||||
|
|
@ -825,12 +919,6 @@ host_extract() {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_hook() {
|
|
||||||
local n="$1" h
|
|
||||||
for h in "${STAGE2_SKIP_HOOKS[@]}"; do [ "$n" = "$h" ] && return 0; done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# stage2_build <name> -- rebuild one package inside the chroot and install it.
|
# stage2_build <name> -- rebuild one package inside the chroot and install it.
|
||||||
#
|
#
|
||||||
# The hook is applied on the HOST, not in the chroot: hooks are seds over the
|
# The hook is applied on the HOST, not in the chroot: hooks are seds over the
|
||||||
|
|
@ -839,14 +927,51 @@ skip_hook() {
|
||||||
stage2_build() {
|
stage2_build() {
|
||||||
local name="$1"
|
local name="$1"
|
||||||
local dir="$WORK/pkg/$name"
|
local dir="$WORK/pkg/$name"
|
||||||
[ -d "$dir" ] || { echo " no checkout for $name" >&2; return 1; }
|
# CLONE IF ABSENT. Stage 2 used to refuse:
|
||||||
|
#
|
||||||
|
# no checkout for python-jinja
|
||||||
|
#
|
||||||
|
# It could only rebuild what stage 1 had cloned -- which is wrong for every
|
||||||
|
# package stage 2 builds and stage 1 cannot. libxslt was the first (Ubuntu's
|
||||||
|
# libxml2 is too old to configure it), and the Python set followed (their
|
||||||
|
# package() reads the running python's paths, so the host bakes in
|
||||||
|
# dist-packages). Those are named in CHROOT_STAGE2_PKGS precisely because
|
||||||
|
# only this stage can produce them, and then this stage would not fetch them.
|
||||||
|
#
|
||||||
|
# Pinned to upstream.lock like stage 1's clone, so a package first built here
|
||||||
|
# is as reproducible as one built there.
|
||||||
|
if [ ! -d "$dir/.git" ]; then
|
||||||
|
local url="https://gitlab.archlinux.org/archlinux/packaging/packages/$name.git"
|
||||||
|
local sha=""
|
||||||
|
[ -f "$HERE/upstream.lock" ] &&
|
||||||
|
sha=$(awk -v n="$name" '$1 == n {print $2}' "$HERE/upstream.lock")
|
||||||
|
echo " cloning $name"
|
||||||
|
rm -rf "$dir"
|
||||||
|
GIT_TERMINAL_PROMPT=0 git clone -q --depth 1 "$url" "$dir" || {
|
||||||
|
rm -rf "$dir"; echo " clone failed: $url" >&2; return 1; }
|
||||||
|
if [ -n "$sha" ]; then
|
||||||
|
git -C "$dir" fetch -q --depth 1 origin "$sha" 2>/dev/null &&
|
||||||
|
git -C "$dir" checkout -q --detach FETCH_HEAD 2>/dev/null &&
|
||||||
|
echo " pinned to ${sha:0:9} (upstream.lock)"
|
||||||
|
else
|
||||||
|
echo " NOTE: $name is not in upstream.lock; built against HEAD" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
( cd "$dir" && git checkout -- PKGBUILD 2>/dev/null ) || true
|
( cd "$dir" && git checkout -- PKGBUILD 2>/dev/null ) || true
|
||||||
if [ -f "$PATCH_DIR/$name.sh" ]; then
|
if [ -f "$PATCH_DIR/$name.sh" ]; then
|
||||||
if skip_hook "$name"; then
|
# EL_STAGE=2, and no skip list any more.
|
||||||
echo " hook skipped (stage-1 only)"
|
#
|
||||||
else
|
# There WAS a list -- naming hooks to ignore here. It skipped the
|
||||||
( cd "$dir" && bash "$PATCH_DIR/$name.sh" ) || {
|
# whole FILE, and that broke silently the moment a listed hook grew a
|
||||||
|
# section both stages need: git and meson each kept failing in stage
|
||||||
|
# 2 on exactly what their new sections fix, while the log said
|
||||||
|
# "hook skipped (stage-1 only)" about a hook that was by then two
|
||||||
|
# thirds relevant.
|
||||||
|
#
|
||||||
|
# A list of file names cannot say why. The hooks read EL_STAGE and
|
||||||
|
# decide per section, with the reason written beside the guard.
|
||||||
|
( cd "$dir" && EL_STAGE=2 bash "$PATCH_DIR/$name.sh" ) || {
|
||||||
echo " hook failed" >&2; return 1; }
|
echo " hook failed" >&2; return 1; }
|
||||||
# A hook can leave a PKGBUILD that no longer parses, and makepkg
|
# A hook can leave a PKGBUILD that no longer parses, and makepkg
|
||||||
# reports that far from its cause:
|
# reports that far from its cause:
|
||||||
|
|
@ -863,7 +988,6 @@ stage2_build() {
|
||||||
# calls a valid file broken without it.
|
# calls a valid file broken without it.
|
||||||
( cd "$dir" && bash -O extglob -n PKGBUILD ) || {
|
( cd "$dir" && bash -O extglob -n PKGBUILD ) || {
|
||||||
echo " hook left an unparseable PKGBUILD" >&2; return 1; }
|
echo " hook left an unparseable PKGBUILD" >&2; return 1; }
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
( cd "$dir" && rm -f ./*.pkg.tar.* ) || true
|
( cd "$dir" && rm -f ./*.pkg.tar.* ) || true
|
||||||
|
|
@ -889,6 +1013,32 @@ stage2_build() {
|
||||||
if host_extract "$name"; then
|
if host_extract "$name"; then
|
||||||
echo " extracting on the host (chroot bsdtar not usable yet)"
|
echo " extracting on the host (chroot bsdtar not usable yet)"
|
||||||
( cd "$dir" && LC_ALL=C.UTF-8 makepkg $mkflags -o -C -f ) || return 1
|
( cd "$dir" && LC_ALL=C.UTF-8 makepkg $mkflags -o -C -f ) || return 1
|
||||||
|
# Symlinks that point out of the chroot.
|
||||||
|
#
|
||||||
|
# nss failed with
|
||||||
|
#
|
||||||
|
# /build/nss/PKGBUILD: line 55: ../certdata2pem.py:
|
||||||
|
# No such file or directory
|
||||||
|
#
|
||||||
|
# on a file that was plainly there. makepkg links a PKGBUILD's local
|
||||||
|
# source files into srcdir, and having extracted on the HOST it wrote the
|
||||||
|
# host's absolute path -- $WORK/pkg/nss/certdata2pem.py. Inside the
|
||||||
|
# chroot that path does not exist; only /build does. "No such file or
|
||||||
|
# directory" for an executable is usually its interpreter, which sent the
|
||||||
|
# first guess to the shebang; here it was the script itself, reached
|
||||||
|
# through a link to nowhere.
|
||||||
|
#
|
||||||
|
# Rewritten to the same file as the chroot sees it. Only links under
|
||||||
|
# $WORK/pkg are touched -- a link to anywhere else was not made by this
|
||||||
|
# mechanism and is not ours to redirect.
|
||||||
|
local _l _t _n=0
|
||||||
|
while IFS= read -r _l; do
|
||||||
|
_t=$(readlink "$_l")
|
||||||
|
case "$_t" in
|
||||||
|
"$WORK/pkg"/*) ln -sfn "/build/${_t#"$WORK/pkg/"}" "$_l"; _n=$((_n + 1)) ;;
|
||||||
|
esac
|
||||||
|
done < <(find "$dir/src" -maxdepth 2 -type l 2>/dev/null)
|
||||||
|
[ "$_n" -gt 0 ] && printf ' %s source link(s) repointed at /build\n' "$_n"
|
||||||
# -e: build in the tree already there. -C would wipe it again.
|
# -e: build in the tree already there. -C would wipe it again.
|
||||||
in_chroot "cd /build/$name && makepkg $mkflags -e -f" || return 1
|
in_chroot "cd /build/$name && makepkg $mkflags -e -f" || return 1
|
||||||
else
|
else
|
||||||
|
|
@ -930,8 +1080,31 @@ stage2_build() {
|
||||||
# against the finished repository with --nodeps OFF. The relaxation is one
|
# against the finished repository with --nodeps OFF. The relaxation is one
|
||||||
# install command wide, and the check that would catch its consequences is
|
# install command wide, and the check that would catch its consequences is
|
||||||
# still there.
|
# still there.
|
||||||
|
# Install what this package produced, MINUS the alternatives. zlib-ng
|
||||||
|
# produces zlib-ng-compat, and installing it fails:
|
||||||
|
#
|
||||||
|
# :: zlib-ng-compat-2.3.3-1 and zlib-1:1.3.2-3 are in conflict
|
||||||
|
#
|
||||||
|
# The package is correct and belongs in repo2; it just cannot be installed
|
||||||
|
# beside the zlib this chroot was built with. CHROOT_EXCLUDE already says so
|
||||||
|
# for the populate step, and the same list applies here -- one statement of
|
||||||
|
# which packages cannot coexist, used in both places.
|
||||||
|
local keep=() f2 pn2
|
||||||
|
for f2 in "${produced[@]}"; do
|
||||||
|
pn2=$(bsdtar -xOf "$f2" .PKGINFO 2>/dev/null | sed -n 's/^pkgname = //p')
|
||||||
|
if printf ' %s ' "${CHROOT_EXCLUDE[*]}" | grep -q " ${pn2:-_} "; then
|
||||||
|
printf ' not installed here: %s (alternative to an installed package)\n' "$pn2"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
keep+=("$f2")
|
||||||
|
done
|
||||||
|
if [ "${#keep[@]}" -eq 0 ]; then
|
||||||
|
printf ' nothing to install\n'
|
||||||
|
( cd "$dir" && rm -rf src pkg ) || true
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
sudo pacman --root "$ROOT" --config "$CONF2" --cachedir "$CACHE" \
|
sudo pacman --root "$ROOT" --config "$CONF2" --cachedir "$CACHE" \
|
||||||
--noconfirm --nodeps -U "${produced[@]}" > "$WORK/stage2-inst-$name.txt" 2>&1 || {
|
--noconfirm --nodeps --nodeps -U "${keep[@]}" > "$WORK/stage2-inst-$name.txt" 2>&1 || {
|
||||||
tail -10 "$WORK/stage2-inst-$name.txt" >&2; return 1; }
|
tail -10 "$WORK/stage2-inst-$name.txt" >&2; return 1; }
|
||||||
printf ' installed %s package(s)\n' "${#produced[@]}"
|
printf ' installed %s package(s)\n' "${#produced[@]}"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,90 @@ STAGE1_PACKAGES=(
|
||||||
# same reason: its package() would take Debian's dist-packages from the
|
# same reason: its package() would take Debian's dist-packages from the
|
||||||
# host's python.
|
# host's python.
|
||||||
python-setuptools-scm
|
python-setuptools-scm
|
||||||
|
# systemd generates part of its source with jinja2 templates:
|
||||||
|
#
|
||||||
|
# meson.build:1620:15: ERROR: python3 is missing modules: jinja2
|
||||||
|
#
|
||||||
|
# Not documentation -- the build cannot proceed without it. python-markupsafe
|
||||||
|
# comes with it, as jinja's only dependency.
|
||||||
|
python-markupsafe
|
||||||
|
python-jinja
|
||||||
|
# Three more the chroot asked for by name, each a build tool:
|
||||||
|
#
|
||||||
|
# python-pkgconfig brotli: ERROR Missing dependencies: pkgconfig
|
||||||
|
# -- the python MODULE, not pkg-config the program,
|
||||||
|
# which has been there since the lib64 fix.
|
||||||
|
# cython libseccomp: ERROR Backend subprocess exited when
|
||||||
|
# trying to invoke get_requires_for_build_wheel
|
||||||
|
# -- its python bindings are Cython.
|
||||||
|
# autoconf-archive tpm2-tss: configure.ac:139: error: undefined or
|
||||||
|
# overquoted macro: AC_MSG_WARN
|
||||||
|
# -- an AX_* macro is missing, so autoconf misreads the
|
||||||
|
# line and blames one it does know.
|
||||||
|
python-pkgconfig
|
||||||
|
cython
|
||||||
|
autoconf-archive
|
||||||
|
# publicsuffix-list: DATA, not a tool. libpsl stops on
|
||||||
|
#
|
||||||
|
# make: *** No rule to make target
|
||||||
|
# '/usr/share/publicsuffix/effective_tld_names.dat', needed by ...
|
||||||
|
#
|
||||||
|
# It compiles the Public Suffix List into a lookup table, so the list itself
|
||||||
|
# is an input to the build. First entry in this port whose absence is neither
|
||||||
|
# a program nor a library.
|
||||||
|
publicsuffix-list
|
||||||
|
# python-poetry-core: the fourth Python build backend this port has needed.
|
||||||
|
# python-pkgconfig stops on
|
||||||
|
#
|
||||||
|
# ERROR Backend 'poetry.core.masonry.api' is not available.
|
||||||
|
#
|
||||||
|
# flit_core, setuptools, hatchling and now poetry-core -- each package picks
|
||||||
|
# its own, and each one has to exist before that package can be built.
|
||||||
|
python-poetry-core
|
||||||
|
# python-vcs-versioning: setuptools-scm was split, and its own build now
|
||||||
|
# imports the half that left:
|
||||||
|
#
|
||||||
|
# from vcs_versioning import Configuration
|
||||||
|
# ModuleNotFoundError: No module named 'vcs_versioning'
|
||||||
|
#
|
||||||
|
# The traceback runs through setuptools' build_meta, so the visible error is
|
||||||
|
# "Backend subprocess exited when trying to invoke build_wheel" -- a backend
|
||||||
|
# complaint about a package that split upstream.
|
||||||
|
python-vcs-versioning
|
||||||
|
# python-fastjsonschema: poetry-core validates pyproject.toml against a JSON
|
||||||
|
# schema, so it needs a schema validator to build anything -- including
|
||||||
|
# itself. ModuleNotFoundError: No module named 'fastjsonschema'.
|
||||||
|
python-fastjsonschema
|
||||||
|
# gyp: nss will not configure without it --
|
||||||
|
#
|
||||||
|
# Building NSS requires an installation of gyp: https://gyp.gsrc.io
|
||||||
|
#
|
||||||
|
# Google's build-file generator, which nss uses to produce its ninja files.
|
||||||
|
# A Python program, so it goes with the rest of the Python set.
|
||||||
|
gyp
|
||||||
|
# --- Rust, and what it needs ---------------------------------------------
|
||||||
|
#
|
||||||
|
# NOT optional, and that was measured rather than assumed. ERPLibre's
|
||||||
|
# poetry.lock requires cryptography 46.0.5 with optional = false, plus jiter,
|
||||||
|
# orjson, pydantic-core and rpds-py -- all of which build Rust from source
|
||||||
|
# where no wheel exists, and none exists for s390x. Without Rust,
|
||||||
|
# `pip install cryptography` fails and ERPLibre does not start.
|
||||||
|
#
|
||||||
|
# The bootstrap cycle is not the obstacle it looks like: rust-1.90.0 ships an
|
||||||
|
# official s390x-unknown-linux-gnu tarball (verified, HTTP 200) and the host
|
||||||
|
# already carries rustc 1.85.1. What costs is llvm and clang, which Arch's
|
||||||
|
# rust lists as makedepends.
|
||||||
|
#
|
||||||
|
# libedit and python-psutil are all llvm and clang need beyond what is
|
||||||
|
# already here -- Sphinx is disabled by their hooks, which removes some
|
||||||
|
# fifteen documentation packages from the bill.
|
||||||
|
libedit
|
||||||
|
# python-psutil is a stage-2 package: built on the host it shipped 41
|
||||||
|
# dist-packages paths, like every Python package whose install path comes
|
||||||
|
# from the running interpreter. The ARTEFACT check caught it.
|
||||||
|
python-psutil
|
||||||
|
llvm
|
||||||
|
clang
|
||||||
# libaio: a real closure gap. lvm2 stops on
|
# libaio: a real closure gap. lvm2 stops on
|
||||||
#
|
#
|
||||||
# device/bcache.c:30:10: fatal error: libaio.h: No such file or directory
|
# device/bcache.c:30:10: fatal error: libaio.h: No such file or directory
|
||||||
|
|
|
||||||
|
|
@ -110,11 +110,37 @@ note "2. ARTEFACT -- wrong library directories, which raise no error"
|
||||||
# as its default libdir, which changed where pkgconf installed, which changed
|
# as its default libdir, which changed where pkgconf installed, which changed
|
||||||
# pkgconf's compiled-in search path, which broke every pkg-config lookup in the
|
# pkgconf's compiled-in search path, which broke every pkg-config lookup in the
|
||||||
# chroot. One stray .a file at the bottom of that.
|
# chroot. One stray .a file at the bottom of that.
|
||||||
|
# TWO EXEMPTIONS, each named with its reason, because this check condemned
|
||||||
|
# correct packages on its first run against stage 2's output:
|
||||||
|
#
|
||||||
|
# python 17 x s390x-linux-gnu/ usr/lib/python3.14/config-3.14-s390x-linux-gnu/
|
||||||
|
# usr/lib/python3.14/_sysconfigdata__linux_s390x-linux-gnu.py
|
||||||
|
# filesystem 11 x usr/local/ usr/local/{bin,etc,games,include,...}
|
||||||
|
#
|
||||||
|
# CPython names those two after the build triplet on EVERY platform -- the Arch
|
||||||
|
# x86_64 package ships _sysconfigdata__linux_x86_64-linux-gnu.py -- so the
|
||||||
|
# triplet there is CPython's convention, not Debian's layout leaking in. And
|
||||||
|
# creating /usr/local's skeleton is what the filesystem package is for; the FHS
|
||||||
|
# requires it.
|
||||||
|
#
|
||||||
|
# Exempted by (package, pattern) pair rather than by package, so python is still
|
||||||
|
# checked for lib64 and dist-packages, and filesystem for multiarch. A blanket
|
||||||
|
# exemption is how a real leak gets waved through.
|
||||||
|
_exempt() { # _exempt <pkgfile> <pattern>
|
||||||
|
case "$(basename "$1")|$2" in
|
||||||
|
python-3*'|s390x-linux-gnu/') return 0 ;;
|
||||||
|
filesystem-*'|^usr/local/') return 0 ;;
|
||||||
|
esac
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
n=0
|
n=0
|
||||||
for f in "$REPO"/*.pkg.tar.*; do
|
for f in "$REPO"/*.pkg.tar.*; do
|
||||||
_l=$(bsdtar -tf "$f" 2>/dev/null)
|
_l=$(bsdtar -tf "$f" 2>/dev/null)
|
||||||
c=$(grep -c 's390x-linux-gnu/' <<< "$_l")
|
if ! _exempt "$f" 's390x-linux-gnu/'; then
|
||||||
[ "$c" -gt 0 ] && { bad "$(basename "$f"): $c multiarch paths"; n=$((n + 1)); }
|
c=$(grep -c 's390x-linux-gnu/' <<< "$_l")
|
||||||
|
[ "$c" -gt 0 ] && { bad "$(basename "$f"): $c multiarch paths"; n=$((n + 1)); }
|
||||||
|
fi
|
||||||
c=$(grep -c '^usr/lib64/' <<< "$_l")
|
c=$(grep -c '^usr/lib64/' <<< "$_l")
|
||||||
[ "$c" -gt 0 ] && { bad "$(basename "$f"): $c paths under usr/lib64"; n=$((n + 1)); }
|
[ "$c" -gt 0 ] && { bad "$(basename "$f"): $c paths under usr/lib64"; n=$((n + 1)); }
|
||||||
# dist-packages: Debian's name for site-packages.
|
# dist-packages: Debian's name for site-packages.
|
||||||
|
|
@ -134,8 +160,10 @@ for f in "$REPO"/*.pkg.tar.*; do
|
||||||
[ "$c" -gt 0 ] && { bad "$(basename "$f"): $c paths under dist-packages"; n=$((n + 1)); }
|
[ "$c" -gt 0 ] && { bad "$(basename "$f"): $c paths under dist-packages"; n=$((n + 1)); }
|
||||||
# usr/local: python's posix_local scheme, and anything else that took the
|
# usr/local: python's posix_local scheme, and anything else that took the
|
||||||
# host's idea of where a local install goes.
|
# host's idea of where a local install goes.
|
||||||
c=$(grep -c '^usr/local/' <<< "$_l")
|
if ! _exempt "$f" '^usr/local/'; then
|
||||||
[ "$c" -gt 0 ] && { bad "$(basename "$f"): $c paths under usr/local"; n=$((n + 1)); }
|
c=$(grep -c '^usr/local/' <<< "$_l")
|
||||||
|
[ "$c" -gt 0 ] && { bad "$(basename "$f"): $c paths under usr/local"; n=$((n + 1)); }
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
[ "$n" -eq 0 ] && good "no multiarch, no lib64, no dist-packages, no usr/local"
|
[ "$n" -eq 0 ] && good "no multiarch, no lib64, no dist-packages, no usr/local"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ acl c51beb032d03a50cbd8dae96de23986d21558875 https://gitlab.archlinux.org/archli
|
||||||
attr 13964f8a55dde2d7e407267eb8fbc5ec44bdb585 https://gitlab.archlinux.org/archlinux/packaging/packages/attr.git
|
attr 13964f8a55dde2d7e407267eb8fbc5ec44bdb585 https://gitlab.archlinux.org/archlinux/packaging/packages/attr.git
|
||||||
audit 8db272a0138b530ab71f98763c808a5713f859a4 https://gitlab.archlinux.org/archlinux/packaging/packages/audit.git
|
audit 8db272a0138b530ab71f98763c808a5713f859a4 https://gitlab.archlinux.org/archlinux/packaging/packages/audit.git
|
||||||
autoconf c69f433ef07dc732887e22cd5d5a7501cd944fef https://gitlab.archlinux.org/archlinux/packaging/packages/autoconf.git
|
autoconf c69f433ef07dc732887e22cd5d5a7501cd944fef https://gitlab.archlinux.org/archlinux/packaging/packages/autoconf.git
|
||||||
|
autoconf-archive e5002e5c706204565fb7bb02a923226e8c53131b https://gitlab.archlinux.org/archlinux/packaging/packages/autoconf-archive.git
|
||||||
automake 9697f63e766a66b5da9ccba3fc1a46a798875154 https://gitlab.archlinux.org/archlinux/packaging/packages/automake.git
|
automake 9697f63e766a66b5da9ccba3fc1a46a798875154 https://gitlab.archlinux.org/archlinux/packaging/packages/automake.git
|
||||||
bash ac765bd0cb9b4c27f75c94bc320bf3c8b57304c4 https://gitlab.archlinux.org/archlinux/packaging/packages/bash.git
|
bash ac765bd0cb9b4c27f75c94bc320bf3c8b57304c4 https://gitlab.archlinux.org/archlinux/packaging/packages/bash.git
|
||||||
binutils 5b5ba27ac801a1e7d11819e02a80605ea33434dd https://gitlab.archlinux.org/archlinux/packaging/packages/binutils.git
|
binutils 5b5ba27ac801a1e7d11819e02a80605ea33434dd https://gitlab.archlinux.org/archlinux/packaging/packages/binutils.git
|
||||||
|
|
@ -19,6 +20,7 @@ coreutils f33db1312f616064d4730f92e793d6a761a69e5a https://gitlab.archlinux.org/
|
||||||
cppdap 4a8ba28125a5fcaf5870b47177bbd6b7949ed59d https://gitlab.archlinux.org/archlinux/packaging/packages/cppdap.git
|
cppdap 4a8ba28125a5fcaf5870b47177bbd6b7949ed59d https://gitlab.archlinux.org/archlinux/packaging/packages/cppdap.git
|
||||||
cryptsetup 5fd56afd0d44fad6129716d89103a48d29aa7ef1 https://gitlab.archlinux.org/archlinux/packaging/packages/cryptsetup.git
|
cryptsetup 5fd56afd0d44fad6129716d89103a48d29aa7ef1 https://gitlab.archlinux.org/archlinux/packaging/packages/cryptsetup.git
|
||||||
curl 45e9c1b535b60dd96c05f0c5dc7c07a8ea5947ac https://gitlab.archlinux.org/archlinux/packaging/packages/curl.git
|
curl 45e9c1b535b60dd96c05f0c5dc7c07a8ea5947ac https://gitlab.archlinux.org/archlinux/packaging/packages/curl.git
|
||||||
|
cython 803d705dd505efa0e6c649164c2d609bb91121d9 https://gitlab.archlinux.org/archlinux/packaging/packages/cython.git
|
||||||
db5.3 ef842314637f28c5ae1a5e803ad3799965c0f27e https://gitlab.archlinux.org/archlinux/packaging/packages/db5.3.git
|
db5.3 ef842314637f28c5ae1a5e803ad3799965c0f27e https://gitlab.archlinux.org/archlinux/packaging/packages/db5.3.git
|
||||||
dbus f9960c26b0014b2b0b750425010feacda1b42be8 https://gitlab.archlinux.org/archlinux/packaging/packages/dbus.git
|
dbus f9960c26b0014b2b0b750425010feacda1b42be8 https://gitlab.archlinux.org/archlinux/packaging/packages/dbus.git
|
||||||
diffutils 63d25ebd4b3fc2850529955960643c07221bc233 https://gitlab.archlinux.org/archlinux/packaging/packages/diffutils.git
|
diffutils 63d25ebd4b3fc2850529955960643c07221bc233 https://gitlab.archlinux.org/archlinux/packaging/packages/diffutils.git
|
||||||
|
|
@ -44,6 +46,7 @@ gperf 1ad3213d13d12c8507fab53ec15ec0559be99ffc https://gitlab.archlinux.org/arch
|
||||||
gpgme ce68a023c3cd8e348f87c83666e0a2713cfca47b https://gitlab.archlinux.org/archlinux/packaging/packages/gpgme.git
|
gpgme ce68a023c3cd8e348f87c83666e0a2713cfca47b https://gitlab.archlinux.org/archlinux/packaging/packages/gpgme.git
|
||||||
grep b6557325ffa4abe40e4785823939a42093218acd https://gitlab.archlinux.org/archlinux/packaging/packages/grep.git
|
grep b6557325ffa4abe40e4785823939a42093218acd https://gitlab.archlinux.org/archlinux/packaging/packages/grep.git
|
||||||
groff f84578039481409d2c880adc5bd5dcc4b3285dbb https://gitlab.archlinux.org/archlinux/packaging/packages/groff.git
|
groff f84578039481409d2c880adc5bd5dcc4b3285dbb https://gitlab.archlinux.org/archlinux/packaging/packages/groff.git
|
||||||
|
gyp 602ee84a4028d468431a12684a0bea63c7c37bc2 https://gitlab.archlinux.org/archlinux/packaging/packages/gyp.git
|
||||||
gzip 4b347e7230151d6980db3251f1c65a7b27956c10 https://gitlab.archlinux.org/archlinux/packaging/packages/gzip.git
|
gzip 4b347e7230151d6980db3251f1c65a7b27956c10 https://gitlab.archlinux.org/archlinux/packaging/packages/gzip.git
|
||||||
help2man e2c0cff5c9566eb76b322950e8ad85b6dd15e9cb https://gitlab.archlinux.org/archlinux/packaging/packages/help2man.git
|
help2man e2c0cff5c9566eb76b322950e8ad85b6dd15e9cb https://gitlab.archlinux.org/archlinux/packaging/packages/help2man.git
|
||||||
hicolor-icon-theme 671ceecae2fa1f55a7fef9ead1d4cecfb3010d62 https://gitlab.archlinux.org/archlinux/packaging/packages/hicolor-icon-theme.git
|
hicolor-icon-theme 671ceecae2fa1f55a7fef9ead1d4cecfb3010d62 https://gitlab.archlinux.org/archlinux/packaging/packages/hicolor-icon-theme.git
|
||||||
|
|
@ -125,14 +128,22 @@ perl-timedate 0c4bac17183489ece9370298f45faf8fef586cb4 https://gitlab.archlinux.
|
||||||
pinentry 960a245f317f34fce281246f46d66f0d9b9d5eae https://gitlab.archlinux.org/archlinux/packaging/packages/pinentry.git
|
pinentry 960a245f317f34fce281246f46d66f0d9b9d5eae https://gitlab.archlinux.org/archlinux/packaging/packages/pinentry.git
|
||||||
pkgconf fd5cdd4c656e1d7db763518d55a95f085e80a6f1 https://gitlab.archlinux.org/archlinux/packaging/packages/pkgconf.git
|
pkgconf fd5cdd4c656e1d7db763518d55a95f085e80a6f1 https://gitlab.archlinux.org/archlinux/packaging/packages/pkgconf.git
|
||||||
popt a40d1ac24230f1aab1034cf67423694fcbe3be4c https://gitlab.archlinux.org/archlinux/packaging/packages/popt.git
|
popt a40d1ac24230f1aab1034cf67423694fcbe3be4c https://gitlab.archlinux.org/archlinux/packaging/packages/popt.git
|
||||||
|
publicsuffix-list 3d200a288c966353b3638eb2e0aeabcbf8c2ba88 https://gitlab.archlinux.org/archlinux/packaging/packages/publicsuffix-list.git
|
||||||
python 3254b074f643d1fe29c72516f4ccb5dc4eeba2ac https://gitlab.archlinux.org/archlinux/packaging/packages/python.git
|
python 3254b074f643d1fe29c72516f4ccb5dc4eeba2ac https://gitlab.archlinux.org/archlinux/packaging/packages/python.git
|
||||||
python-build 4d3e49b21fdb9e3648ca89bae4f27cb9a3681b78 https://gitlab.archlinux.org/archlinux/packaging/packages/python-build.git
|
python-build 4d3e49b21fdb9e3648ca89bae4f27cb9a3681b78 https://gitlab.archlinux.org/archlinux/packaging/packages/python-build.git
|
||||||
|
python-fastjsonschema 5160e0bd608c23fb9f8cef53392a47d7f8156747 https://gitlab.archlinux.org/archlinux/packaging/packages/python-fastjsonschema.git
|
||||||
python-flit-core 85b6eb1e07f482cd748b30e6feee8b3d09c443d1 https://gitlab.archlinux.org/archlinux/packaging/packages/python-flit-core.git
|
python-flit-core 85b6eb1e07f482cd748b30e6feee8b3d09c443d1 https://gitlab.archlinux.org/archlinux/packaging/packages/python-flit-core.git
|
||||||
python-installer eac45dc1cca1a3e08192ded2f206b9882ba62559 https://gitlab.archlinux.org/archlinux/packaging/packages/python-installer.git
|
python-installer eac45dc1cca1a3e08192ded2f206b9882ba62559 https://gitlab.archlinux.org/archlinux/packaging/packages/python-installer.git
|
||||||
|
python-jinja d39adbed48638fb2aeec1fa3c14a829e6498ffaf https://gitlab.archlinux.org/archlinux/packaging/packages/python-jinja.git
|
||||||
|
python-markupsafe bf271fe95f2b5706e30bd2278848ed344854b2f8 https://gitlab.archlinux.org/archlinux/packaging/packages/python-markupsafe.git
|
||||||
python-packaging a61fb6392a3d58655c46d6fba09f8edb978bb562 https://gitlab.archlinux.org/archlinux/packaging/packages/python-packaging.git
|
python-packaging a61fb6392a3d58655c46d6fba09f8edb978bb562 https://gitlab.archlinux.org/archlinux/packaging/packages/python-packaging.git
|
||||||
|
python-pkgconfig 3f70bf174624c01d2ac1431430f9f5ddd0aca302 https://gitlab.archlinux.org/archlinux/packaging/packages/python-pkgconfig.git
|
||||||
|
python-poetry-core 89a9484a143dbd201c625e54a46a9902f40b6fe4 https://gitlab.archlinux.org/archlinux/packaging/packages/python-poetry-core.git
|
||||||
python-pyproject-hooks 3f43005e004dd15d6aa2dde0cd3f34886f954b2c https://gitlab.archlinux.org/archlinux/packaging/packages/python-pyproject-hooks.git
|
python-pyproject-hooks 3f43005e004dd15d6aa2dde0cd3f34886f954b2c https://gitlab.archlinux.org/archlinux/packaging/packages/python-pyproject-hooks.git
|
||||||
python-setuptools 8b56f5626b15d6b62ea6653e34e93d3a7e6dbb3e https://gitlab.archlinux.org/archlinux/packaging/packages/python-setuptools.git
|
python-setuptools 8b56f5626b15d6b62ea6653e34e93d3a7e6dbb3e https://gitlab.archlinux.org/archlinux/packaging/packages/python-setuptools.git
|
||||||
|
python-setuptools-scm d58e8364e8bc47b9f01ee459f31212f5c7c00d2e https://gitlab.archlinux.org/archlinux/packaging/packages/python-setuptools-scm.git
|
||||||
python-tqdm e0b7ec5522cc742812ba067fab0c0db660333063 https://gitlab.archlinux.org/archlinux/packaging/packages/python-tqdm.git
|
python-tqdm e0b7ec5522cc742812ba067fab0c0db660333063 https://gitlab.archlinux.org/archlinux/packaging/packages/python-tqdm.git
|
||||||
|
python-vcs-versioning 86fac49f3111ee3a77cc438d134c2d4fd794a556 https://gitlab.archlinux.org/archlinux/packaging/packages/python-vcs-versioning.git
|
||||||
python-wheel fa134ae45e7a48fc26dbb5c7aa4a78c16f9f61dd https://gitlab.archlinux.org/archlinux/packaging/packages/python-wheel.git
|
python-wheel fa134ae45e7a48fc26dbb5c7aa4a78c16f9f61dd https://gitlab.archlinux.org/archlinux/packaging/packages/python-wheel.git
|
||||||
readline 562fc3dc105d29b06ad9bfae84e27387d1d50b6a https://gitlab.archlinux.org/archlinux/packaging/packages/readline.git
|
readline 562fc3dc105d29b06ad9bfae84e27387d1d50b6a https://gitlab.archlinux.org/archlinux/packaging/packages/readline.git
|
||||||
rhash 61d85647a7448bab282f716abed0cdfb7709cdce https://gitlab.archlinux.org/archlinux/packaging/packages/rhash.git
|
rhash 61d85647a7448bab282f716abed0cdfb7709cdce https://gitlab.archlinux.org/archlinux/packaging/packages/rhash.git
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue