cosmic: la calculadora del lanzador ANDA — el stdin de qalc era el stdout
=123*456 → 56088 en el lanzador. libqalculate re-sellado b3:edb8d14d. La causa del «no lee nada de la tubería» no era readline, ni el toolchain, ni la versión: el binario salía DINÁMICO pese a link="static", porque libtool se come el -static que inyecta el harness. Y en un musl dinámico stdin, stdout y stderr se resolvieron por copy relocation a UNA SOLA ranura de BSS compartida —las tres en la misma dirección—, así que fileno(stdin) daba 1: el stdin del programa era el stdout. Eso explica la asimetría que parecía absurda, que qalc -f /dev/stdin funcionara (abre el fd por RUTA, sin tocar el FILE* roto) y qalc leyendo stdin no. Fix: make LDFLAGS="-all-static -no-pie", el mismo par que ya usa libxml2. Con él los tres símbolos vuelven a tener direcciones distintas en .rodata. Regla para el runbook: link="static" en la receta NO garantiza un binario estático — readelf -d y nm -S | grep ' std' lo contestan en dos segundos. Segundo muro: qalc pregunta si activar autocalc antes de leer nada, el plugin le manda la expresión y cierra, la expresión se consume como respuesta y qalc nunca llega a guardar config ⇒ vuelve a preguntar siempre. Se siembra qalc.cfg desde cosmic-start, política de imagen como el color de fondo. Y hay que repetir el -L de los alias de curses en el make: el LDFLAGS del make pisa al del configure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -108,7 +108,7 @@ Más `cosmic-settings-daemon` y `xdg-desktop-portal-cosmic` fuera de esa lista.
|
||||
| **`cosmic-applets`** (19 binarios en uno) | ✅ **sellado** (necesitó `dbus-shared`, ver gotcha 10) | `b3:3e53a325` |
|
||||
| `pop-launcher` 1.2.7 (otro repo, ver abajo) | ✅ sellado a la primera | `b3:64a5cbaa` |
|
||||
| `gmp` 6.3.0 · `mpfr` 4.2.2 (cadena de la calculadora) | ✅ sellados a la primera | `b3:d99a0a5d` · `b3:13982d20` |
|
||||
| `libqalculate` 5.12.0 (`qalc`) | ✅ sellado — **pero el plugin del lanzador no lo puede usar, ver abajo** | `b3:6bb435a7` |
|
||||
| `libqalculate` 5.12.0 (`qalc`) | ✅ sellado — la calculadora del lanzador ANDA (ver abajo) | `b3:edb8d14d` |
|
||||
|
||||
**La cola está COMPLETA: 30 recetas, `escritorio-cosmic` 68/68.**
|
||||
|
||||
@@ -481,38 +481,66 @@ plugin, que contesta «qalc command is not installed»**. Esa respuesta es la me
|
||||
disponible: el proceso hijo corrió, evaluó la consulta y devolvió una fila. Lo que falta ahora es
|
||||
`libqalculate` (el binario `qalc`), que es un paquete, no un problema.
|
||||
|
||||
### 🧮 `libqalculate`: empaquetado y andando, e inservible para el plugin
|
||||
### 🧮 `libqalculate`: la calculadora del lanzador, y un `stdin` que era `stdout`
|
||||
|
||||
`qalc` está sellado y **funciona**: `qalc -t '2+2'` → `4`, `-f fichero`, y el modo interactivo sobre
|
||||
una terminal calcula perfecto (`123 × 456 = 56088`). La cadena que baja desde una tecla —`Super` →
|
||||
cosmic-launcher → pop-launcher → plugin `calc` → `qalc` → **mpfr → gmp**— está entera en el catálogo.
|
||||
**`=123*456` → `56088` en el lanzador** (`cosmic-calculadora-qemu-2026-08-04.png`). La cadena entera
|
||||
desde una tecla está en el catálogo: `Super` → cosmic-launcher → pop-launcher → plugin `calc` →
|
||||
`qalc` → **mpfr → gmp**.
|
||||
|
||||
**Y aun así el lanzador sigue mostrando una fila vacía.** El plugin no le pasa la cuenta por argv:
|
||||
arranca `qalc` SIN expresión, con stdin y stdout en tubería, le ESCRIBE la expresión y cierra. Ese
|
||||
modo, en nuestro binario, no lee nada. Acotado con dos invocaciones que sólo difieren en cuándo llega
|
||||
el EOF:
|
||||
Pero el camino hasta ahí tuvo dos muros que vale la pena dejar escritos, porque ninguno se parecía a
|
||||
lo que era.
|
||||
|
||||
```sh
|
||||
{ printf '123*456\n'; sleep 3; } | qalc # LEE (aparece la pregunta de primer arranque)
|
||||
printf '123*456\n' | qalc # NO lee NADA: imprime el prompt y sale con rc=0
|
||||
**1) `stdin` apuntaba al descriptor 1.** El plugin no le pasa la cuenta por argv: arranca `qalc` SIN
|
||||
expresión, con stdin en tubería, le escribe la expresión y cierra. En ese modo el binario **no leía
|
||||
nada** — ni error ni resultado, la fila del lanzador salía en blanco. El síntoma acusaba a readline,
|
||||
al toolchain y a la versión, y no era ninguno:
|
||||
|
||||
```
|
||||
DIAG-main isatty=0 feof=0 ferror=0 fd=1 ← fileno(stdin) == 1
|
||||
nm -S qalc | grep -E ' (stdin|stdout|stderr)$'
|
||||
1847148 8 B stderr
|
||||
1847148 8 B stdin ← las TRES en la misma dirección
|
||||
1847148 8 B stdout
|
||||
```
|
||||
|
||||
O sea: **con el EOF ya pendiente en un stdin que no es terminal, `readline()` devuelve NULL antes de
|
||||
entregar la línea que sí está en el búfer** — y así es exactamente como lo invoca el plugin.
|
||||
La causa: **el binario salía DINÁMICO aunque la receta dice `link = "static"`, porque libtool se come
|
||||
el `-static` que inyecta el harness** ([[link-static-mentira-libtool]] otra vez, cuarto caso). Y en
|
||||
un musl dinámico las tres variables de stdio se resolvieron por *copy relocation* a **una sola ranura
|
||||
de BSS compartida**: la última que escribe el loader gana, así que el `stdin` del programa era el
|
||||
`stdout`. De ahí la asimetría que parecía absurda: `qalc -f /dev/stdin` funcionaba —abre el
|
||||
descriptor por RUTA, sin tocar el `FILE*` roto— y `qalc` leyendo `stdin` no.
|
||||
|
||||
Lo que ya se DESCARTÓ midiendo, para que nadie lo repita:
|
||||
- **No es el toolchain.** Una sonda estática musl del propio sandbox (C y C++) lee la tubería sin
|
||||
problema. El binario no tiene nada raro: un solo `NEEDED`, `libc.so`.
|
||||
- **No es readline vs no-readline.** Sin readline es peor (no lee nunca, ni con la tubería abierta);
|
||||
con readline al menos lee cuando el escritor no ha cerrado.
|
||||
- **No es la versión de readline.** Se construyó una 8.3 como sombra de cola y el síntoma no se
|
||||
movió; la sombra se descartó en vez de dejar una receta duplicada que no arregla nada.
|
||||
- **No es el descriptor 0.** `qalc -f /dev/stdin` —el MISMO pipe, reabierto por ruta— sí funciona.
|
||||
El que no sirve es el `FILE*` `stdin`.
|
||||
El fix es el par que ya usa `libxml2`: `make LDFLAGS="-all-static -no-pie"`. Con él el binario queda
|
||||
estático de verdad y los tres símbolos vuelven a tener direcciones distintas, en `.rodata`:
|
||||
|
||||
La pista que queda es justamente esa última asimetría. Y el aviso de método: **empaquetar el binario
|
||||
que falta no garantiza que el consumidor lo pueda usar** — «qalc no está instalado» y «qalc está y no
|
||||
contesta» son dos estados distintos, y el segundo se ve peor porque la fila sale en blanco.
|
||||
```
|
||||
11e71c8 8 R stderr
|
||||
11e71d0 8 R stdin
|
||||
11e71d8 8 R stdout
|
||||
```
|
||||
|
||||
**La regla, y es de las caras: `link = "static"` en la receta no garantiza un binario estático.**
|
||||
Cuando algo se comporta como si su `stdin`/`stdout` estuvieran cruzados, `readelf -d` y
|
||||
`nm -S | grep ' std'` contestan en dos segundos lo que el log no dice nunca.
|
||||
|
||||
**2) La pregunta de primer arranque se come la cuenta, SIEMPRE.** Antes de leer nada, `qalc` pregunta
|
||||
si activar `autocalc`. El plugin le manda la expresión y cierra: la expresión se consume como
|
||||
respuesta, no es un sí/no válido, y qalc **no llega a guardar config** ⇒ la próxima vez vuelve a
|
||||
preguntar. No es «falla la primera vez»: no anda nunca. Se siembra
|
||||
`~/.config/qalculate/qalc.cfg` con `calculate_as_you_type=0` desde `cosmic-start` — política de la
|
||||
imagen, como el color de fondo; una distro de verdad lo pondría en `/etc/skel`.
|
||||
|
||||
**Gotchas de empaquetado de la cadena:**
|
||||
- **`gmp` va con `--disable-assembly`.** Elige rutinas en ensamblador mirando la CPU de quien
|
||||
compila, o sea hornearía la ISA del laptop en el artefacto y el hash dejaría de significar lo mismo
|
||||
en la granja. Es una calculadora de escritorio: la implementación en C portable sobra.
|
||||
- **El configure de libqalculate no encuentra readline** porque prueba `-lreadline` junto a
|
||||
`-lncurses`, `-lcurses`, `-ltermcap` y `-ltinfo`, y el corpus **sólo empaqueta `libncursesw.a`**.
|
||||
Que el paquete se llame `ncurses` no significa que provea `-lncurses`. Los alias van en un
|
||||
directorio LOCAL (`.curses-compat/`) y no en `/usr/lib`: esa vista es la evidencia de qué se
|
||||
declaró, y ensuciarla para que pase un test deja mintiendo justo al mecanismo que existe para no
|
||||
mentir. Ojo: hay que repetir el `-L` en el `make`, porque el `LDFLAGS` del `make` PISA al del
|
||||
`configure`.
|
||||
|
||||
### ⏱ El panel tiene un DEADLINE de arranque: con 4 vCPU sale mutilado
|
||||
|
||||
@@ -530,9 +558,9 @@ El número de procesos no distingue «arrancó» de «dibujó». El framebuffer
|
||||
|
||||
## Lo que falta, en orden
|
||||
|
||||
1. **Aplicaciones.** No hay ni una: los 20 `.desktop` de la imagen son `NoDisplay=true`. El primer
|
||||
candidato barato es `libqalculate` (el binario `qalc`), que es lo único que le falta al plugin de
|
||||
la calculadora para dar un resultado en vez de decir que no está.
|
||||
1. **Aplicaciones con ventana.** Sigue sin haber ninguna: los 20 `.desktop` de la imagen son
|
||||
`NoDisplay=true`, así que la biblioteca sale vacía y eso es correcto. La calculadora del lanzador
|
||||
ya da resultados, pero es una fila de texto, no una app. `cosmic-term` sería la primera de verdad.
|
||||
2. `xdg-desktop-portal-cosmic` — sin él no hay captura de pantalla, ni file-chooser, ni compartir.
|
||||
3. `cosmic-settings` (el panel de control) y `cosmic-files`: la suite tiene aplicaciones y el
|
||||
catálogo todavía no.
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
"totals": {
|
||||
"recipes": 800,
|
||||
"nodes": 800,
|
||||
"sealed": 797,
|
||||
"never": 2,
|
||||
"debt": 1
|
||||
"sealed": 798,
|
||||
"never": 2
|
||||
},
|
||||
"by_class": {
|
||||
"c": 160,
|
||||
@@ -15,7 +14,7 @@
|
||||
"rust": 241
|
||||
},
|
||||
"debt_by_class": {
|
||||
"c": 3
|
||||
"c": 2
|
||||
},
|
||||
"by_queue": {
|
||||
"corpus": {
|
||||
@@ -23,8 +22,7 @@
|
||||
"never": 2
|
||||
},
|
||||
"incoming-cosmic": {
|
||||
"sealed": 29,
|
||||
"debt": 1
|
||||
"sealed": 30
|
||||
}
|
||||
},
|
||||
"by_profile": {
|
||||
@@ -41,8 +39,7 @@
|
||||
"escritorio-cosmic": {
|
||||
"raices": 20,
|
||||
"clausura": 68,
|
||||
"sealed": 67,
|
||||
"debt": 1
|
||||
"sealed": 68
|
||||
},
|
||||
"escritorio-mirada": {
|
||||
"raices": 14,
|
||||
@@ -4898,7 +4895,7 @@
|
||||
"hash": "b3:d99a0a5d6fb0e301523c3797d899e7c1002c58f282865df87e221b4e47fd0642",
|
||||
"state": "sealed",
|
||||
"blocked_by": [],
|
||||
"unblocks": 1,
|
||||
"unblocks": 0,
|
||||
"perfiles": [
|
||||
"escritorio-cosmic"
|
||||
],
|
||||
@@ -8228,8 +8225,8 @@
|
||||
],
|
||||
"cls": "c",
|
||||
"queue": "incoming-cosmic",
|
||||
"hash": "b3:fcf9c6c097f9f37235319d52dbe64e42deaa012cc374aee206f9c5d2201ae3ac",
|
||||
"state": "debt",
|
||||
"hash": "b3:edb8d14db8e625168dea50e40073840b29a6800d7c5b027bbf01f17f15fd5b68",
|
||||
"state": "sealed",
|
||||
"blocked_by": [],
|
||||
"unblocks": 0,
|
||||
"perfiles": [
|
||||
@@ -8452,7 +8449,7 @@
|
||||
"hash": "b3:c4c65c4b17b86211c4a7f076e6693aedb9168d72cc8e45a4a9022fdd75f79494",
|
||||
"state": "sealed",
|
||||
"blocked_by": [],
|
||||
"unblocks": 1,
|
||||
"unblocks": 0,
|
||||
"perfiles": [
|
||||
"escritorio-cosmic",
|
||||
"escritorio-gnome"
|
||||
@@ -8804,7 +8801,7 @@
|
||||
"hash": "b3:fbad44acdc76df4b081cccd3cc02666664b6d1a03cd6fa482f85791fa533a602",
|
||||
"state": "sealed",
|
||||
"blocked_by": [],
|
||||
"unblocks": 2,
|
||||
"unblocks": 1,
|
||||
"perfiles": [
|
||||
"base",
|
||||
"cli",
|
||||
@@ -9471,7 +9468,7 @@
|
||||
"hash": "b3:13982d20e404affb9ab825c157a50efc2f0370e1befe75cb7ce93b914d55d497",
|
||||
"state": "sealed",
|
||||
"blocked_by": [],
|
||||
"unblocks": 1,
|
||||
"unblocks": 0,
|
||||
"perfiles": [
|
||||
"escritorio-cosmic"
|
||||
],
|
||||
@@ -9695,7 +9692,7 @@
|
||||
"hash": "b3:a3be97622d20cd8d831a25403e00eccb23f2585ed78670a4e12d6cbe519fb8ec",
|
||||
"state": "sealed",
|
||||
"blocked_by": [],
|
||||
"unblocks": 1,
|
||||
"unblocks": 0,
|
||||
"perfiles": [
|
||||
"base",
|
||||
"cli",
|
||||
@@ -10617,7 +10614,7 @@
|
||||
"hash": "b3:f0b5d0b1cb4321b3c61f24a871b9a58da3ebb7eb903af4015e35bd41a6465437",
|
||||
"state": "sealed",
|
||||
"blocked_by": [],
|
||||
"unblocks": 1,
|
||||
"unblocks": 0,
|
||||
"perfiles": [
|
||||
"base",
|
||||
"cli",
|
||||
@@ -11053,7 +11050,7 @@
|
||||
"hash": "b3:03c0eb9ccaf42a65d876c0778b7ee53695f6389bbe5c4c9bcf606f8aa328ec36",
|
||||
"state": "sealed",
|
||||
"blocked_by": [],
|
||||
"unblocks": 1,
|
||||
"unblocks": 0,
|
||||
"perfiles": [
|
||||
"base",
|
||||
"cli",
|
||||
|
||||
@@ -69,8 +69,17 @@ for a in libncurses libcurses libtinfo libtermcap; do ln -sf /usr/lib/libncurses
|
||||
--disable-nls \
|
||||
LDFLAGS="$LDFLAGS -L$PWD/.curses-compat"
|
||||
'''
|
||||
compile = 'make -j"$(nproc)"'
|
||||
install = 'make DESTDIR=/out install'
|
||||
# `-all-static` NO ES REDUNDANTE con `link = "static"`, y esa confusión costó todo un frente.
|
||||
# El harness inyecta `LDFLAGS=-static`, pero **libtool se lo come**: la línea de enlace real de `qalc`
|
||||
# salía dinámica contra `libc.so`. Y un musl DINÁMICO acá no es sólo «pesa distinto»: `stdin`,
|
||||
# `stdout` y `stderr` terminaron **en la misma dirección de BSS**, las tres compartiendo una única
|
||||
# ranura de copy-relocation, así que el `stdin` del programa era en realidad el `stdout`
|
||||
# (`fileno(stdin)` = 1). De ahí que `qalc` no leyera NADA de una tubería mientras `-f /dev/stdin`
|
||||
# —que abre el descriptor por ruta, sin tocar el FILE* roto— funcionaba perfecto.
|
||||
# `-all-static` es la forma de decírselo a libtool; `-no-pie` va con él (un estático PIE no tiene
|
||||
# sentido). Mismo par que usa `libxml2` en el corpus, por la misma razón.
|
||||
compile = 'make LDFLAGS="-all-static -no-pie -L$PWD/.curses-compat" -j"$(nproc)"'
|
||||
install = 'make DESTDIR=/out install LDFLAGS="-all-static -no-pie -L$PWD/.curses-compat"'
|
||||
|
||||
[deps]
|
||||
build = ["make", "gmp", "mpfr", "libxml2", "pkgconf", "readline", "ncurses"]
|
||||
|
||||
@@ -157,6 +157,19 @@ RON
|
||||
say "fondo: color liso (el wallpaper por defecto vive en git-lfs y no se empaqueta)"
|
||||
fi
|
||||
|
||||
# ── SEMILLA DE CONFIG DE qalc, SIN LA CUAL LA CALCULADORA DEL LANZADOR NUNCA ANDA ────────────────
|
||||
# En el primer arranque `qalc` hace una PREGUNTA interactiva («¿activar autocalc?») antes de leer
|
||||
# nada. El plugin `calc` de pop-launcher le escribe la expresión y cierra el pipe, así que la
|
||||
# expresión se consume como respuesta, no es un sí/no válido, y qalc **no llega a guardar config** ⇒
|
||||
# la próxima vez vuelve a preguntar. O sea que sin sembrar esto no falla una vez: falla SIEMPRE.
|
||||
# Es política de la imagen, no del paquete —igual que el color de fondo—: una distro de verdad lo
|
||||
# pondría en el esqueleto de /etc/skel.
|
||||
if [ ! -f "$HOME/.config/qalculate/qalc.cfg" ]; then
|
||||
mkdir -p "$HOME/.config/qalculate"
|
||||
printf '[General]\ncalculate_as_you_type=0\n' > "$HOME/.config/qalculate/qalc.cfg"
|
||||
say "qalc: config sembrada (si no, la pregunta de primer arranque se come la cuenta)"
|
||||
fi
|
||||
|
||||
# ── MODO: bare (default) o session ──────────────────────────────────────────────────────────────
|
||||
# `cosmic-session` es el camino de producción, pero HOY no se puede usar: llama a
|
||||
# `cosmic-settings-daemon` con `.expect("failed to start settings daemon")` (src/main.rs:255) y
|
||||
|
||||
Reference in New Issue
Block a user