# 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)" '''