tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1572Shell 203Rust 109Markdown 993728 Definitions

bluez + pipewire: bluez5 encendido, y el bluetooth SUENA

`-Dbluez5=enabled` en pipewire, con `bluez` y `sbc` declarados. Resultado
medido en el artefacto: /usr/lib/spa-0.2/bluez5/ con los tres .so —
libspa-bluez5.so (21M), libspa-codec-bluez5-sbc.so y
libspa-codec-bluez5-faststream.so — y el plugin DEFINE 14 símbolos sbc_*, o
sea que el códec entró de verdad y no quedó un plugin que carga sin poder
negociar A2DP.

⚠ `libbluetooth.a` de bluez NO era PIC, y el enlace del plugin moría así:
    ld.lld: error: relocation R_X86_64_64 cannot be used against local symbol;
            recompile with -fPIC
    >>> defined in /usr/lib/libbluetooth.a(bluetooth.o)

Se arregla en bluez y no en el consumidor porque **su radio es 1** —pipewire
es su único consumidor, medido— y la regla del repo es que el radio decide de
qué lado se toca (libuv radio 1 frente a util-linux radio 79). Y no añade
cascada: pipewire ya se rearmaba por la perilla. Hacen falta los DOS flags,
igual que en sbc: --with-pic solo no basta con --disable-shared.

Los dos guardianes nuevos usan la prueba autoritativa en vez de contar
reubicaciones: meter la .a dentro de una .so, que es lo que hace el
consumidor. Contar R_X86_64_32 da falsos positivos por las secciones .debug_*
(me rechazó un sbc correcto el mismo día).

Y el de pipewire comprueba lo que de verdad importaba: que libspa-bluez5.so
quede DONDE PipeWire lo busca y con los símbolos del códec definidos. Sin eso
el servidor arranca perfecto y el auricular no es una salida — el estado del
que venimos.

NEEDED del plugin verificados contra el store, sin colgantes:
libdbus-1.so.3 → dbus-shared · libffi.so.8 → libffi-shared · libz.so.1 →
zlib-rs. El vigía de sonames da 0 sin proveedor en los cinco escritorios.

⚠ Esto rearma 18 recetas más, las TRES de Gecko incluidas (cadena PGO). Se
hace a pedido explícito del usuario, que conocía el precio.

271d22804b6acb1b593942cde9bedd4f76c26517 · by Sergio · (1 d ago) · parent 081839284 · browse the tree at this commit

Semantic delta

No definition changed: this change is text, documentation or data.

2 files · +68 −5

diff --git a/recipes/bluez.toml b/recipes/bluez.toml
index 3a5b5dd5..4c93a0dc 100644
--- a/recipes/bluez.toml
+++ b/recipes/bluez.toml
@@ -36,7 +36,21 @@ target   = "x86_64-linux-musl"
 link     = "static"
 
 [build.phases]
-configure = './configure --build=$CBUILD --host=$CHOST --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libexecdir=/usr/lib --disable-shared --enable-static --enable-library --enable-threads --disable-systemd --disable-obex --disable-manpages --disable-cups --disable-udev --with-dbusconfdir=/usr/share'
+# ⚠ **`--with-pic` + `CFLAGS=-fPIC` desde el 2026-10-21, y NO es cosmético.** `libbluetooth.a`
+# tiene un consumidor nuevo: `libspa-bluez5.so`, el plugin que PipeWire carga con `dlopen` para
+# hablar A2DP. Una `.a` sin PIC no entra en una `.so`, y el enlace de pipewire moría así:
+#     ld.lld: error: relocation R_X86_64_64 cannot be used against local symbol; recompile with -fPIC
+#     >>> defined in /usr/lib/libbluetooth.a(bluetooth.o)
+#     >>> referenced by bluetooth.o:(.rodata.bt_compidtostr+0x4ab8)
+#
+# Se arregla ACÁ y no en el consumidor porque **el radio de bluez es 1** —`pipewire` es su único
+# consumidor, medido— y la regla del repo es que el radio decide de qué lado se toca (igual que
+# `libuv` radio 1 frente a `util-linux` radio 79). Y no añade cascada: pipewire ya se rearma por
+# el `-Dbluez5=enabled`.
+#
+# Hacen falta LOS DOS flags: `--with-pic` solo no basta con `--disable-shared`, porque libtool lo
+# aplica a los objetos de la `.so` que no se construye. Mismo caso que en `sbc`.
+configure = './configure --build=$CBUILD --host=$CHOST --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libexecdir=/usr/lib --disable-shared --enable-static --enable-library --enable-threads --disable-systemd --disable-obex --disable-manpages --disable-cups --disable-udev --with-dbusconfdir=/usr/share --with-pic CFLAGS="$CFLAGS -fPIC"'
 # ⚠ `LDFLAGS=-all-static` EN COMPILE **Y** EN INSTALL. bluez enlaza con libtool, y libtool lee el
 # `-static` que exporta el lab como «preferí los .a de libtool», no como flag al linker ⇒ el primer
 # sello salió con los 11 ejecutables DINÁMICOS y `scripts/static-audit.sh` lo marcó. Lo de *install*
@@ -50,7 +64,21 @@ configure = './configure --build=$CBUILD --host=$CHOST --prefix=/usr --sysconfdi
 # pkg-config ⇒ la transitiva nunca entra. En dinámico no se nota (la resuelve el loader); en
 # estático hay que nombrarla. Misma familia que las transitivas del `.pc` de glib en `[deps]`.
 compile   = 'make LDFLAGS=-all-static LIBS=-lncursesw'
-install   = 'make LDFLAGS=-all-static LIBS=-lncursesw DESTDIR=/out install'
+install = '''
+set -e
+make LDFLAGS=-all-static LIBS=-lncursesw DESTDIR=/out install
+
+# ⚠ GUARDIÁN DE PIC — prueba AUTORITATIVA, no recuento de reubicaciones.
+# Contar `R_X86_64_32/32S` en el `.o` da falsos positivos: las secciones `.debug_*` llevan
+# reubicaciones absolutas SIEMPRE y no se cargan en ejecución (ese control me rechazó un build
+# CORRECTO de `sbc` por 321 de ésas, el mismo día). Lo que importa es si el consumidor puede
+# enlazarla, así que se hace exactamente eso: meter `libbluetooth.a` dentro de una `.so`.
+[ -f /out/usr/lib/libbluetooth.a ] || { echo "bluez: no quedó libbluetooth.a — --enable-library debería publicarla" >&2; exit 1; }
+printf 'extern int bt_bacmp(const void*,const void*);\nint envoltura(const void*a,const void*b){return bt_bacmp(a,b);}\n' > /tmp/bt.c
+/opt/zig/zig cc -mcpu=baseline -shared -fPIC -o /tmp/libbt.so /tmp/bt.c /out/usr/lib/libbluetooth.a 2>/tmp/bt.err \
+  || { echo "bluez: libbluetooth.a NO entra en una .so ⇒ libspa-bluez5.so de PipeWire no podría enlazarla y el bluetooth no sonaría" >&2; tail -8 /tmp/bt.err >&2; exit 1; }
+echo "bluez: libbluetooth.a es PIC (entra en una .so)"
+'''
 
 [[service]]
 label   = "bluetoothd"
diff --git a/recipes/pipewire.toml b/recipes/pipewire.toml
index 4c9b48f7..75174358 100644
--- a/recipes/pipewire.toml
+++ b/recipes/pipewire.toml
@@ -77,7 +77,23 @@
 # recetas entre colas, aplicada con la medición delante.
 #
 # Fuente del gitlab.freedesktop.org (como networkmanager/modemmanager).
-# Recortado al core + SPA: sin bluez5 (cadena de códecs aptx/ldac/aac/opus enorme), sin jack/v4l2/
+# Recortado al core + SPA: sin jack/v4l2/
+#
+# ══ ✅ BLUEZ5 ENCENDIDO EL 2026-10-21 — y la razón de apagarlo era exagerada ═══════════════════
+# Esta nota decía «sin bluez5 (cadena de códecs aptx/ldac/aac/opus enorme)». La cadena existe y es
+# OPCIONAL: leyendo `spa/meson.build:49-53`, las deps DURAS de `bluez5=enabled` son cinco —
+# `bluez >= 4.101`, `gio-2.0`, `gio-unix-2.0`, `glib-2.0` y `sbc`— y las cuatro primeras ya
+# estaban. Faltaba UNA receta, `sbc`, que es el único códec que A2DP exige (aptX/LDAC/AAC son
+# mejoras de calidad que se pueden añadir después sin tocar esto).
+#
+# **Qué se arregla:** el bluetooth EMPAREJABA y NO SONABA. `bluez` trae `bluetoothctl` y su daemon,
+# y los cuatro escritorios habilitan el servicio — pero sin el plugin SPA bluez5, PipeWire no ve el
+# auricular como salida. `/usr/lib/spa-0.2/` traía alsa, audioconvert, aec… y CERO bluez. Ninguno
+# de los dos paquetes estaba roto y la capacidad no existía.
+#
+# ⚠ **Esto rearma 19 recetas**, entre ellas las TRES de Gecko (firefox, firefox-instrumentado,
+# waterfox) ⇒ la cadena PGO entera. Era la razón de no hacerlo «de paso», y se hizo a pedido
+# explícito del usuario.
 # libcamera/gstreamer/ffmpeg/vulkan/roc/lv2/avahi/x11/echo-cancel-webrtc/libusb/flatpak/snap.
 # systemd/logind/selinux/rtkit off (no hay systemd acá). alsa=enabled + sndfile=enabled + libpulse=enabled
 # (el emulador pulse: deja que los clientes libpulse hablen con pipewire) — las 3 ya selladas.
@@ -110,7 +126,7 @@ PYTHONPATH=/usr/lib/python3.12/site-packages meson setup output --prefix=/usr --
   -Dsystemd=disabled -Dlogind=disabled -Dsystemd-system-service=disabled \
   -Dsystemd-user-service=disabled -Dselinux=disabled -Dlegacy-rtkit=false \
   -Dpipewire-jack=disabled -Dpipewire-v4l2=disabled -Djack=disabled -Dv4l2=disabled \
-  -Dlibcamera=disabled -Dbluez5=disabled -Dffmpeg=disabled -Dvulkan=disabled \
+  -Dlibcamera=disabled -Dbluez5=enabled -Dffmpeg=disabled -Dvulkan=disabled \
   -Droc=disabled -Dlv2=disabled -Davahi=disabled -Dx11=disabled -Dx11-xfixes=disabled \
   -Decho-cancel-webrtc=disabled -Dlibusb=disabled -Dflatpak=disabled -Dsnap=disabled \
   -Dlibmysofa=disabled -Dsdl2=disabled -Dopus=disabled -Dlibffado=disabled -Dcompress-offload=disabled \
@@ -138,11 +154,30 @@ PYTHONPATH=/usr/lib/python3.12/site-packages DESTDIR=/out meson install -C outpu
 mkdir -p /out/etc/alsa/conf.d
 ln -sf /usr/share/alsa/alsa.conf.d/50-pipewire.conf         /out/etc/alsa/conf.d/50-pipewire.conf
 ln -sf /usr/share/alsa/alsa.conf.d/99-pipewire-default.conf /out/etc/alsa/conf.d/99-pipewire-default.conf
+
+# ── ⚠ GUARDIÁN DEL PLUGIN BLUEZ5 ──────────────────────────────────────────────────────────────
+# `-Dbluez5=enabled` hace que meson FALLE si le faltan las deps, pero no protege del caso que de
+# verdad importa acá: que el plugin se construya y **no se instale** donde PipeWire lo busca. Sin
+# el `.so` en `/usr/lib/spa-0.2/` el servidor arranca perfecto y el auricular no es una salida —
+# que es exactamente el estado que esta receta viene a dejar atrás, así que se comprueba.
+bl=$(find /out/usr/lib/spa-0.2 -name 'libspa-bluez5.so' 2>/dev/null | head -1)
+[ -n "$bl" ] || { echo "pipewire: NO quedó libspa-bluez5.so en /usr/lib/spa-0.2 — el bluetooth seguiría sin sonar" >&2; ls /out/usr/lib/spa-0.2/ >&2; exit 1; }
+# Y que traiga DENTRO el códec: el plugin enlaza sbc estáticamente, así que sus símbolos tienen que
+# estar definidos (sección ≠ UND). Pedir sólo el fichero dejaría pasar un plugin sin códec, que
+# cargaría y no podría negociar A2DP.
+command -v nm >/dev/null && {
+  n=$(nm -D --defined-only "$bl" 2>/dev/null | grep -c 'sbc_' || true)
+  [ "${n:-0}" -gt 0 ] || { echo "pipewire: libspa-bluez5.so no DEFINE ningún símbolo sbc_* — el códec no entró y A2DP no se podría negociar" >&2; exit 1; }
+  echo "pipewire: libspa-bluez5.so presente con $n símbolo(s) sbc_* definidos"
+}
 '''
 
 [deps]
 build = ["meson", "samurai", "python3", "pkgconf", "dbus-shared", "expat", "alsa-lib", "libsndfile",
-  "pulseaudio", "glib", "pcre2", "libffi", "libudev-zero", "zlib-shared", "gettext-tiny"]
+  "pulseaudio", "glib", "pcre2", "libffi", "libudev-zero", "zlib-shared", "gettext-tiny",
+  # `bluez` y `sbc` son las dos piezas de `-Dbluez5=enabled`. `bluez` aporta su `bluez.pc` (5.87) y
+  # `sbc` el códec A2DP obligatorio; `gio-2.0`/`gio-unix-2.0`/`glib-2.0` los publica ya `glib`.
+  "bluez", "sbc"]
 
 # ── LOS SERVICIOS QUE ESTE PAQUETE TRAE (SDD 30) ────────────────────────────────────────────────
 # `scope = "session"`, y eso es una afirmación con consecuencia: estos NO van en el `genesis` de la