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