cadena wasm completa: wasi-libc y wasi-sdk sellan (SDD 26, unidad 3.b)
Los cuatro eslabones que enciende RLBox en firefox, sellados de punta a punta:
wasi-libc-headers b3:54c6e96d (andamio, rompe el ciclo del bootstrap)
wasi-compiler-rt b3:a3fe63d1 (libclang_rt.builtins-wasm32.a)
wasi-libc b3:8e50b145 (libc.a 970.734 bytes, 32 archivos .a)
wasi-sdk b3:c8a587fa (el .cfg que hace el sysroot invisible)
Los dos primeros ya estaban construidos; los dos últimos costaron dos fallos, y
ninguno de los dos era de la receta:
1. `check-symbols` moría por SESGO DE CLANG, no por un artefacto malo. El lab
trae clang 22.1.8 y este commit de wasi-libc (2025-06-26) congeló su snapshot
de macros predefinidos contra un clang anterior, así que el diff completo era
UNA línea: `+#define __wasip1__ 1`. La mitad que importa —los símbolos
definidos e indefinidos de la libc recién construida— coincidía byte a byte.
Por eso se RECONCILIA `expected/*/predefined-macros.txt` en vez de saltar el
chequeo con `make no-check-symbols`, que era la salida fácil: ese target
existe y se lleva por delante también la comparación de símbolos, que es la
que vale. Así cualquier OTRA deriva sigue matando el build.
2. `make TARGET_TRIPLE=NOBUILD ... install` NO es un no-op. La regla `install`
depende de `finish`, que depende de `libc`, así que make no lee el triple
inexistente como «no construyas» sino como «construí para el triple NOBUILD»
y muere en `build/NOBUILD/.../crt1-command.o` con `invalid thread model
'single'` — un error que nombra un fichero que nadie pidió. Se copia
`sysroot/{lib,share,include}` a mano, que es literalmente lo que hace la
regla de upstream (`SYSROOT ?= $(CURDIR)/sysroot`).
Cada receta lleva su guardián de contenido, porque acá el modo de fallo caro no
es el ausente sino el vacío: un sysroot con headers y sin libc.a pasa por bueno
y revienta dentro del build de firefox, horas después y sin nombrar a nadie de
esta cadena. Verificado en verde: los builtins son objetos wasm de verdad
(magic 0061736d, no x86_64 nativos) y el .cfg de wasi-sdk apunta a un sysroot
que existe.
El segundo fallo lo diagnosticamos entre dos sesiones: hammer-f8 aportó el
`invalid thread model 'single'` que explicaba la línea que yo veía.
Queda para la próxima unidad el flip de recipes/firefox.toml:
--without-wasm-sandboxed-libraries -> --with-wasi-sysroot, que es un rebuild
largo y su propia unidad de trabajo.
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
# wasi-compiler-rt — los builtins de compiler-rt compilados a wasm32.
|
||||
#
|
||||
# QUÉ ES: la runtime del compilador para WebAssembly (`libclang_rt.builtins-wasm32.a`). Sin esto no
|
||||
# se puede enlazar NADA a wasm, y por eso es el primer eslabón real del sandbox RLBox de firefox
|
||||
# (SDD 26 §3.bis, lectura 1: RLBox apagado es una desventaja de SEGURIDAD — es la jaula wasm
|
||||
# alrededor de los parsers de fuentes y medios, o sea justo el código que come entrada no confiable).
|
||||
#
|
||||
# NO CONSTRUYE LLVM. El lab ya trae LLVM 22.1.8 CON el backend de WebAssembly compilado dentro
|
||||
# (comprobado: `wasm32`, `wasm64` y las descripciones "WebAssembly 32-bit/64-bit" están en
|
||||
# `libLLVM.so.22.1`). De acá sale sólo la runtime, que son ~100 ficheros C: minutos, no horas.
|
||||
#
|
||||
# ⚠ LA VERSIÓN TIENE QUE SEGUIR A LA DEL LAB. Los builtins son un contrato con el clang que los va a
|
||||
# usar: Alpine lo escribe como `wasi-compiler-rt~$_llvmver` en las makedepends de firefox. Acá el
|
||||
# tarball es 22.1.8 y el lab tiene llvm22 22.1.8-r1 — MISMA versión upstream. Si el lab sube de
|
||||
# LLVM, esta receta sube con él. Y no queda al aire: `clang` y `llvm` son prefijos de
|
||||
# `TOOLCHAIN_PREFIXES` (hammer-core/src/lab.rs), así que un bump del lab MUEVE la huella y re-hashea
|
||||
# esto solo. La alineación es un invariante vigilado, no una nota al pie.
|
||||
#
|
||||
# DÓNDE ATERRIZA: `/usr/lib/llvm22/lib/clang/22/lib/wasi/`, que es el resource dir donde clang
|
||||
# busca los builtins sin que nadie le pase un flag. En el lab ese `lib/` NO existe (sólo hay
|
||||
# `include/`), y las deps se apilan como capas overlay BAJO el rootfs ⇒ esta receta lo CREA sin
|
||||
# pisar nada del lab.
|
||||
#
|
||||
# Verificado: el sha512 del tarball coincide byte a byte con el del APKBUILD de Alpine.
|
||||
name = "wasi-compiler-rt"
|
||||
version = "22.1.8"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
|
||||
[source]
|
||||
tarball = "https://github.com/llvm/llvm-project/releases/download/llvmorg-22.1.8/llvm-project-22.1.8.src.tar.xz"
|
||||
sha256 = "922f1817a0df7b1489272d18134ee0087a8b068828f87ac63b9861b1a9965888"
|
||||
|
||||
[build]
|
||||
compiler = "clang"
|
||||
|
||||
[deps]
|
||||
# `python3`: el CMakeLists de compiler-rt busca Python3 y, si no lo encuentra, cae a un
|
||||
# `find_package(Python2 ... REQUIRED)` que MUERE. El error dice "Could NOT find Python2" y lo
|
||||
# que falta es python3 — el mensaje nombra el fallback, no la causa.
|
||||
build = ["cmake", "samurai", "python3", "wasi-libc-headers"]
|
||||
|
||||
[build.phases]
|
||||
configure = '''
|
||||
set -e
|
||||
|
||||
# El toolchain file de wasi-sdk, ESCRITO ACÁ EN VEZ DE TRAÍDO. Upstream son 38 líneas repartidas en
|
||||
# dos ficheros del tarball de wasi-sdk (`wasi-sdk.cmake` + `cmake/Platform/WASI.cmake`, y el segundo
|
||||
# es literalmente `set(WASI 1)`). Traerlos costaría una fuente de red y una receta enteras para 38
|
||||
# líneas de declaraciones puras — peor trato. Se transcriben de wasi-sdk-27, que es el que Alpine
|
||||
# pinea para esta misma versión de compiler-rt.
|
||||
mkdir -p cmake/Platform
|
||||
echo 'set(WASI 1)' > cmake/Platform/WASI.cmake
|
||||
cat > wasi-sdk.cmake <<'EOF'
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
set(CMAKE_SYSTEM_NAME WASI)
|
||||
set(CMAKE_SYSTEM_VERSION 1)
|
||||
set(CMAKE_SYSTEM_PROCESSOR wasm32)
|
||||
set(triple wasm32-wasi)
|
||||
set(CMAKE_C_COMPILER ${WASI_SDK_PREFIX}/bin/clang)
|
||||
set(CMAKE_CXX_COMPILER ${WASI_SDK_PREFIX}/bin/clang++)
|
||||
set(CMAKE_ASM_COMPILER ${WASI_SDK_PREFIX}/bin/clang)
|
||||
set(CMAKE_AR ${WASI_SDK_PREFIX}/bin/llvm-ar)
|
||||
set(CMAKE_RANLIB ${WASI_SDK_PREFIX}/bin/llvm-ranlib)
|
||||
set(CMAKE_C_COMPILER_TARGET ${triple})
|
||||
set(CMAKE_CXX_COMPILER_TARGET ${triple})
|
||||
set(CMAKE_ASM_COMPILER_TARGET ${triple})
|
||||
# No buscar EJECUTABLES en el sysroot (los de correr durante el build son del host); el resto,
|
||||
# SÓLO en el sysroot, para que no se cuele una lib nativa x86_64 en un enlace a wasm.
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
EOF
|
||||
|
||||
# CFLAGS/LDFLAGS del entorno se limpian a propósito: cualquier flag pensado para el x86_64 nativo
|
||||
# (un `-static`, un `-march`) es veneno en un enlace a wasm32 y el error que produce no se parece
|
||||
# en nada a la causa.
|
||||
unset CFLAGS CXXFLAGS LDFLAGS
|
||||
|
||||
cmake -B build -G Ninja -S compiler-rt -Wno-dev \
|
||||
-DCMAKE_BUILD_TYPE=MinSizeRel \
|
||||
-DCMAKE_MODULE_PATH=/src/cmake \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/src/wasi-sdk.cmake \
|
||||
-DCMAKE_C_COMPILER_WORKS=ON \
|
||||
-DCMAKE_CXX_COMPILER_WORKS=ON \
|
||||
-DCOMPILER_RT_BAREMETAL_BUILD=ON \
|
||||
-DCOMPILER_RT_INCLUDE_TESTS=OFF \
|
||||
-DCOMPILER_RT_HAS_FPIC_FLAG=OFF \
|
||||
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
|
||||
-DCOMPILER_RT_OS_DIR=wasi \
|
||||
-DCMAKE_AR=/usr/bin/llvm-ar \
|
||||
-DCMAKE_RANLIB=/usr/bin/llvm-ranlib \
|
||||
-DWASI_SDK_PREFIX=/usr \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr/lib/llvm22/lib/clang/22/ \
|
||||
-DCMAKE_SYSROOT=/usr/share/wasi-sysroot-bootstrap
|
||||
'''
|
||||
compile = 'cmake --build build'
|
||||
install = '''
|
||||
set -e
|
||||
DESTDIR=/out cmake --install build
|
||||
|
||||
RES=/out/usr/lib/llvm22/lib/clang/22
|
||||
|
||||
# El `include/` del resource dir pertenece al LAB (son los headers de clang). Instalarlo desde acá
|
||||
# lo taparía con una copia del tarball: misma trampa que las deps `clang18`/`llvm18` que había que
|
||||
# quitar de firefox. Fuera.
|
||||
rm -rf "$RES/include"
|
||||
|
||||
# Los alias que espera clang según cómo se nombre el target. `wasm32-wasi` se renombró a
|
||||
# `wasm32-wasip1` en LLVM 22.1 (lo dice el propio configure de Mozilla), así que el mismo `.a`
|
||||
# tiene que responder a los dos nombres o el enlace falla por un alias que no existe.
|
||||
for p in 1 2; do
|
||||
ln -s ./wasi "$RES/lib/wasm32-wasip$p"
|
||||
ln -s ./wasi "$RES/lib/wasm32-unknown-wasip$p"
|
||||
done
|
||||
ln -s ./libclang_rt.builtins-wasm32.a "$RES/lib/wasi/libclang_rt.builtins.a"
|
||||
|
||||
# GUARDIÁN. Un `cmake --install` que no instala nada sale con 0 y deja el árbol vacío — que en el
|
||||
# store es un cache-hit envenenado, no un fallo. Se exige el fichero Y que sea un archivo wasm de
|
||||
# verdad, no un `.a` vacío ni uno de objetos x86_64.
|
||||
A="$RES/lib/wasi/libclang_rt.builtins-wasm32.a"
|
||||
test -s "$A" || { echo "!! no se instaló $A" >&2; find /out -name 'libclang_rt*' >&2; exit 1; }
|
||||
N=$(llvm-nm --print-file-name "$A" 2>/dev/null | wc -l)
|
||||
test "$N" -gt 0 || { echo "!! $A no tiene símbolos: archivo vacío" >&2; exit 1; }
|
||||
|
||||
# Que los miembros sean WASM y no x86_64 nativos. Es LA comprobación que importa: si el sysroot o el
|
||||
# triple se configuran mal, cmake compila igual pero produce objetos nativos, el `.a` queda lleno y
|
||||
# con símbolos, y el fallo recién aparece al enlazar firefox — lejos y sin nombrar a esta receta.
|
||||
# Se mira el número mágico del objeto (`\0asm`), no el nombre del fichero: la primera versión de
|
||||
# este guardián exigía que el miembro terminara en `.o` y lo rechazó estando BIEN construido,
|
||||
# porque compiler-rt los nombra de otro modo. Una convención de nombre no es una propiedad.
|
||||
M=$(llvm-ar t "$A" | head -1)
|
||||
mkdir -p /tmp/guardian && (cd /tmp/guardian && llvm-ar x "$A" "$M")
|
||||
MAGIC=$(od -An -tx1 -N4 "/tmp/guardian/$M" | tr -d ' \n')
|
||||
test "$MAGIC" = "0061736d" || {
|
||||
echo "!! los objetos de $A NO son wasm (magic=$MAGIC, esperaba 0061736d)" >&2
|
||||
echo " primer miembro: $M" >&2
|
||||
exit 1
|
||||
}
|
||||
echo "guardián: builtins wasm32 instalados ($(llvm-ar t "$A" | wc -l) objetos, magic wasm ok, $(stat -c%s "$A") bytes)"
|
||||
'''
|
||||
@@ -0,0 +1,59 @@
|
||||
# wasi-libc-headers — SÓLO los headers de wasi-libc, para ROMPER el ciclo del bootstrap wasm.
|
||||
#
|
||||
# EL CICLO: `wasi-libc` necesita `libclang_rt.builtins-wasm32.a` para enlazar, y
|
||||
# `wasi-compiler-rt` necesita los headers de wasi-libc para compilar. Ninguno de los dos puede ir
|
||||
# primero. Se rompe por acá: los headers NO necesitan compilar nada —el target
|
||||
# `copy-include-headers.stamp` sólo copia ficheros— así que esta receta sale sin builtins y le da a
|
||||
# `wasi-compiler-rt` el `CMAKE_SYSROOT` que le falta.
|
||||
#
|
||||
# ⚠ POR QUÉ ESTE COMMIT Y NO EL DE `wasi-libc`: acá se pinea `ac020b86` (viejo) y en `wasi-libc`
|
||||
# `3f7eb4c7` (nuevo), igual que Alpine. NO es un descuido. El árbol instala los headers en
|
||||
# `sysroot/include/$(TARGET_TRIPLE)`, y el TRIPLE POR DEFECTO cambió entre los dos commits:
|
||||
# `wasm32-wasi` en el viejo, `wasm32-wasip1` en el nuevo. El toolchain file de wasi-sdk que usa
|
||||
# `wasi-compiler-rt` fija `wasm32-wasi`, así que con el árbol nuevo clang buscaría
|
||||
# `include/wasm32-wasi` y encontraría `include/wasm32-wasip1` — sysroot vacío y build muerto.
|
||||
# El artefacto FINAL que consume firefox es el de `wasi-libc` (wasip1, el triple que clang 22.1
|
||||
# usa de verdad); éste es andamio de bootstrap y muere acá.
|
||||
#
|
||||
# Verificado: el sha512 de este tarball coincide byte a byte con el que publica Alpine en su
|
||||
# APKBUILD de `wasi-compiler-rt` — o sea que la descarga está contrastada contra una fuente
|
||||
# independiente, no sólo consigo misma.
|
||||
name = "wasi-libc-headers"
|
||||
version = "0.20250521"
|
||||
license = "Apache-2.0 WITH LLVM-exception AND MIT AND CC0-1.0 AND BSD-2-Clause"
|
||||
|
||||
[source]
|
||||
# Tarball `/archive/<commit>` de GitHub: se genera al vuelo, pero va pineado por COMMIT (no por tag
|
||||
# móvil) y su sha256 está fijado acá, así que un cambio de bytes falla ruidosamente en el fetch.
|
||||
# El repo trae un `.gitmodules` con `tools/wasi-headers/WASI`, que en el tarball llega VACÍO: es el
|
||||
# generador de headers desde la espec WASI, y su salida ya está commiteada en el árbol. El Makefile
|
||||
# no lo toca. No hace falta modo git.
|
||||
tarball = "https://github.com/WebAssembly/wasi-libc/archive/ac020b86fd44bafe60aa4fa12f407d16e3731329.tar.gz"
|
||||
sha256 = "d44bd7fa456aa42c1494767e5ffa00cdbab182d8497a577592a6562629f6f49e"
|
||||
|
||||
[build]
|
||||
compiler = "clang"
|
||||
|
||||
[deps]
|
||||
build = ["make"]
|
||||
|
||||
[build.phases]
|
||||
configure = "true"
|
||||
# `install-include-headers.sh` necesita un shell POSIX y `find`; los dos están en el lab.
|
||||
compile = 'make build/wasm32-wasi/copy-include-headers.stamp'
|
||||
install = '''
|
||||
set -e
|
||||
mkdir -p /out/usr/share/wasi-sysroot-bootstrap
|
||||
cp -a sysroot/. /out/usr/share/wasi-sysroot-bootstrap/
|
||||
|
||||
# GUARDIÁN. El target de la stamp es un `touch`: si el script de copia fallara sin salir con
|
||||
# error, la stamp existiría igual y esta receta sellaría un sysroot VACÍO — que es un cache-hit
|
||||
# envenenado, no un fallo (regla 3 del CLAUDE.md). Se exige un header concreto, no el directorio.
|
||||
test -f /out/usr/share/wasi-sysroot-bootstrap/include/wasm32-wasi/stdlib.h || {
|
||||
echo "!! el sysroot de bootstrap no tiene include/wasm32-wasi/stdlib.h" >&2
|
||||
echo " (¿cambió TARGET_TRIPLE por defecto en este commit de wasi-libc?)" >&2
|
||||
ls -R /out/usr/share/wasi-sysroot-bootstrap 2>/dev/null | head -30 >&2
|
||||
exit 1
|
||||
}
|
||||
echo "guardián: headers wasm32-wasi presentes ($(find /out/usr/share/wasi-sysroot-bootstrap -name '*.h' | wc -l) .h)"
|
||||
'''
|
||||
@@ -0,0 +1,118 @@
|
||||
# wasi-libc — la libc de WebAssembly. Es el sysroot que firefox usa para compilar sus librerías
|
||||
# enjauladas en wasm (RLBox): los parsers de fuentes y medios —graphite, ogg, expat, woff2—, o sea
|
||||
# el código que come entrada no confiable de la red.
|
||||
#
|
||||
# ES EL ESLABÓN FINAL de la cadena wasm, y el que firefox consume de verdad:
|
||||
# wasi-libc-headers (andamio, triple viejo) → wasi-compiler-rt (los builtins) → ESTE
|
||||
#
|
||||
# ⚠ COMMIT DISTINTO AL DE `wasi-libc-headers`, a propósito. Acá va el NUEVO (`3f7eb4c7`), cuyo
|
||||
# triple por defecto es `wasm32-wasip1`. Ése es el que importa: en LLVM 22.1 el target `wasm32-wasi`
|
||||
# se renombró a `wasm32-wasip1` y el propio `toolchain.configure` de Mozilla lo contempla
|
||||
# explícitamente, así que el clang 22.1 del lab va a pedir el sysroot con ESE nombre. El commit
|
||||
# viejo existe sólo para romper el ciclo de bootstrap; ver `wasi-libc-headers.toml`.
|
||||
#
|
||||
# Verificado: el sha512 de este tarball coincide byte a byte con el del APKBUILD de Alpine.
|
||||
name = "wasi-libc"
|
||||
version = "27.20250626"
|
||||
license = "Apache-2.0 WITH LLVM-exception AND Apache-2.0 AND MIT AND CC0-1.0 AND BSD-2-Clause"
|
||||
|
||||
[source]
|
||||
tarball = "https://github.com/WebAssembly/wasi-libc/archive/3f7eb4c7d6ede4dde3c4bffa6ed14e8d656fe93f.tar.gz"
|
||||
sha256 = "6bb86e09dc5ed43260e81176537d702568689cf4203b8beb1f505609c4139ca5"
|
||||
|
||||
[build]
|
||||
compiler = "clang"
|
||||
|
||||
[deps]
|
||||
build = ["make", "wasi-compiler-rt"]
|
||||
|
||||
[build.phases]
|
||||
configure = "true"
|
||||
compile = '''
|
||||
set -e
|
||||
|
||||
# ⚠ `BUILTINS_LIB` NO ES OPCIONAL ACÁ, y no por gusto: si no se define, el Makefile se BAJA una
|
||||
# copia conocida desde la CI de wasi-sdk con `curl` (línea ~610 del Makefile upstream). Dentro del
|
||||
# sandbox hermético eso no tiene red, así que el build moriría; y si la tuviera sería peor, porque
|
||||
# estaríamos sellando un binario ajeno sin hash. Se le pasa el que construyó `wasi-compiler-rt`.
|
||||
#
|
||||
# Ruta ABSOLUTA, no la relativa que usa el APKBUILD de Alpine: el Makefile la consume como
|
||||
# prerequisito de una regla (`$(BUILTINS_LIB_PATH): $(BUILTINS_LIB)`) y la resuelve contra su propio
|
||||
# CURDIR, que acá es `/src` y no `/`.
|
||||
BUILTINS=/usr/lib/llvm22/lib/clang/22/lib/wasi/libclang_rt.builtins-wasm32.a
|
||||
test -f "$BUILTINS" || { echo "!! falta $BUILTINS (¿no llegó la dep wasi-compiler-rt?)" >&2; exit 1; }
|
||||
|
||||
unset CFLAGS CXXFLAGS LDFLAGS
|
||||
|
||||
# ⚠ `check-symbols` CONTRA UN CLANG MÁS NUEVO QUE EL SNAPSHOT DEL ÁRBOL.
|
||||
#
|
||||
# El target `check-symbols` del Makefile hace DOS cosas: compara los símbolos definidos/indefinidos
|
||||
# de la libc recién construida contra `expected/`, y compara la lista de macros predefinidos del
|
||||
# clang que la compiló contra otro snapshot del mismo directorio. Lo primero es una comprobación
|
||||
# real del artefacto; lo segundo es un detector de deriva de toolchain.
|
||||
#
|
||||
# El lab trae clang 22.1.8 y este commit de wasi-libc (2025-06-26) fue congelado contra un clang
|
||||
# anterior, así que el build muere con UNA sola línea de diferencia:
|
||||
#
|
||||
# +#define __wasip1__ 1
|
||||
#
|
||||
# La mitad que importa PASÓ: `defined-symbols.txt` y `undefined-symbols.txt` coinciden byte a byte;
|
||||
# el diff completo son esas 3.196 líneas iguales y ese macro de más. O sea: la libc construida es la
|
||||
# esperada y lo que cambió es que el compilador define un macro nuevo.
|
||||
#
|
||||
# Por eso se RECONCILIA el snapshot en vez de saltar el chequeo con `make no-check-symbols`, que era
|
||||
# la salida fácil: ese target existe y se lleva por delante también la comparación de símbolos, que
|
||||
# es justamente la que vale. Así el chequeo sigue vivo y CUALQUIER OTRA deriva —un símbolo que
|
||||
# desaparece, otro macro nuevo— sigue matando el build.
|
||||
#
|
||||
# Se exige que la inserción ocurra: si upstream renombra el ancla, este bloque no puede quedarse
|
||||
# callado dejando el mismo fallo para más adelante.
|
||||
for T in wasm32-wasip1 wasm32-wasip1-threads; do
|
||||
F="expected/$T/predefined-macros.txt"
|
||||
grep -q '^#define __wasip1__ 1$' "$F" && continue
|
||||
sed -i 's/^#define __wasm 1$/#define __wasip1__ 1\n#define __wasm 1/' "$F"
|
||||
grep -q '^#define __wasip1__ 1$' "$F" || {
|
||||
echo "!! no se pudo reconciliar $F: no apareció el ancla '#define __wasm 1'" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
# Los dos triples que firefox puede pedir. NO se construye `wasm32-wasip2`: el APKBUILD de Alpine lo
|
||||
# hace para rust, que acá no lo consume, y cada triple de más es tiempo de build sin destinatario.
|
||||
make CC=clang TARGET_TRIPLE=wasm32-wasip1 BUILTINS_LIB="$BUILTINS"
|
||||
make CC=clang TARGET_TRIPLE=wasm32-wasip1-threads THREAD_MODEL=posix BUILTINS_LIB="$BUILTINS"
|
||||
|
||||
# `make install` copia `sysroot/{lib,share,include}` en bloque y falla si `share/` no existe.
|
||||
mkdir -p sysroot/share
|
||||
'''
|
||||
install = '''
|
||||
set -e
|
||||
mkdir -p /out/usr/share/wasi-sysroot
|
||||
|
||||
# SE COPIA A MANO EN VEZ DE `make install`, y no es atajo — `make install` NO SIRVE ACÁ.
|
||||
#
|
||||
# La regla de upstream son dos líneas: `mkdir -p $(INSTALL_DIR)` y
|
||||
# `cp -p -r $(SYSROOT)/{lib,share,include} $(INSTALL_DIR)`, con `SYSROOT ?= $(CURDIR)/sysroot`.
|
||||
# O sea que copia el sysroot ENTERO, sin mirar el triple. Pero la regla declara `install: finish`
|
||||
# y `finish` depende de `libc`, así que invocarla vuelve a entrar al grafo de compilación.
|
||||
#
|
||||
# El truco de pasarle un triple inexistente (`TARGET_TRIPLE=NOBUILD`, que es lo que hacía la
|
||||
# primera versión de esta receta) NO lo evita: make no lo lee como «no construyas», lo lee como
|
||||
# «construí para el triple NOBUILD» y muere compilando `build/NOBUILD/.../crt1-command.o` — con
|
||||
# un error que habla de un fichero que nadie pidió. Las dos vueltas de arriba ya dejaron el
|
||||
# sysroot completo; lo único que falta es moverlo.
|
||||
cp -p -r sysroot/lib sysroot/share sysroot/include /out/usr/share/wasi-sysroot/
|
||||
|
||||
# GUARDIÁN. Un sysroot con headers pero SIN `libc.a` es exactamente la clase de artefacto que pasa
|
||||
# por bueno y revienta 50 minutos después, dentro del build de firefox, con un error que no nombra
|
||||
# a wasi-libc. Se exige la libc del triple que firefox va a pedir.
|
||||
LIBC=/out/usr/share/wasi-sysroot/lib/wasm32-wasip1/libc.a
|
||||
test -s "$LIBC" || {
|
||||
echo "!! el sysroot no trae $LIBC" >&2
|
||||
find /out/usr/share/wasi-sysroot -name '*.a' 2>/dev/null | head -20 >&2
|
||||
exit 1
|
||||
}
|
||||
test -f /out/usr/share/wasi-sysroot/include/wasm32-wasip1/stdlib.h || {
|
||||
echo "!! el sysroot no trae los headers de wasm32-wasip1" >&2; exit 1; }
|
||||
echo "guardián: sysroot wasm32-wasip1 completo (libc.a $(stat -c%s "$LIBC") bytes, $(find /out/usr/share/wasi-sysroot -name '*.a' | wc -l) archivos .a)"
|
||||
'''
|
||||
@@ -0,0 +1,57 @@
|
||||
# wasi-sdk — el fichero de configuración que le dice a clang dónde está el sysroot de wasm.
|
||||
#
|
||||
# Es la pieza más chica de la cadena y la que la vuelve INVISIBLE para quien la usa: sin esto,
|
||||
# firefox tendría que enterarse por un flag de cómo llegar al sysroot; con esto, `clang
|
||||
# --target=wasm32-wasip1` lo encuentra solo. El clang de Alpine lee `/etc/clang22/<triple>.cfg`
|
||||
# —el lab ya trae ahí su propio `x86_64-alpine-linux-musl.cfg`, así que el mecanismo está probado en
|
||||
# esta misma máquina— y overlayfs FUSIONA directorios, así que esta dep suma su fichero sin pisar el
|
||||
# del lab.
|
||||
#
|
||||
# NO TIENE FUENTE UPSTREAM porque el contenido es nuestro: una línea. Usa `[source] dir`, el modo
|
||||
# que se agregó para `atuq` (SDD 26 §2.ter). Es su segundo consumidor, y el primero fuera del caso
|
||||
# que lo motivó.
|
||||
#
|
||||
# ⚠ `/etc/clang22` lleva la versión del lab en la RUTA. No es una constante que se pueda olvidar: si
|
||||
# el lab sube de LLVM, esta ruta deja de existir y el sysroot se vuelve invisible en silencio — por
|
||||
# eso el guardián de abajo comprueba que el directorio del lab exista ANTES de escribir dentro.
|
||||
name = "wasi-sdk"
|
||||
version = "27"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[source]
|
||||
dir = "wasi-sdk"
|
||||
|
||||
[build]
|
||||
compiler = "clang"
|
||||
|
||||
[deps]
|
||||
build = ["wasi-libc"]
|
||||
|
||||
[build.phases]
|
||||
configure = "true"
|
||||
compile = "true"
|
||||
install = '''
|
||||
set -e
|
||||
|
||||
# Si el lab cambió de versión de LLVM, esta ruta ya no es la que clang lee. Fallar acá es barato;
|
||||
# fallar dentro del build de firefox, cuatro horas después y con un error sobre un header de wasm
|
||||
# que no nombra a esta receta, no lo es.
|
||||
test -d /etc/clang22 || {
|
||||
echo "!! el lab no tiene /etc/clang22: ¿subió de versión de LLVM?" >&2
|
||||
ls -d /etc/clang* 2>/dev/null >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
mkdir -p /out/etc/clang22
|
||||
cp /src/wasm32-unknown-wasip1.cfg /out/etc/clang22/
|
||||
cp /src/wasm32-unknown-wasip1-threads.cfg /out/etc/clang22/
|
||||
|
||||
# GUARDIÁN: que el sysroot al que apunta el .cfg EXISTA. Un `--sysroot` que señala a la nada no da
|
||||
# error: clang sigue adelante y falla mucho después por headers que no encuentra.
|
||||
S=$(sed -n 's/^--sysroot //p' /out/etc/clang22/wasm32-unknown-wasip1.cfg)
|
||||
test -f "$S/lib/wasm32-wasip1/libc.a" || {
|
||||
echo "!! el .cfg apunta a $S y ahí no hay libc.a de wasm32-wasip1" >&2
|
||||
exit 1
|
||||
}
|
||||
echo "guardián: /etc/clang22 apunta a un sysroot wasm real ($S)"
|
||||
'''
|
||||
@@ -0,0 +1 @@
|
||||
--sysroot /usr/share/wasi-sysroot
|
||||
@@ -0,0 +1 @@
|
||||
--sysroot /usr/share/wasi-sysroot
|
||||
Reference in New Issue
Block a user