wasi-libcxx: el directorio VACÍO que hace visible a libc++ (y el guardián que lo prueba)

Segunda muerte del firefox con RLBox, otra vez a los 6 segundos y con el mismo
mensaje engañoso, ya con wasi-libcxx sellado:

    checking the wasm C compiler can find wasi headers... yes
    checking the wasm C++ compiler can find wasi headers...
    fatal error: 'cstring' file not found

El C pasaba todo y sólo fallaba el C++. Y `cstring` ESTABA en el artefacto, en
include/wasm32-wasip1/c++/v1/cstring. No era un fichero que faltara: era un
fichero que clang no buscaba.

CAUSA. El APKBUILD de Alpine hace un `mkdir -p .../include/c++/v1` que parece
ruido de empaquetado y yo descarté al transcribir. Es la SONDA por la que el
driver de clang decide que el sysroot tiene layout de libc++; sin ese directorio
no añade `include/<triple>/c++/v1` a la lista de búsqueda.

MEDIDO, no deducido. Sysroot fusionado (wasi-libc + wasi-libcxx) y la invocación
literal del configure de Mozilla, dentro del lab:

    clang++ -std=gnu++20 --target=wasm32-wasip1 conftest.cpp --sysroot=$S -c

    sin include/c++/v1  ->  fatal error: 'cstring' file not found
    con include/c++/v1  ->  exit 0

Es el reverso exacto de la regla 3 del CLAUDE.md: allá un directorio vacío es un
artefacto mentiroso, acá un directorio vacío es una declaración dirigida al
compilador. Queda documentado en la receta para que nadie lo borre por limpieza.

Y la lección que deja el guardián nuevo: los tests de presencia que tenía la
receta habrían dado esto por bueno, porque "existe" no es "se encuentra". Así
que ahora la receta corre LA MISMA PRUEBA que el configure de firefox, contra un
sysroot fusionado con el de su dep. Si pasa acá no puede fallar allá; y si falla,
falla en el segundo 20 de esta receta —imprimiendo la lista de búsqueda de
clang— y no en el segundo 6 de un build de cuatro horas que además culpa a otro.

Re-hashea: wasi-libcxx b3:1361deae -> b3:838a9557, y con él firefox.
This commit is contained in:
Sergio
2026-09-06 01:46:38 +00:00
parent 553fc1fb7d
commit cddae46205
+47
View File
@@ -163,6 +163,27 @@ for t in wasm32-unknown-wasip1 wasm32-unknown-wasip1-threads; do
done
cd /src
# ⚠ UN DIRECTORIO VACÍO QUE SÍ IMPORTA — y por eso está en su propia línea con su propio párrafo.
#
# El APKBUILD de Alpine hace un `mkdir -p .../include/c++/v1` que parece ruido de empaquetado. NO
# lo es: es la SONDA por la que el driver de clang decide que este sysroot tiene layout de libc++.
# Sin ese directorio, clang NO añade `include/<triple>/c++/v1` a la lista de búsqueda, y los
# headers quedan instalados en el artefacto y a la vez invisibles para el compilador.
#
# MEDIDO, no deducido. Con el sysroot fusionado (wasi-libc + esta receta) y la invocación EXACTA
# que hace el configure de firefox:
#
# clang++ -std=gnu++20 --target=wasm32-wasip1 conftest.cpp --sysroot=$S -c
#
# sin include/c++/v1 -> fatal error: 'cstring' file not found (y `cstring` ESTABA ahí)
# con include/c++/v1 -> exit 0
#
# Es el reverso exacto de la regla 3 del CLAUDE.md: allá un directorio vacío es un artefacto
# mentiroso; acá un directorio vacío es una declaración dirigida al compilador. Borrarlo por
# "limpieza" reintroduce un fallo que aparece a 6 segundos de un build de 4 horas, culpando a los
# headers de WASI, que están perfectos.
mkdir -p "$S/include/c++/v1"
# GUARDIÁN. Se exige exactamente lo que el configure de firefox no encontró: el header de C++ que
# disparó todo esto y la librería que lo respalda, PARA LOS DOS TRIPLES. Un `cmake --install` que no
# instala nada sale con 0, y un sysroot con headers y sin `.a` pasa por bueno y revienta dentro del
@@ -181,4 +202,30 @@ for t in wasm32-wasip1 wasm32-wasip1-threads; do
done
echo "guardián: $t ok — libc++.a $(stat -c%s "$A") bytes, libc++abi.a $(stat -c%s "$B") bytes"
done
# ── GUARDIÁN DE VERDAD: CORRER LA MISMA PRUEBA QUE HACE EL CONFIGURE DE FIREFOX ───────────────
# Los tests de arriba comprueban que los ficheros existen, y "existe" no es "se encuentra": el
# fallo que motivó esta receta era exactamente eso —`cstring` presente en el disco e invisible
# para clang—, así que un guardián de presencia lo habría dado por bueno.
#
# Se reproduce la invocación literal del configure de Mozilla contra un sysroot FUSIONADO (el de
# la dep `wasi-libc` más lo que acaba de instalar esta receta), que es la forma en que se va a usar
# de verdad. Si esto pasa acá, no puede fallar allá; y si falla, falla en el segundo 20 de ESTA
# receta y no en el segundo 6 de un build de cuatro horas que además culpa a otro.
P=/tmp/sysroot-fusionado
mkdir -p "$P"
cp -a /usr/share/wasi-sysroot/. "$P"/ # lo que aporta la dep wasi-libc
cp -a "$S"/. "$P"/ # lo que aporta esta receta
echo '#include <cstring>' > /tmp/probe.cpp
for t in wasm32-wasip1 wasm32-wasip1-threads; do
clang++ -std=gnu++20 --target=$t /tmp/probe.cpp --sysroot="$P" -c -o /tmp/probe.o || {
echo "!! libc++ instalada pero INVISIBLE para clang en $t." >&2
echo " Los headers están en el artefacto y el compilador no los encuentra." >&2
echo " Sospechá del directorio-sonda include/c++/v1 antes que de la instalación." >&2
clang++ -std=gnu++20 --target=$t /tmp/probe.cpp --sysroot="$P" -c -o /tmp/probe.o -v 2>&1 \
| sed -n '/search starts/,/End of search/p' >&2
exit 1
}
echo "guardián: clang++ encuentra <cstring> para $t (la prueba exacta del configure de firefox)"
done
'''