From 327ff55665877866a0d2772e7ff33057027aa6bf Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Mon, 24 Aug 2026 01:57:19 -0400 Subject: [PATCH] [ADD] llvm and clang, with Sphinx off, for Rust MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rust is not optional. 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 with HTTP 200, and the host already carries rustc 1.85.1. What costs is llvm and clang. Measured before choosing, the way glib2 and iproute2 were: beyond what this port already has, llvm and clang want libedit, python-psutil, python-sphinx and python-myst-parser. The last two are documentation only, and behind them sit docutils, babel, pygments, snowballstemmer, imagesize, alabaster, the sphinxcontrib family, markdown-it-py and mdit-py-plugins -- some fifteen packages to render HTML for a compiler whose manual nothing here reads. -DLLVM_ENABLE_SPHINX=OFF removes all of it. Their package() ends on `rm -r .../html/{_sources,.buildinfo}`, which Sphinx creates. Seventeenth appearance of that shape, and the FIRST found before the build rather than after -- the procedure written in jsoncpp's hook, applied forwards. python-psutil is a stage-2 package: built on the host it shipped 41 dist-packages paths, and the ARTEFACT check caught it. --- FR --- Rust n'est pas optionnel. Le poetry.lock d'ERPLibre exige cryptography 46.0.5 en optional = false, plus jiter, orjson, pydantic-core et rpds-py, qui tous compilent du Rust depuis les sources là où aucune roue n'existe — et il n'en existe pas pour s390x. Sans Rust, `pip install cryptography` échoue et ERPLibre ne démarre pas. Le cycle d'amorçage n'est pas l'obstacle qu'il paraît : rust-1.90.0 publie une archive officielle s390x-unknown-linux-gnu, vérifiée en HTTP 200, et l'hôte porte déjà rustc 1.85.1. Ce qui coûte, c'est llvm et clang. Mesuré avant de choisir, comme glib2 et iproute2 : au-delà de ce que ce portage a déjà, llvm et clang veulent libedit, python-psutil, python-sphinx et python-myst-parser. Les deux derniers ne servent qu'à la documentation, et derrière eux viennent docutils, babel, pygments, snowballstemmer, imagesize, alabaster, la famille sphinxcontrib, markdown-it-py et mdit-py-plugins — une quinzaine de paquets pour produire du HTML sur un compilateur dont personne ici ne lit le manuel. -DLLVM_ENABLE_SPHINX=OFF supprime tout cela. Leur package() finit sur `rm -r .../html/{_sources,.buildinfo}`, que Sphinx crée. Dix-septième apparition de cette forme, et la PREMIÈRE trouvée avant la construction plutôt qu'après — la procédure inscrite dans le hook de jsoncpp, appliquée à l'endroit. python-psutil est un paquet d'étage 2 : bâti sur l'hôte, il livrait 41 chemins dist-packages, et le test ARTEFACT l'a attrapé. Assisted-by: Claude Opus 5 --- patches/pkgbuild/clang.sh | 39 +++++++++++++++++++++++++++++++++++++++ patches/pkgbuild/llvm.sh | 39 +++++++++++++++++++++++++++++++++++++++ scripts/build-stage2.sh | 4 +++- scripts/packages.sh | 23 +++++++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100755 patches/pkgbuild/clang.sh create mode 100755 patches/pkgbuild/llvm.sh diff --git a/patches/pkgbuild/clang.sh b/patches/pkgbuild/clang.sh new file mode 100755 index 0000000..11c2b17 --- /dev/null +++ b/patches/pkgbuild/clang.sh @@ -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" diff --git a/patches/pkgbuild/llvm.sh b/patches/pkgbuild/llvm.sh new file mode 100755 index 0000000..37b2035 --- /dev/null +++ b/patches/pkgbuild/llvm.sh @@ -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" diff --git a/scripts/build-stage2.sh b/scripts/build-stage2.sh index d78218a..2f540d3 100755 --- a/scripts/build-stage2.sh +++ b/scripts/build-stage2.sh @@ -800,7 +800,8 @@ STAGE2_FIRST=(texinfo libxml2 binutils pkgconf wget libxslt python-installer python-setuptools python-wheel python-setuptools-scm python-markupsafe python-jinja python-pkgconfig cython python-poetry-core - python-vcs-versioning python-fastjsonschema gyp) + python-vcs-versioning python-fastjsonschema gyp + python-psutil) # Packages the chroot needs that can only come from repo2. # @@ -863,6 +864,7 @@ CHROOT_STAGE2_PKGS=( python-setuptools-scm python-markupsafe python-jinja python-pkgconfig cython python-poetry-core python-vcs-versioning python-fastjsonschema gyp + python-psutil ) # Packages whose sources must be extracted on the HOST, because the chroot diff --git a/scripts/packages.sh b/scripts/packages.sh index 14dc154..e191fb2 100644 --- a/scripts/packages.sh +++ b/scripts/packages.sh @@ -340,6 +340,29 @@ STAGE1_PACKAGES=( # 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 # # device/bcache.c:30:10: fatal error: libaio.h: No such file or directory