Files
takana/recipes/nodejs.toml
T
Sergio 9c657efe61 plataforma Gecko: nodejs 24.18.1 — ./mach configure lo exige
Firefox aborta con «Could not find a Node.js executable»: lo usa para empaquetar
los bundles de JS. Waterfox y Zen lo necesitan igual ⇒ al corpus con el resto de
la plataforma.

TODO BUNDLEADO, a diferencia de Alpine, que lo construye contra diez deps del
sistema de las cuales el corpus tiene dos. La decisión de fondo: acá Node es un
COMPILADOR, no software que la distro publique — entra al sandbox de Firefox y
desaparece, así que el cierre chico gana al cierre puro y el precio (binario
gordo, openssl bundleado que nadie expone) no lo paga ningún usuario. Si algún
día se quiere PUBLICAR Node, esa es otra receta; queda avisado en la cabecera.

Dos AVX-512 apagados, y los dos por la perilla que upstream mismo deja:
 · simdjson  → SIMDJSON_AVX512_ALLOWED=0. ⚠ EN EL .h Y EN EL .cpp: la librería se
   distribuye AMALGAMADA y el .cpp lleva su propia copia (línea 2493), así que
   tocar sólo el header no sirve — y engaña, porque ninja sigue con otros objetos
   y el log parece avanzar.
 · simdutf (dentro de V8) → se antepone SIMDUTF_IMPLEMENTATION_ICELAKE 0, que es
   el override que habilita su #ifndef.
No se pierde nada: todo el corpus va -mcpu=baseline y ambas eligen implementación
en RUNTIME. CXXFLAGS NO sirve acá — GYP no lo propaga a la línea de compilación
(verificado buscando el -D en el comando que ninja reportó al fallar).

EL PARALELISMO SE CAPA POR RAM Y SIN ESCRIBIR UN NÚMERO. Sin cap, ninja lanza
nproc+2 y muere con `job terminated due to signal 9` en el objeto 2936/4414
compilando lo que genera Torque (~2 G por job). Un `-j2` fijo ataría el
ArtifactHash a la RAM de quien escribió la receta; la cuenta es un job cada 3 GiB
de MemTotal, mínimo 1, tope nproc. Da 2 en momento (7,6 GiB) y 5 en el LXC
(16 GiB, 6 cores) con el MISMO texto y el mismo hash.
2026-09-04 20:55:57 +00:00

96 lines
6.6 KiB
TOML

# Node.js 24.18.1 (LTS) — HERRAMIENTA DE BUILD de la plataforma Gecko, no un runtime de la distro.
#
# ══ POR QUÉ ENTRA ══════════════════════════════════════════════════════════════════════════════
# `./mach configure` de Firefox aborta con «Could not find a Node.js executable» si no lo encuentra:
# lo usa para empaquetar los bundles de JS del navegador. No hay perilla para saltarlo. Firefox,
# Waterfox y Zen lo necesitan igual, así que va al corpus con el resto de la plataforma.
#
# ══ TODO BUNDLEADO, A DIFERENCIA DE ALPINE ═════════════════════════════════════════════════════
# El APKBUILD de Alpine lo construye contra deps del sistema (ada, brotli, c-ares, icu, nghttp2,
# openssl, simdjson, simdutf, sqlite, zstd): de esas, el corpus tiene DOS. Escribir las otras ocho
# para que un navegador pueda compilar es la cola equivocada por la que agarrar el problema.
#
# La decisión de fondo: **acá Node es un compilador más, no software que la distro publique**. Nadie
# va a `hammer install nodejs` desde este artefacto — entra al sandbox de Firefox y desaparece. Para
# eso, el cierre chico gana al cierre puro, y el precio (un binario más gordo, un openssl bundleado
# que nadie expone) no lo paga ningún usuario. Si algún día la distro quiere PUBLICAR Node, esa es
# otra receta y otras deps, y esta nota es el aviso de que no se reutiliza tal cual.
#
# `--with-intl=small-icu`: el default `full-icu` DESCARGA el ICU completo durante el configure, y un
# build hermético no baja nada. `small-icu` usa el ICU que ya viene en el árbol.
# `--ninja`: V8 con make es notablemente más lento y acá se compila entero.
name = "nodejs"
version = "24.18.1"
license = "MIT"
[source]
tarball = "https://nodejs.org/dist/v24.18.1/node-v24.18.1.tar.gz"
# sha256 de SHASUMS256.txt publicado por upstream, no calculado sobre lo que bajó: el fichero de
# nodejs.org/dist es un artefacto SUBIDO, no generado al vuelo por una forja ⇒ estable (misma
# distinción que en la receta de mbedtls).
sha256 = "b62cd76de0a0a28dd9ff88580c92344bdeb008f21c1d7479c5d8659cd96ef4e2"
[build]
compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "dynamic"
flags = []
[build.phases]
# ⚠ `SIMDJSON_IMPLEMENTATION_ICELAKE=0` — el simdjson que Node bundlea trae un kernel AVX-512 y
# zig-cc lo rechaza: `always_inline function '_mm512_loadu_si512' requires target feature 'evex512'`
# más una tanda de «AVX vector argument … without 'evex512' enabled changes the ABI». clang exige
# `evex512` además del `avx512*` que el código pide por atributo.
#
# Se apaga el kernel en vez de encender `-mevex512`, y no es una salida por lo bajo: **todo el corpus
# compila `-mcpu=baseline`**, así que ese camino no se ejecutaría ni aunque compilara — simdjson elige
# implementación en RUNTIME y caería a haswell/westmere igual. Encender AVX-512 acá produciría además
# un binario que no arranca en cualquier máquina, que es lo contrario de lo que el `baseline` protege.
#
# **Por `sed` sobre el header y NO por `CXXFLAGS`**, que fue el primer intento y no funciona: GYP no
# propaga `CXXFLAGS` del entorno a la línea de compilación (verificado buscando el `-D` en el comando
# que ninja reportó al fallar — no estaba). Se toca la perilla que el propio simdjson expone,
# `SIMDJSON_AVX512_ALLOWED` (`simdjson.h:2512`, default 1), y no la macro de resultado: apagar la
# entrada declarada por upstream es más estable ante una actualización que forzar la salida.
configure = '''
# ⚠ EL `.h` NO ALCANZA: simdjson se distribuye AMALGAMADO y `simdjson.cpp` trae **su propia copia**
# de la perilla (`simdjson.cpp:2493`), no la incluye del header. Tocar sólo el `.h` deja el `.cpp`
# compilando el kernel AVX-512 igual — y el fallo ENGAÑA, porque ninja sigue con otros objetos y el
# log parece avanzar. Se tocan LOS DOS ficheros, y el `grep` verifica los dos.
for f in deps/simdjson/simdjson.h deps/simdjson/simdjson.cpp; do
sed -i 's/^#define SIMDJSON_AVX512_ALLOWED 1$/#define SIMDJSON_AVX512_ALLOWED 0/' "$f"
grep -q '^#define SIMDJSON_AVX512_ALLOWED 0$' "$f" # falla ruidoso si upstream mueve la línea
done
# simdutf (dentro de V8) es la MISMA falla en otra librería: apareció recién cuando simdjson dejó de
# fallar, que es cómo salen estos errores — por capas, una librería por vuelta. No expone un knob
# «ALLOWED»; lo que deja es el `#ifndef SIMDUTF_IMPLEMENTATION_ICELAKE` de `simdutf.cpp:3901`, o sea
# que el override previsto es DEFINIRLO desde afuera. Se antepone al fichero en vez de editar el
# `#define`, que ocupa dos líneas con continuación y sería más frágil ante una actualización.
sed -i '1i #define SIMDUTF_IMPLEMENTATION_ICELAKE 0' deps/v8/third_party/simdutf/simdutf.cpp
head -1 deps/v8/third_party/simdutf/simdutf.cpp | grep -q 'SIMDUTF_IMPLEMENTATION_ICELAKE 0'
python3 ./configure --prefix=/usr --ninja --with-intl=small-icu
'''
# ══ EL PARALELISMO SE CAPA POR RAM, Y SIN ESCRIBIR UN NÚMERO ═══════════════════════════════════
# Sin cap, ninja lanza `nproc+2` jobs y el build muere con `ninja: job terminated due to signal 9`
# —SIGKILL, el OOM killer— alrededor del objeto 2900/4414, compilando los ficheros que genera Torque:
# son de los C++ más pesados que existen, del orden de 2 G por job.
#
# **No se escribe `-j2`.** Las fases entran en `hash_inputs`, así que un número fijo ataría el
# ArtifactHash a la RAM de la máquina donde se escribió la receta, y el mismo texto daría hashes
# distintos según quién lo edite. La regla del repo es que el TEXTO sea independiente de la máquina y
# el COMPORTAMIENTO se adapte — que es exactamente lo que hace el `$(nproc)` del resto del corpus.
# Acá el recurso escaso no son los cores sino la memoria, así que la cuenta es por RAM: un job cada
# 3 GiB de MemTotal, nunca menos de 1 ni más de `nproc`. En una máquina de 7 GiB da 2; en una de 64
# daría 21 y ganaría el `nproc`.
compile = '''
gib=$(awk "/MemTotal/{printf \"%d\", \$2/1024/1024}" /proc/meminfo)
j=$(( gib / 3 )); [ "$j" -lt 1 ] && j=1
n=$(nproc); [ "$j" -gt "$n" ] && j=$n
echo "ninja -j$j (MemTotal ${gib} GiB, nproc $n) — V8 y Torque son de los C++ más pesados que hay"
ninja -C out/Release -j"$j"
'''
install = "DESTDIR=/out ninja -C out/Release install || (mkdir -p /out/usr/bin && cp out/Release/node /out/usr/bin/node)"
[deps]
build = ["python3", "samurai", "pkgconf", "make", "linux-headers", "zlib"]