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…

⎇ main recipes/brltty.toml TOML · 175 lines · 11.7 KB History raw

accesibilidad: el BRAILLE, con displays y contracción 1c2c5a6db · Sergio ·

1# brltty 6.9.1 — el driver de DISPLAYS BRAILLE. Cierra el hueco de accesibilidad para quien no ve
2# y no usa voz.
3#
4# ══ POR QUÉ ES SU PROPIO FRENTE, Y NO «lo mismo que la voz» ════════════════════════════════════
5# La voz y el braille no son alternativas de gusto. Braille es lo que permite leer código,
6# ortografía, tablas y matemáticas —cosas donde escuchar no alcanza— y es el único camino para quien
7# además no oye. Una distro con voz y sin braille deja afuera a sordociegos por completo.
8#
9# brltty lee la pantalla (la consola de Linux y, vía BrlAPI, las apps) y la escribe en el display.
10# Trae **42 drivers de braille** para hardware de distintos fabricantes.
11#
12# ══ LAS PERILLAS QUE IMPORTAN ══════════════════════════════════════════════════════════════════
13#   --enable-api        **BrlAPI**: el protocolo por el que una aplicación —`orca`, un editor— toma
14#                       el display en vez de dejárselo a la lectura de pantalla. Sin esto brltty
15#                       sirve para la consola y nada más
16#   --enable-liblouis   braille CONTRAÍDO. Sin liblouis es una celda por carácter: legible, tres
17#                       veces más largo, y nadie lee así un texto. Ver `recipes/liblouis.toml`
18#   --disable-x         la distro es Wayland-only
19#   --disable-icu       `icu` no está en el corpus. Lo que se pierde es normalización Unicode fina
20#                       en la conversión de texto; `--enable-iconv` cubre el caso general
21#   --disable-polkit    no hay polkit en esta pila
22#   --disable-gpm       el ratón de consola; no está en el corpus
23#
24# ⚠ **`--disable-python-bindings`, Y ES UNA PÉRDIDA CONCRETA QUE SE DICE EN VEZ DE DISIMULARSE.**
25# El binding es un `.pyx` y necesita **Cython** (`Bindings/Python/bindings.m4:108`:
26# `AC_PATH_PROGS([CYTHON], [cython3 cython])`), que **no está en el corpus ni en ninguna cola**
27# (comprobado). Y el `configure` sólo emite un `AC_MSG_WARN` si falta: o sea que **sin apagarlo
28# explícitamente el binding se salta EN SILENCIO** y el artefacto sale igual.
29#
30# Lo que eso bloquea, concreto: `orca` importa el módulo `brlapi` de Python para manejar el
31# display. ⇒ con esta receta brltty funciona para la CONSOLA y para cualquier app que use BrlAPI en
32# C, pero **orca no podrá usar braille hasta que exista una receta de `cython`**. Se apaga a
33# propósito para que el día que alguien lo necesite el motivo esté escrito, en vez de descubrir un
34# hueco que nadie decidió.
35#
36# Los otros bindings (java, lisp, lua, ocaml, tcl, emacs) se apagan por lo mismo: sus lenguajes no
37# están en el corpus y el `configure` los saltaría sin avisar.
38#
39# ⚠ `--sysconfdir=/etc`: con `--prefix=/usr` a secas autotools deriva `/usr/etc` en SILENCIO, y el
40# binario hornea esa ruta — el artefacto queda auto-consistente y la configuración, donde nadie la
41# busca. Pasó con `speech-dispatcher` el mismo día; 31 recetas del repo ya lo pasan.
42#
43# ✅ **`--enable-i18n` CON las nueve traducciones, incluida `ar.po` — y eso es MEDIDO, no un
44# descuido.** Este repo tiene documentado que el `msgfmt` de `gettext-tiny` muere con el árabe
45# (SIGILL y un `.mo` de 0 bytes), así que iba a parchear `ar.po` fuera. Antes lo probé: el
46# `ar.po` de brltty **compila bien** (rc=0, `.mo` de 67 300 bytes), igual que `fr` y `zh`. La nota
47# de la memoria vale para un caso concreto de plurales que este fichero no dispara. *Una memoria
48# describe lo que era cierto cuando se escribió; se verifica antes de actuar sobre ella.*
49name    = "brltty"
50version = "6.9.1"
51license = "LGPL-2.1-or-later"
52
53[source]
54# ⚠ El tarball OFICIAL de brltty.app, no el archive del tag de GitHub: el del tag trae sólo
55# `configure.ac` y el lab no tiene autoconf ni automake. Tercera vez que mirar si upstream publica
56# un tarball de release ahorra escribir un autoconf.
57tarball = "https://brltty.app/archive/brltty-6.9.1.tar.xz"
58sha256  = "cf4619ce1471690e4ecc5544ee6289cef6c5bdf5855a1ac8dcc63f5beedf108d"
59
60[build]
61compiler = "zig-cc"
62target   = "x86_64-linux-musl"
63link     = "dynamic"
64flags    = []
65
66[build.phases]
67configure = '''
68set -e
69[ -f ./configure ] || { echo "brltty: el tarball no trae ./configure — ¿se cambió por el archive del tag?" >&2; exit 1; }
70# ⚠ **PARCHE: el `msgfmt` de `gettext-tiny` no soporta la opción LARGA `--output-file`.**
71# `Messages/Makefile.in:57` invoca así:
72#
73#     $(MSGFMT) --output-file $@ -- <fichero>.po
74#     ⇒ fopen: No such file or directory          … y **sale con rc=0**
75#
76# Medido aislando cada parte: con `-o` el mismo `ar.po` compila (67 300 bytes); con `--output-file`
77# falla, y falla igual el francés. O sea que **no es el idioma, es la opción**, y `ar.po` sólo era
78# el primero por orden alfabético.
79#
80# ⚠ **Y me equivoqué antes de llegar acá, en dos pasos que vale anotar.** (1) Este repo tiene
81# documentado que el msgfmt de gettext-tiny muere con el árabe, así que iba a quitar `ar.po`; probé
82# primero y «compilaba bien» — cierto, pero con `-o`, que **no es la invocación que usa el build**.
83# Verifiqué el fichero correcto con el comando equivocado. (2) El tool devuelve **rc=0 mientras no
84# escribe nada**: si `make` no comprobara que el `.mo` existe, esto habría pasado en silencio. Es la
85# misma familia que el `INSTALL_ROOT` de abajo — *un fallo que sale con éxito.*
86#
87# ⇒ Se cambia a `-o`, que gettext-tiny sí entiende, y así entran **las nueve traducciones** en vez
88# de perderlas con `--disable-i18n`. El hueco de `gettext-tiny` es real y va a morder a otras
89# recetas; barrerlo es su propia unidad de trabajo, no algo que se hace de paso.
90MF=Messages/Makefile.in
91grep -q -- '--output-file' "$MF" || { echo "brltty: $MF ya no usa --output-file; el parche de gettext-tiny sobra o cambió de forma — REVISAR" >&2; exit 1; }
92sed -i 's/--output-file \$@ --/-o $@/' "$MF"
93grep -q -- '--output-file' "$MF" && { echo "brltty: el parche de --output-file no se aplicó" >&2; grep -n 'MSGFMT' "$MF" >&2; exit 1; }
94grep -q -- '-o \$@' "$MF" || { echo "brltty: tras el parche no aparece '-o \$@' en $MF" >&2; grep -n 'MSGFMT' "$MF" >&2; exit 1; }
95echo "brltty: msgfmt pasa a la opción corta (gettext-tiny no entiende --output-file)"
96
97# ⚠ `-Wno-error=date-time`: `Headers/spk_driver.h:52` y `scr_driver.h:46` usan `__DATE__`/`__TIME__`
98# y **el lab compila con `-Werror=date-time`** — su política de reproducibilidad, que acá hizo
99# exactamente su trabajo y paró el build en los drivers de voz y de pantalla.
100#
101# Desactivarlo es SEGURO **porque el sandbox exporta `SOURCE_DATE_EPOCH=1`**: con esa variable
102# definida clang hace que `__DATE__`/`__TIME__` rindan esa fecha fija en vez de la del reloj, así
103# que el binario sigue siendo determinista. Sin `SOURCE_DATE_EPOCH` esto sería hornear la hora del
104# build dentro del artefacto, que es justo lo que el warning previene. Mismo razonamiento y misma
105# cura que `fastfetch`, `cairo` y `appstream` en este repo — no es una excepción nueva.
106CFLAGS="${CFLAGS:-} -Wno-error=date-time" \
107./configure --build=$CBUILD --host=$CHOST --prefix=/usr --sysconfdir=/etc \
108  --enable-api --enable-liblouis --enable-i18n --enable-iconv --enable-expat \
109  --disable-x --disable-icu --disable-polkit --disable-gpm \
110  --disable-python-bindings --disable-java-bindings --disable-lisp-bindings \
111  --disable-lua-bindings --disable-ocaml-bindings --disable-tcl-bindings \
112  --disable-emacs-bindings
113'''
114compile = 'make -j"$(nproc)"'
115# El guardián se escribe contra lo que el `install` de upstream PROMETE —leído en
116# `Programs/Makefile.in:1199`: programas, tablas, drivers, cabeceras, mensajes, el `.pc` y la
117# API— y busca por PATRÓN y no por ruta exacta, para no rechazar un build correcto por haberme
118# equivocado de directorio. Es la lección de los cuatro guardianes demasiado estrictos del 20-oct.
119install = '''
120set -e
121# ⚠ **`INSTALL_ROOT` Y NO `DESTDIR`, Y ESTO ESTUVO A UN PASO DE SELLAR UN ARTEFACTO VACÍO.**
122# `common.mk` de brltty no menciona `DESTDIR` **ni una vez** (medido): usa su propia variable,
123# `INSTALL_ROOT`, para prefijar cada directorio de instalación. El sandbox exporta `DESTDIR=/out`
124# para todos, así que la forma habitual pasa inadvertida — y acá era un no-op:
125#
126#     /usr/bin/install -c -d /usr/bin
127#     /usr/bin/install -c -d /usr/libexec/brltty
128#     install: cannot create directory '/usr/libexec/brltty': Value too large for data type
129#
130# Estaba instalando **en la raíz del sandbox**, no en `/out`. Falló sólo porque el overlay no lo
131# dejó escribir. **Si lo hubiera dejado, el build habría terminado con éxito y `/out` vacío** — y
132# un directorio vacío en el store no es un artefacto, es un nombre: se sella, es un cache-hit, y el
133# fallo llega hasta el final diciendo que todo fue bien. Es exactamente la regla 3 del repo, y la
134# única razón de que no pasara fue el permiso.
135#
136# ⇒ Corolario para cualquier receta nueva: **que `make install` no falle no prueba que haya
137# instalado donde creés.** El guardián de abajo lo comprueba igual, buscando los ficheros en `/out`.
138make install INSTALL_ROOT=/out
139b=$(find /out -name brltty -type f -perm -u+x 2>/dev/null | head -1)
140[ -n "$b" ] || { echo "brltty: no quedó el binario — NO sello" >&2; find /out -maxdepth 4 -type f -perm -u+x 2>/dev/null | head -20 >&2; exit 1; }
141
142# ⚠ EL CONTROL DECISIVO: que liblouis esté CABLEADA de verdad.
143# `--enable-liblouis` no garantiza nada por sí solo: brltty la busca por pkg-config y le pide la
144# variable `tablesdir` para hornearla como `LOUIS_TABLES_DIRECTORY` (`configure.ac:1214-1220`). Si
145# el `.pc` no definiera `tablesdir`, el valor quedaría VACÍO, el build saldría igual y brltty
146# tendría «soporte de braille contraído» sin saber dónde están las tablas — sellado, con contenido
147# y sin la función. Se comprueba en el BINARIO, que es donde el valor vive:
148strings "$b" 2>/dev/null | grep -q 'liblouis/tables' || {
149  echo "brltty: el binario no trae la ruta de tablas de liblouis — el braille CONTRAÍDO no funcionaría, y sin error" >&2
150  strings "$b" 2>/dev/null | grep -i louis | head -5 >&2
151  exit 1
152}
153
154# BrlAPI: sin esto ninguna aplicación puede tomar el display.
155api=$(find /out -name 'libbrlapi.so*' -o -name 'libbrlapi.a' 2>/dev/null | head -1)
156[ -n "$api" ] || { echo "brltty: no quedó libbrlapi — ninguna app podría manejar el display, sólo la consola" >&2; exit 1; }
157
158# Los drivers: 42 en el árbol. El piso es bajo a propósito —según cómo se enlacen pueden quedar
159# dentro del binario en vez de como módulos— pero CERO ficheros de datos de driver sí es un fallo.
160drv=$(find /out -name 'libbrltty*.so' 2>/dev/null | wc -l)
161# Las tablas de texto y de contracción propias de brltty.
162tbl=$(find /out -path '*brltty*' \( -name '*.ttb' -o -name '*.ctb' -o -name '*.ktb' -o -name '*.tti' \) 2>/dev/null | wc -l)
163[ "$tbl" -gt 50 ] || { echo "brltty: sólo $tbl tabla(s) propias — esperaba >50; sin ellas no sabe traducir a celdas" >&2; find /out -path '*brltty*' -name '*.ttb' 2>/dev/null | head -5 >&2; exit 1; }
164# La herramienta de tablas de contracción: es lo que prueba que ese camino se construyó.
165[ -n "$(find /out -name 'brltty-ctb' -type f 2>/dev/null | head -1)" ] || { echo "brltty: falta brltty-ctb — el compilador de tablas de contracción no se construyó" >&2; exit 1; }
166echo "brltty: binario + brlapi + $drv driver(s) externo(s) + $tbl tabla(s) + liblouis cableada"
167'''
168
169[deps]
170build = ["make", "pkgconf", "liblouis", "ncurses", "expat", "alsa-lib",
171         "gettext-tiny", "libtool", "python3",
172         # ⚠ `binutils` por el GUARDIÁN (aporta `strings`), no por el build: sin declararlo el
173         # control de liblouis fallaría por falta de herramienta y acusaría a la receta de algo que
174         # no hizo. Misma nota que `espeak-ng` y `speech-dispatcher`.
175         "binutils"]