Con `atk` arreglado, atuq llegó más lejos y murió igual, ahora con Pango:
GLib-GObject-CRITICAL: cannot register existing type 'PangoFontMap'
… decenas de líneas … tipo '<invalid>'
MISMO CUADRO, CULPABLE DISTINTO Y MÁS GRANDE. `gtk3` produce DOS objetos compartidos —libgtk-3.so y
libgdk-3.so— y libxul declara NEEDED las dos, así que se cargan siempre juntas. Con las variantes
ESTÁTICAS de sus deps, cada una se llevaba adentro su propia copia. Medido con el mismo instrumento
que cazó a atk, `nm -D --defined-only`, preguntando quién DEFINE cada símbolo:
pango_font_map_get_type → libgdk-3.so, libgtk-3.so, libgailutil-3.so
cairo_create → libgdk-3.so, libgtk-3.so
gdk_pixbuf_get_type → libgdk-3.so, libgtk-3.so
hb_buffer_create → libgdk-3.so, libgtk-3.so, libgailutil-3.so
Y se comprobó el otro lado: libxul NO embebe ninguna —enlaza libgtk-3/libgdk-3 como debe—, así que
la duplicación es toda interna del par GTK3.
Cuatro variantes nuevas: harfbuzz-shared, cairo-shared, gdk-pixbuf-shared, pango-shared. Sólo cambia
el modo de librería; se conservan todos los switches del canónico para no arrastrar deps nuevas.
DOS DEUDAS ANOTADAS, NO OLVIDADAS: `fribidi` y `pixman` siguen estáticos —no existe variante— pero
quedan embebidos en UNA sola .so cada uno, así que no hay copia que colisione; y `libepoxy` sí queda
en las dos, y se deja porque no registra tipos de GObject ni mantiene estado global. Si algún día
otra .so del mismo proceso los embebe, vuelve el cuadro.
`firefox` swapea las mismas cuatro: declarar las ESTÁTICAS junto a un gtk3 que trae las compartidas
son dos artefactos peleando por el mismo `pango.pc`, que es la otra forma conocida de este fallo.
Y `xkeyboard-config` SUBE AL CORPUS. Existía idéntica en las cuatro colas de escritorio (un solo md5
entre las cuatro, verificado antes de mover) y atuq, que vive en el corpus, no podía alcanzar
ninguna: sibling-first y después el catálogo padre, nunca una cola hermana. Sin sus datos el
navegador ni pinta («xkbcommon: failed to add default include path /usr/share/X11/xkb»). Mismo hash
en el corpus que en las colas ⇒ cero rebuilds, y las copias de las colas se quedan donde están.
298 lines
21 KiB
TOML
298 lines
21 KiB
TOML
# Firefox 154.0 — el navegador. Tercera app de usuario final, y **la cabeza de la familia Gecko**:
|
|
# Waterfox y Zen son forks suyos y reutilizan todo lo de abajo.
|
|
#
|
|
# ══ POR QUÉ 154 Y NO 155, QUE ES LA QUE SIGUE ZEN ══════════════════════════════════════════════
|
|
# Zen declara `"version": "155.0.1"` en su `surfer.json` y Waterfox 6.7 también va por el canal
|
|
# release, así que 155 parecía la base obvia. Se eligió **154** por una razón concreta: **los parches
|
|
# de musl de Alpine son para 154.0**, y son once. Ese es el trabajo de portabilidad que un import de
|
|
# nix pierde y que no conviene rehacer a mano — sin ellos Firefox no compila contra musl.
|
|
#
|
|
# Un Firefox que compila con el set probado vale más que uno con el número correcto que no compila.
|
|
# Y como Firefox se mueve cada cuatro semanas, la paridad exacta con Zen es una cinta de correr: lo
|
|
# que de verdad se reutiliza entre los tres es LA PLATAFORMA (gtk3/nodejs/clang/cbindgen, todo ya en
|
|
# el corpus) y ESTE SET DE PARCHES. Subir a 155 después es un rebase, no un port.
|
|
#
|
|
# ══ TODO BUNDLEADO SALVO GTK3 ══════════════════════════════════════════════════════════════════
|
|
# Alpine usa `--with-system-{icu,nspr,nss,av1,libvpx,webp,libevent,...}`; de ésas el corpus tiene
|
|
# CERO. Firefox trae todas en el árbol, así que se dejan bundleadas: son menos piezas móviles para el
|
|
# primer build, que es exactamente cuando conviene minimizar variables. Cuando alguna de esas
|
|
# librerías tenga receta propia y valga compartirla, el flag se enciende y se re-mide.
|
|
#
|
|
# ══ SIN BRANDING OFICIAL, Y NO ES UN DESCUIDO ══════════════════════════════════════════════════
|
|
# Alpine pone `--enable-official-branding`. Acá NO: el binario lleva once parches, y usar el nombre y
|
|
# el logo de Firefox sobre un build modificado entra en la política de marcas de Mozilla — es
|
|
# literalmente la historia de Iceweasel en Debian. Con el branding `unofficial` el navegador es el
|
|
# mismo software y nadie tiene que pedir permiso a nadie. Es la misma cautela que la receta de
|
|
# `dejavu-fonts-nerd` ya aplicó con la licencia de Bitstream Vera: **una fuente modificada no puede
|
|
# llamarse como la original, y un navegador parcheado tampoco.**
|
|
#
|
|
# ══ WAYLAND-ONLY, HEREDADO DE GTK3 ═════════════════════════════════════════════════════════════
|
|
# `--enable-default-toolkit=cairo-gtk3-wayland`. Nuestro GTK3 se construyó con `-Dx11_backend=false`
|
|
# ⇒ este Firefox **no puede correr como cliente X11 ni bajo Xwayland**. Bajo Wayland nativo sí. Está
|
|
# escrito en `recipes/gtk3.toml` y se repite acá porque es lo primero que alguien va a preguntar.
|
|
#
|
|
# ══ HERMÉTICO: NADA DE RED DURANTE EL BUILD ════════════════════════════════════════════════════
|
|
# --disable-bootstrap su trabajo ES descargar toolchains. Prohibido.
|
|
# MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE sin esto `mach` arma un virtualenv con `pip` y sale a
|
|
# =system la red. Con `system` usa lo que ya está.
|
|
# MOZBUILD_STATE_PATH por defecto escribe en `$HOME`, que en el sandbox no es
|
|
# suyo; se apunta al árbol de build.
|
|
# Los crates de Rust vienen VENDORIZADOS en el tarball (`third_party/rust`) ⇒ cargo no baja nada.
|
|
#
|
|
# ══ LO DEMÁS QUE SE APAGA ══════════════════════════════════════════════════════════════════════
|
|
# --disable-jemalloc musl trae su propio allocator; jemalloc encima es la receta del
|
|
# cuelgue clásico de Firefox en Alpine.
|
|
# --without-wasm-sandboxed- exige el SDK de WASI, que no está en ninguna cola. Apaga el
|
|
# libraries sandbox wasm de algunas librerías de medios, no el sandbox del
|
|
# proceso de contenido.
|
|
# --disable-crashreporter manda telemetría a Mozilla; además pide breakpad.
|
|
# --disable-updater la distro actualiza por hammer, no por un updater propio.
|
|
# --disable-tests no entran al artefacto.
|
|
# (SIN --enable-linker) Se deja que Firefox detecte solo. Con `zig-cc` esto era
|
|
# OBLIGATORIO —zig se anuncia como `zig ld 0.16.0` y el sondeo de
|
|
# `toolchain.configure` clasifica por esa cadena buscando
|
|
# «mold»/«GNU ld»/«GNU gold»/«LLD»— y **pedir el linker por nombre
|
|
# vuelve FATAL cualquier fallo del sondeo**. Con gcc el linker sí se
|
|
# anuncia como «GNU ld», así que el flag ya no haría daño; se deja
|
|
# fuera igual porque no aporta nada y una perilla menos es una
|
|
# diferencia menos entre esta receta y las de Waterfox y Zen.
|
|
name = "firefox"
|
|
version = "154.0"
|
|
license = "MPL-2.0"
|
|
|
|
[source]
|
|
# Tarball de RELEASE de Mozilla: fichero SUBIDO por upstream, sha256 estable y publicado en su
|
|
# SHA256SUMS. No es un `/archive/<tag>` de forja, que se genera al vuelo (ver `recipes/mbedtls.toml`).
|
|
tarball = "https://ftp.mozilla.org/pub/firefox/releases/154.0/source/firefox-154.0.source.tar.xz"
|
|
sha256 = "36cec5b3688a60f78a6d20dcaee15b598f84e03c66f6587056aead6cb498b99a"
|
|
# Los once de musl del APKBUILD de Alpine (community/firefox). NO se traen los suyos de ppc64le,
|
|
# loongarch ni Android: no aplican a x86_64 y cada parche que no hace falta es una forma más de que
|
|
# un rebase falle sin motivo.
|
|
patches = [
|
|
"firefox-patches/lfs64.patch",
|
|
"firefox-patches/time64.patch",
|
|
"firefox-patches/musl-no-linux-prctl.patch",
|
|
"firefox-patches/fix-fortify-system-wrappers.patch",
|
|
"firefox-patches/fix-rust-target.patch",
|
|
"firefox-patches/sandbox-sched_setscheduler.patch",
|
|
"firefox-patches/abseil-cpp.patch",
|
|
"firefox-patches/glean-stub.patch",
|
|
"firefox-patches/rust-lto-thin.patch",
|
|
"firefox-patches/wasip1.patch",
|
|
"firefox-patches/widevine.patch",
|
|
]
|
|
|
|
[build]
|
|
# ══ `clang` — Y POR QUÉ YA NO ES `gcc` (2026-09-05) ════════════════════════════════════════════
|
|
# HISTORIA: esta receta nació con `compiler = "gcc"` porque con zig-cc el configure de Firefox murió
|
|
# tres veces seguidas. Los tres muros eran REALES y siguen siéndolo para zig:
|
|
#
|
|
# 1. «Could not use lld as linker» — zig se identifica como `zig ld 0.16.0` y el sondeo de Mozilla
|
|
# clasifica por esa cadena buscando «LLD»/«GNU ld»/«GNU gold».
|
|
# 2. «Cannot find ar» — zig trae `ar` como SUBCOMANDO y `check_prog` busca un ejecutable.
|
|
# 3. «Firefox does not support linking statically with libstdc++» — `flags.configure:79` compila un
|
|
# C++ mínimo, lo pasa por `llvm-objdump --private-headers` y exige un `NEEDED` de la stdlib de
|
|
# C++. zig enlaza libc++ ESTÁTICA para musl, así que ese NEEDED no existe nunca.
|
|
#
|
|
# gcc satisfacía los tres, pero al precio de quedar FUERA de la cadena de optimización de Gecko:
|
|
# **PGO, LTO y BOLT son cadena de clang en Firefox** (`--enable-lto=cross` quiere clang+lld,
|
|
# `--enable-profile-use=cross` espera `-fprofile-instr-use`). Con gcc no hay perilla que encender.
|
|
# Medido contra el APKBUILD de `community/firefox` de aports —nuestro propio upstream, de donde
|
|
# salen los once parches de musl— y contra el PKGBUILD de Arch: **las dos hacen LTO y PGO**. No
|
|
# estábamos adelante de nadie; estábamos atrás, y la puerta era el compilador.
|
|
#
|
|
# clang RESUELVE LOS TRES MUROS SIN PERDER NADA:
|
|
# 1. `--enable-linker=lld` + `lld` en el lab (añadido a `bootstrap-devfs.sh` el 2026-09-05).
|
|
# 2. `AR=llvm-ar` lo pone hammer solo con `compiler="clang"` (hammer-build/src/lib.rs), y la suite
|
|
# `llvm-*` está expuesta en `/usr/bin` por el paso 3a-ter del bootstrap.
|
|
# 3. clang++ de Alpine usa la `libstdc++` COMPARTIDA de gcc ⇒ el `NEEDED` existe. La prueba no es
|
|
# teórica: Alpine construye este mismo Firefox con clang22 y **sin** `libcxx` en sus makedepends.
|
|
#
|
|
# El lab ya traía `clang22`/`llvm22` 22.1.8 (la MISMA major que usa Alpine: `_llvmver=22`), así que
|
|
# esto no costó una receta de LLVM: costó `apk add lld`.
|
|
#
|
|
# ⚠ EL PRECIO, ESCRITO: el toolchain del lab SÍ entra en `hash_inputs` desde el 2026-08-10
|
|
# (`hammer-core/src/lab.rs`), pero **`lld` no casa ningún prefijo de `TOOLCHAIN_PREFIXES`** ⇒ su
|
|
# versión NO está en la huella. Eso es lo que permitió añadirlo sin re-hashear los 837 artefactos
|
|
# sellados —medido: la huella no se movió—, y a la vez deja un agujero que sólo expone a las recetas
|
|
# `compiler="clang"`, que hoy es ésta. Cerrarlo cuesta un re-hasheo del corpus entero.
|
|
compiler = "clang"
|
|
target = "x86_64-linux-musl"
|
|
link = "dynamic"
|
|
flags = []
|
|
# ══ `strip_debug`: SIN ESTO EL ARTEFACTO SERÍA INMANEJABLE ═════════════════════════════════════
|
|
# Medido en el `nodejs` que acaba de sellar sin strip: su binario pesa **984 MB, de los cuales
|
|
# `.debug_info` son 497 MB y `.debug_line` otros 43** — más de la mitad del artefacto es información
|
|
# de depuración. Firefox es varias veces V8, así que sin strip su artefacto entraría en varios GB, y
|
|
# el store no es sólo disco: se sincroniza hub↔worker y se respalda.
|
|
#
|
|
# Es además el hallazgo del SDD 23: el 79% del contenido binario del store era `.debug_*`, y quitarlo
|
|
# hace que artefactos que no reproducían PASEN a reproducir, porque lo que difería eran las rutas del
|
|
# árbol de build embebidas en esas secciones.
|
|
#
|
|
# Entra en `hash_inputs` A PROPÓSITO (cambia el contenido del artefacto), y usa `zig objcopy`, que
|
|
# siempre está en el sandbox ⇒ no agrega una dep de build.
|
|
strip_debug = true
|
|
# ⚠ DEUDA MEDIDA EL 2026-09-05: ESTE ARTEFACTO NO REPRODUCE BIT A BIT ═══════════════════════════
|
|
# `application.ini` del artefacto sellado trae `BuildID=20260905035306`: la FECHA Y HORA del build.
|
|
# Dos construcciones de esta misma receta, con el mismo hash, producen bytes distintos — que es
|
|
# exactamente el agujero que el invariante de reproducibilidad existe para cerrar, y no se ve en
|
|
# `build-state.json` porque el ArtifactHash es input-addressed y no se mueve.
|
|
# El arreglo es el que ya usa Alpine: exportar `MOZ_BUILD_DATE` con un valor determinista en las
|
|
# fases (su APKBUILD lo deriva de `SOURCE_DATE_EPOCH`; acá el candidato natural es un valor fijo,
|
|
# que al vivir en el texto de la fase entra en `hash_inputs` y queda declarado).
|
|
# NO se aplica de paso: cambiar una fase re-hashea la receta y cuesta otro build de cuatro horas
|
|
# más el re-sellado de `atuq`, que cuelga de ella. Es su propia unidad de trabajo.
|
|
|
|
[build.phases]
|
|
configure = '''
|
|
export MOZBUILD_STATE_PATH="$PWD/.mozbuild"
|
|
export MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE=system
|
|
export MOZ_NOSPAM=1
|
|
# ── RUST_TARGET: lo EXIGE el parche de Alpine, no Firefox ─────────────────────────────────────
|
|
# `fix-rust-target.patch` REEMPLAZA la autodetección del triple de Rust por un
|
|
# `os.environ['RUST_TARGET']` pelado. Sin la variable, configure muere con
|
|
# `KeyError: 'RUST_TARGET'` — que se lee como un bug de Firefox y es en realidad el contrato del
|
|
# parche: el APKBUILD de Alpine lo exporta como `$CTARGET` y acá hay que hacer lo propio.
|
|
# El valor NO se adivina: sale de `ls .dev-fs/alpine/usr/lib/rustlib/` en el lab, que es
|
|
# `x86_64-alpine-linux-musl` — el rustc del sandbox es el de Alpine, no el del host (el del host es
|
|
# `x86_64-unknown-linux-gnu` y usarlo produciría un cross-compile silencioso).
|
|
export RUST_TARGET=x86_64-alpine-linux-musl
|
|
|
|
# ── LOS PARCHES ROMPEN EL CHECKSUM DE LOS CRATES VENDORIZADOS ─────────────────────────────────
|
|
# `error: the listed checksum of third_party/rust/zeitstempel/src/unix.rs has changed`. Los crates
|
|
# de Rust vienen VENDORIZADOS en el tarball y cargo verifica el sha de CADA fichero contra
|
|
# `.cargo-checksum.json`; en cuanto un parche de musl toca uno, el build muere. Cargo no ofrece
|
|
# ninguna forma de recalcularlo, así que la salida —la misma del APKBUILD de Alpine— es vaciar la
|
|
# lista de ficheros del manifiesto, dejando el checksum del paquete.
|
|
#
|
|
# Son los CINCO crates que tocan los parches, no uno: el error los va destapando de a uno y buscarlos
|
|
# por prueba y error costaría cinco vueltas de configure.
|
|
for c in audio_thread_priority cc zeitstempel wgpu-hal alsa; do
|
|
f="third_party/rust/$c/.cargo-checksum.json"
|
|
[ -f "$f" ] || { echo "FALTA $f — ¿upstream movió el crate?" >&2; exit 1; }
|
|
sed -i 's/\("files":{\)[^}]*/\1/' "$f"
|
|
done
|
|
cat > .mozconfig <<'MOZ'
|
|
ac_add_options --prefix=/usr
|
|
ac_add_options --enable-application=browser
|
|
ac_add_options --enable-default-toolkit=cairo-gtk3-wayland
|
|
ac_add_options --enable-release
|
|
ac_add_options --enable-optimize
|
|
ac_add_options --enable-hardening
|
|
# ── LA CADENA DE OPTIMIZACIÓN (2026-09-05) ────────────────────────────────────────────────────
|
|
# Las tres primeras son lo que Alpine y Arch ya hacían y nosotros no. `--enable-linker=lld` además
|
|
# resuelve el muro 1 del sondeo de linker (ver el bloque [build]).
|
|
ac_add_options --enable-linker=lld
|
|
ac_add_options --enable-lto=cross
|
|
ac_add_options --enable-packed-relative-relocs
|
|
# ── LO QUE HABILITA A `atuq` (SDD 26) ─────────────────────────────────────────────────────────
|
|
# Sin esto un Firefox de release rechaza las extensiones que la distro deja en
|
|
# `distribution/extensions/`. Es flag de CONFIGURE, o sea que NO se puede resolver en el overlay del
|
|
# artefacto derivado: la capacidad de `atuq` de shipear sus propias extensiones (el `sct` v1) se
|
|
# decide acá, en la base. Alpine pasa exactamente este flag y por el mismo motivo.
|
|
ac_add_options --with-unsigned-addon-scopes=app,system
|
|
ac_add_options --with-branding=browser/branding/unofficial
|
|
ac_add_options --with-libclang-path=/usr/lib
|
|
ac_add_options --disable-bootstrap
|
|
ac_add_options --disable-jemalloc
|
|
ac_add_options --disable-crashreporter
|
|
ac_add_options --disable-updater
|
|
ac_add_options --disable-tests
|
|
ac_add_options --disable-debug
|
|
ac_add_options --disable-debug-symbols
|
|
ac_add_options --disable-strip
|
|
ac_add_options --disable-install-strip
|
|
ac_add_options --disable-cargo-incremental
|
|
ac_add_options --without-wasm-sandboxed-libraries
|
|
ac_add_options --enable-alsa
|
|
ac_add_options --enable-pulseaudio
|
|
ac_add_options --enable-dbus
|
|
ac_add_options --enable-ffmpeg
|
|
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/objdir
|
|
MOZ
|
|
# ── POR QUÉ AQUÍ NO HAY PGO TODAVÍA ───────────────────────────────────────────────────────────
|
|
# PGO es la otra mitad de la ganancia (LTO solo rinde menos que LTO+PGO) y NO entra en esta pasada
|
|
# por dos muros que las distros no tienen, porque no persiguen lo que nosotros perseguimos:
|
|
# 1. El perfil se junta CORRIENDO el navegador. Alpine y Arch lo hacen bajo `xvfb-run`; nosotros
|
|
# NO tenemos X11 en el corpus (la distro es Wayland-only) ⇒ el camino es un sway headless.
|
|
# 2. El `profdata` NO es determinista (los contadores dependen del timing) ⇒ si se generara aquí,
|
|
# cada build sellaría bytes distintos. La salida es generarlo UNA vez, sellarlo como artefacto
|
|
# propio y consumirlo por hash desde `[deps]`.
|
|
# Es su propia unidad de trabajo (SDD 26 §3.ter). Cuando llegue, además trae el `jarlog`, que ordena
|
|
# el `omni.ja` para el arranque — y eso condiciona cómo `atuq` puede re-empacarlo.
|
|
#
|
|
# ── ThinLTO Y LA MEMORIA ──────────────────────────────────────────────────────────────────────
|
|
# El enlace ThinLTO abre un trabajo por hilo y cada uno carga bitcode: sin capar, el link es lo
|
|
# primero que muere por OOM en una máquina de 16 GiB. Se capa con la MISMA cuenta que `-j` y por la
|
|
# misma razón que ella no es un número fijo: un literal ataría el ArtifactHash a la RAM de quien
|
|
# escribió la receta (ver la nota de la fase compile).
|
|
# ⚠ Si algún día dos máquinas con distinto `nproc` sellan bytes distintos, el primer sospechoso es
|
|
# este flag — ThinLTO se diseñó determinista respecto al número de trabajos, pero es una promesa
|
|
# de upstream, no algo que hayamos medido acá.
|
|
gib=$(awk "/MemTotal/{printf \"%d\", \$2/1024/1024}" /proc/meminfo)
|
|
jl=$(( gib / 3 )); [ "$jl" -lt 1 ] && jl=1
|
|
n=$(nproc); [ "$jl" -gt "$n" ] && jl=$n
|
|
export LDFLAGS="${LDFLAGS:-} -Wl,--thinlto-jobs=$jl"
|
|
echo "ThinLTO con --thinlto-jobs=$jl (MemTotal ${gib} GiB, nproc $n)"
|
|
./mach configure
|
|
'''
|
|
# `mach build` respeta -jN; la cuenta es la misma que en nodejs.toml y por el mismo motivo: un número
|
|
# fijo ataría el ArtifactHash a la RAM de quien escribió la receta.
|
|
# ⚠ OJO con el techo: dentro del sandbox `/proc/meminfo` NO muestra la memoria del contenedor sino la
|
|
# del host (medido en el LXC: 186 GiB en vez de 16), así que en un contenedor esta cuenta se degrada
|
|
# a `nproc`. Es un tope, no una garantía.
|
|
compile = '''
|
|
export RUST_TARGET=x86_64-alpine-linux-musl # ver la nota en la fase configure
|
|
export MOZBUILD_STATE_PATH="$PWD/.mozbuild"
|
|
export MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE=system
|
|
export MOZ_NOSPAM=1
|
|
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 "mach build -j$j (MemTotal ${gib} GiB, nproc $n)"
|
|
./mach build -j"$j"
|
|
'''
|
|
install = '''
|
|
export RUST_TARGET=x86_64-alpine-linux-musl # ver la nota en la fase configure
|
|
export MOZBUILD_STATE_PATH="$PWD/.mozbuild"
|
|
export MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE=system
|
|
DESTDIR=/out ./mach install
|
|
'''
|
|
|
|
[deps]
|
|
build = [
|
|
"python3", "pkgconf", "nasm", "make", "cmake",
|
|
# la plataforma Gecko, compartida con los forks (SDD 26)
|
|
#
|
|
# ⚠ NI `clang18` NI `llvm18` — Y NO ES UN OLVIDO (2026-09-05) ─────────────────────────────────
|
|
# Estaban aquí cuando esta receta compilaba con gcc: `clang18` aportaba el `libclang.so` que
|
|
# bindgen carga en runtime y `llvm18` la suite `llvm-ar`/`llvm-objdump` que Mozilla exige. Con
|
|
# `compiler = "clang"` se volvieron ACTIVAMENTE DAÑINAS: una dep del corpus se materializa en el
|
|
# sandbox y **tapa** el binario del lab, así que `/usr/bin/llvm-ar` pasaba a ser el de LLVM 18
|
|
# mientras el compilador era clang 22. Con ThinLTO encendido los `.o` ya no son objetos sino
|
|
# BITCODE, y el bitcode no es compatible hacia atrás:
|
|
#
|
|
# /usr/bin/llvm-ar: error: …log.o: 'Unknown attribute kind (102)'
|
|
# (Producer: 'LLVM22.1.8' Reader: 'LLVM 18.1.8')
|
|
#
|
|
# El error nombra las DOS versiones, que es lo que lo hace diagnosticable de un vistazo. Es la
|
|
# misma forma que la lección de los headers UAPI: una dep tapa al lab y el fallo aparece lejos.
|
|
# El lab ya trae todo lo necesario en la versión correcta —`clang22-libclang` deja
|
|
# `/usr/lib/libclang.so` y el paso 3a-ter del bootstrap expone la suite `llvm-*` de llvm22 en
|
|
# `/usr/bin`—, así que la respuesta no es apuntar el AR a mano: es NO traer el 18.
|
|
# Es además lo que hace Alpine: clang22 + clang22-libclang, sin un segundo LLVM en la mesa.
|
|
"nodejs", "cbindgen",
|
|
# Las mismas variantes `-shared` que usa gtk3 (2026-09-05). No es simetría: declarar acá las
|
|
# ESTÁTICAS junto a un gtk3 que trae las compartidas son dos artefactos peleando por el mismo
|
|
# `lib/pkgconfig/pango.pc` y las mismas cabeceras, que es la otra forma conocida de este mismo
|
|
# fallo. Van las dos listas al mismo sitio o ninguna.
|
|
"gtk3", "atk", "gdk-pixbuf-shared", "pango-shared", "cairo-shared", "libepoxy",
|
|
"glib-shared", "pcre2-shared", "libffi-shared", "zlib-shared",
|
|
"harfbuzz-shared", "fribidi", "freetype-shared", "fontconfig-shared", "pixman",
|
|
"libpng-shared", "libjpeg-turbo-shared",
|
|
"wayland", "wayland-protocols", "libxkbcommon", "mesa", "libdrm",
|
|
"dbus", "pipewire", "pulseaudio", "alsa-lib",
|
|
"libxml2-shared", "linux-headers",
|
|
]
|