# libqalculate — la calculadora que le falta al lanzador. El plugin `calc` de pop-launcher no calcula # nada por su cuenta: arma una línea y se la pasa al binario **`qalc`**, que es de este paquete. Sin # él, tecleando `=2+2` el lanzador contesta —correctamente y sin fallar— «qalc command is not # installed». Es el primer paquete del catálogo que existe para que una TECLA del escritorio dé un # resultado, no para que otra librería enlace. # # ── LA CADENA QUE NADIE ADIVINA MIRANDO ARRIBA ────────────────────────────────────────────────── # `Super` → cosmic-launcher → pop-launcher → plugin calc → qalc → libqalculate → **mpfr → gmp**. # Seis saltos desde una tecla hasta la aritmética de precisión arbitraria, y los dos últimos son # obligatorios: el configure corta con «libgmp not found» y «libmpfr not found or uses a different # ABI». Por eso [[gmp]] y [[mpfr]] entraron primero. # # ── LO QUE SE APAGA, Y POR QUÉ CADA UNO ───────────────────────────────────────────────────────── # · `--without-libcurl`: es para BAJARSE tipos de cambio de internet. Un paquete de una distro # reproducible no tiene por qué traer un cliente HTTP para sumar; y la clausura se ahorra curl # entero. Las tasas quedan las del fichero de definiciones, que es lo honesto: un dato con fecha. # · `--without-icu`: sólo aporta comparación de cadenas Unicode insensible a mayúsculas. Traería # ICU —decenas de MB de tablas— para que `SIN` funcione igual que `sin`. # · `--disable-nls`: no hay locales en la imagen (los clientes ya avisan «failed to get system # locale, falling back to en-US»), así que gettext sólo agregaría dependencia sin traducir nada. # # ── ⚠ READLINE NO ES OPCIONAL ACÁ, Y ESO SE MIDIÓ ─────────────────────────────────────────────── # Yo había razonado que era indiferente «porque el plugin usa qalc de forma no interactiva». **Es # falso, y el código del plugin lo dice**: `Command::new("qalc")` sin expresión, con `stdin` en pipe, # le ESCRIBE la expresión por stdin y descarta las dos primeras líneas de stdout. O sea que lo usa en # modo INTERACTIVO con stdin redirigido — el modo en que `-t ` no participa. # Sin readline ese modo no funciona: el binario imprime el prompt `>` y no evalúa nada, así que la # fila del lanzador sale VACÍA (no «no está instalado»: está, y no contesta). Con readline el bucle # de entrada es el que espera el plugin. # La lección es la de siempre en esta campaña, otra vez: **la dep no se deduce de para qué sirve el # paquete, se lee de cómo lo INVOCA quien lo usa.** «Es una calculadora, la llamarán con la cuenta # en argv» era una suposición, no una medición. name = "libqalculate" version = "5.12.0" license = "GPL-2.0-or-later" [source] tarball = "https://github.com/Qalculate/libqalculate/releases/download/v5.12.0/libqalculate-5.12.0.tar.gz" sha256 = "f3dfdcf97d5a9e3a5bc0ebe66afd184721b606276eee3ba0ada8c92a5e71d44c" [build] # C++ de verdad (la librería entera lo es), y con `compiler = "zig-cc"` el sandbox pone # CXX=takana-zig-cxx, o sea `zig c++` con la libc++ de LLVM enlazada ESTÁTICA. Eso es lo que evita # que el artefacto pida `libstdc++.so.6`/`libgcc_s.so.1` de Alpine — la deuda que la campaña # «matar gcc» viene pagando en el resto del árbol. compiler = "zig-cc" target = "x86_64-linux-musl" link = "static" flags = [] [build.phases] configure = ''' # ── ALIAS DE CURSES, PORQUE EL CORPUS SÓLO EMPAQUETA LA VARIANTE WIDE ─────────────────────────── # El configure de libqalculate busca readline probando `-lreadline` junto a `-lncurses`, `-lcurses`, # `-ltermcap` y `-ltinfo`, en ese orden. Nuestro `ncurses` instala **sólo `libncursesw.a`** (la # variante de caracteres anchos, que es la correcta y la única que hace falta), así que las cuatro # pruebas fallan con «unable to find static system library» y el configure concluye —sin error— que # no hay readline. Que el paquete se llame `ncurses` no significa que provea `-lncurses`. # Los alias van en un directorio LOCAL y no tocando `/usr/lib`: la vista de deps del sandbox es la # evidencia de qué se declaró, y ensuciarla para que un test pase deja mintiendo justo al mecanismo # que existe para no mentir. mkdir -p .curses-compat for a in libncurses libcurses libtinfo libtermcap; do ln -sf /usr/lib/libncursesw.a ".curses-compat/$a.a"; done ./configure \ --build=$CBUILD --host=$CHOST \ --prefix=/usr \ --disable-shared --enable-static \ --without-libcurl \ --without-icu \ --disable-nls \ LDFLAGS="$LDFLAGS -L$PWD/.curses-compat" ''' # `-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"]