# swayimg 5.6 — el VISOR DE IMÁGENES. Cierra un hueco que el censo marcaba 5 de 5 ausente: la # distro no tenía NINGUNA forma de abrir un JPEG. # # ══ POR QUÉ ESTE Y NO LOS POPULARES: SE DESCARTARON POR MEDICIÓN ═══════════════════════════════ # `nsxiv` es un fork de sxiv, **Xlib**. Esta distro es Wayland-only ⇒ muro, no candidato # `feh` idem, X11 # `imv` es el que todo el mundo recomienda para Wayland, y **no sirve acá**: sus # `dependency()` piden `egl`, `gl`, `opengl`, `glu` y `wayland-egl`, y este corpus **no # publica `libGL.so` ni `gl.pc`** (comprobado en el store; es el muro documentado de «sin # OpenGL de escritorio», el mismo que bloquea a `kitty`) # `swayimg` **cero menciones de GL** en todo su `meson.build` (medido). Pinta por software sobre # `wayland-client`, con fontconfig/freetype para el texto # # ⇒ La lección de método: en este corpus, «el visor de imágenes estándar para Wayland» no es una # recomendación transferible — hay que mirar si pide GL antes de escribir la receta. # # ══ SUS DEPS OBLIGATORIAS SON CINCO, Y TODAS ESTABAN ═══════════════════════════════════════════ # Leídas en su `meson.build`: `xkbcommon`, `fontconfig`, `freetype2`, `threads` y `wayland-client` # con `wayland-protocols >= 1.35` (tenemos 1.48). **Todo lo demás va detrás de una perilla**, # incluida `librsvg-2.0` — o sea que el bloqueo de GNOME no toca acá. # # ⚠ Con una excepción que casi no vi: `lua = dependency(get_option('liblua'))` **no es # condicional** — es obligatoria, y el nombre del módulo pkg-config sale de la opción. # # ⚠⚠ **Y ACÁ ME CORRIJO, PORQUE PISÉ TRABAJO AJENO.** Escribí esta receta con `cat >` **sin mirar # que ya existía**: otro agente la había llevado de 4.7 a 5.5, y mi versión borró 70 líneas suyas. # Entre ellas, la decisión de usar el default `luajit` — por eso ese agente había escrito # `recipes/luajit.toml`. Mi `-Dliblua=lua` dejó **su luajit sin un solo consumidor** (medido: # ningún `[deps]` del catálogo lo nombraba). # # ⇒ Vuelve a `luajit`, que es el default de upstream y lo que ese agente empaquetó para esto # (`luajit.pc`, `libluajit-5.1.{a,so}`, sellado al hash vigente). Lo que SÍ conservo de mi pasada es # `-Dexif=enabled` con `exiv2`: ellos lo tenían apagado, y sin EXIF las fotos verticales de móvil # salen tumbadas. Eso es una mejora, no una preferencia. # # La lección, que es la regla 2 del repo por otra puerta: **`cat >` sobre un fichero del repo # compartido es destructivo y no avisa.** El `git add` acotado no protege de esto — el fichero ya # estaba sobrescrito antes de llegar a git. # # ══ ⚠ TODAS LAS PERILLAS EXPLÍCITAS, Y ESO ES EL PUNTO DE ESTA RECETA ══════════════════════════ # Sus opciones de formato son `feature` con default **`auto`**: una dep ausente se **salta en # silencio** y el build sale bien. Eso es exactamente la figura que este catálogo persigue —un visor # sellado que no abre PNG y no te dice por qué—. ⇒ cada formato se fija `enabled` o `disabled`: # # ENCENDIDOS (la dep está en el corpus, y si faltara el build DEBE fallar): # png jpeg webp tiff gif los formatos que cubren casi todo lo que alguien abre # exif `exiv2`, y NO es un adorno: una cámara de móvil no rota los # píxeles, anota la orientación en EXIF. Sin esto **todas las fotos # verticales salen tumbadas**, sin error y sin remedio # wayland compositor la ventana normal # drm ⚠ el modo sin compositor: ver una imagen **desde una consola TTY**. # En una distro que arranca a texto esto no es exótico, es el caso de # «mirá esta captura antes de levantar el escritorio» # # APAGADOS, con el motivo: # svg `librsvg-2.0` sólo existe en `incoming-gnome`, enredada con su pila # de introspección; promoverla cuesta 35 recetas (medido). **Lo que se # pierde es abrir SVG**, que es real y queda dicho # heif avif jxl jp2 exr raw los formatos modernos y de cámara: `libheif`, `libavif`, `libjxl`, # sixel `openjpeg`, `OpenEXR`, `libraw`, `libsixel` NO están en el corpus # video `ffmpeg` está, pero reproducir vídeo es trabajo de `mpv`, que ya # viaja. Un visor de imágenes no necesita arrastrar esa cadena # tests `gtest` no está en el corpus name = "swayimg" version = "5.6" license = "MIT" [source] tarball = "https://github.com/artemsen/swayimg/archive/refs/tags/v5.6/swayimg-5.6.tar.gz" sha256 = "0f70cbc665217a747e8a098e1a881239e96df270930f47c262ab2ecff290e428" [build] compiler = "zig-cc" target = "x86_64-linux-musl" link = "dynamic" flags = [] [build.phases] # `-Dversion=5.6`: su default es `0.0.0` y lo hornea en `--version`. Dejarlo así daría un binario # que miente sobre qué es — y además haría imposible saber qué versión corre en una imagen. configure = ''' set -e # ⚠ **`--prefer-static` NO es una preferencia de tamaño: sin él el enlace NO CIERRA.** # El corpus es estático-primero, y `libfontconfig.a` referencia **11 símbolos `XML_*` sin definir** # (medido) porque su `.pc` declara `Requires.private: expat`. pkg-config sólo entrega las privadas # en modo estático; en meson eso es `--prefer-static`. Sin la bandera, lld cortó con los once: # # ld.lld: error: undefined symbol: XML_ParserCreate … (y 10 más) # # ⚠ Y esos once errores NO venían de `exiv2`, aunque al principio los atribuí ahí: expat entra en # `libexiv2` con visibilidad HIDDEN/LOCAL —correcto, no exporta la API de expat— y los símbolos # aparecen definidos. Venían de fontconfig desde el primer intento. Es la lección de # [[control-antes-que-precision]] por el lado del diagnóstico: el primer sospechoso plausible no es # el culpable, y la forma de saberlo es mirar QUIÉN tiene el símbolo sin definir. PKG_CONFIG_PATH=/usr/lib/pkgconfig meson setup output --prefix=/usr --buildtype=release \ --prefer-static \ -Dversion=5.6 \ -Dliblua=luajit \ -Dpng=enabled -Djpeg=enabled -Dwebp=enabled -Dtiff=enabled -Dgif=enabled \ -Dexif=enabled \ -Dwayland=enabled -Dcompositor=enabled -Ddrm=enabled \ -Dsvg=disabled -Dheif=disabled -Davif=disabled -Djxl=disabled -Djp2=disabled \ -Dexr=disabled -Draw=disabled -Dsixel=disabled -Dvideo=disabled \ -Dtests=disabled ''' compile = 'meson compile -C output' # El guardián no se conforma con que el binario exista: comprueba que los formatos que PEDIMOS # estén de verdad enlazados. Con perillas `auto` esto sería imprescindible; con las perillas fijas # meson ya habría fallado, así que acá es la segunda red — y la que detectaría que alguien vuelva a # poner `auto` sin darse cuenta. install = ''' set -e DESTDIR=/out meson install -C output [ -x /out/usr/bin/swayimg ] || { echo "swayimg: no quedó el binario — NO sello" >&2; exit 1; } # ⚠⚠ **EL GUARDIÁN SE COMPRUEBA POR SÍMBOLO DEFINIDO, NO POR `NEEDED` — y me costó una vuelta.** # Mi versión anterior exigía `libwayland-client`, `libxkbcommon` y `libdrm` en `NEEDED`, y rechazó un # build **correcto**: con `--prefer-static` el corpus entrega estáticas y el binario sale # autosuficiente. Medido sobre el artefacto real: # # readelf -d swayimg | grep NEEDED ⇒ libc.so ← y NADA MÁS # los once símbolos de abajo ⇒ todos DEFINIDOS # # O sea un visor de imágenes con **una sola** dependencia dinámica. Eso además hace que declararlo # en un perfil no cueste ningún proveedor compartido. # # ⇒ La regla, que ya pagué cinco veces hoy en recetas distintas: **un `NEEDED` no prueba que la # función esté, y su ausencia no prueba que falte.** Lo que prueba la capacidad es el símbolo # DEFINIDO. Y cuando el artefacto cambia de forma (compartido → estático), el guardián tiene que # cambiar con él o se convierte en un rechazo de builds buenos. definido() { readelf -sW "$1" 2>/dev/null | awk -v s="$2" '$8==s && $7!="UND" {f=1} END{exit !f}' } falta="" for par in "wl_display_connect:wayland" "xkb_context_new:xkbcommon" "drmModeGetResources:drm (modo consola)" \ "png_create_read_struct:png" "jpeg_read_header:jpeg" "WebPGetInfo:webp" \ "TIFFOpen:tiff" "DGifOpen:gif" "FcInit:fontconfig" "FT_Init_FreeType:freetype" \ "luaJIT_setmode:luajit"; do sim=${par%%:*}; que=${par##*:} definido /out/usr/bin/swayimg "$sim" || falta="$falta $que($sim)" done if [ -n "$falta" ]; then echo "swayimg: faltan capacidades SIN NINGÚN ERROR de build:$falta" >&2 echo " — con las perillas en 'auto' meson las habría saltado en silencio; están fijas justo por esto" >&2 exit 1 fi # exiv2 entra estática (ver su receta: el cruce de C++ con una .so segfaultearía), así que se # comprueba su símbolo y no un NEEDED. Sin esto, el EXIF no se leería y las fotos verticales # saldrían tumbadas — sin error. readelf -sW /out/usr/bin/swayimg 2>/dev/null | grep -q 'Exiv2.*ImageFactory' || { echo "swayimg: no hay rastro de Exiv2::ImageFactory en el binario — el EXIF no se leería y las fotos verticales saldrían tumbadas" >&2; exit 1; } n=$(readelf -d /out/usr/bin/swayimg 2>/dev/null | grep -c NEEDED) echo "swayimg: binario autosuficiente ($n NEEDED) · wayland + drm + png jpeg webp tiff gif + exif" ''' [deps] build = ["meson", "samurai", "pkgconf", "wayland", "wayland-protocols", "libxkbcommon", "fontconfig", "freetype", "libpng", "libjpeg-turbo", "libwebp", "libtiff", "giflib", "exiv2", "libdrm", "luajit", "expat", "zlib", "brotli", "binutils", "python3"]