`scripts/mudanza/planear.py` agrupa el software del origen en familias funcionales y contesta, para
cada una, con qué la reemplaza takana. Cruzando esa tabla contra el catálogo, cuatro familias salen
SIN NADA sellado: caché en memoria, contenedores, correo y base vectorial. Ésta cierra la primera.
Valkey y no redis a propósito: redis dejó de ser software libre en 2024 (RSALv2/SSPLv1, que no pasan
la OSI); valkey es el fork de la Linux Foundation desde el último commit BSD, mismo protocolo y mismo
RDB/AOF. Y upstream instala los seis alias `redis-*`, así que un `redis-server` se reemplaza sin
tocar datos ni clientes. Para una distro que publica el catálogo con `license` poblado receta a
receta, meter SSPL sería meter algo que después hay que sacar.
**El hallazgo caro de esta receta no fue compilar: fue que el PRIMER artefacto se selló VACÍO.**
`make install PREFIX=/usr DESTDIR=/out` imprimió sus `INSTALL valkey-server` en verde y salió 0 — y
`/out` quedó sin un solo fichero. La causa está en la línea 65 de `src/Makefile`: valkey define
`INSTALL_BIN=$(PREFIX)/bin` **sin prefijar `$(DESTDIR)`**, o sea que IGNORA `DESTDIR` y copió los
binarios a `/usr/bin` dentro del sandbox, que se tira al terminar. Lo sellado fue un directorio con
`.hammer/recipe.toml` y nada más: un cache-hit permanente que habría contestado «valkey ya está»
para siempre. Es la regla 3 del repo en vivo — *un ausente falla ruidosamente; un vacío llega hasta
el final diciendo que todo fue bien*. Se vio mirando el árbol del artefacto, NO el código de salida.
El arreglo es `PREFIX=/out/usr`.
El otro muro, medido con un control mínimo fuera de valkey: con `zig cc` el link muere con
`undefined symbol: __cpu_model` en los tres binarios. No es valkey — es que `__builtin_cpu_supports()`
(que valkey usa para elegir en runtime las rutas AVX2/AVX-512) emite esa referencia y el
`compiler_rt` de zig 0.16.0 no la trae:
printf '#include <stdio.h>\nint main(void){__builtin_cpu_init();return printf("%d",__builtin_cpu_supports("avx2"));}\n' > t.c
zig cc -target x86_64-linux-musl -O2 -o t t.c ⇒ ld.lld: error: undefined symbol: __cpu_model
De ahí `compiler = "gcc"`, que es la palanca declarativa que el lab expone justo para esto. Arrancarle
el multiversioning a parches habría costado las rutas SIMD de `BITCOUNT`/`PFCOUNT` y habría que
rehacer el parche en cada versión.
Verificado: REPRODUCE bit a bit. Único NEEDED `libc.so`, que provee `musl-shared` — raíz de `base`
desde hoy ⇒ resuelve en cualquier imagen sin declarar nada en la receta.
92 lines
6.1 KiB
TOML
92 lines
6.1 KiB
TOML
# valkey 9.1.2 — la caché en memoria. Entra por un hueco que se ve desde la herramienta de mudanza:
|
|
# `scripts/mudanza/planear.py` agrupa el software del origen en FAMILIAS funcionales y contesta, para
|
|
# cada una, si takana tiene con qué reemplazarla. Cruzada contra el catálogo, la familia «caché en
|
|
# memoria» salía SIN NADA: ni redis, ni valkey, ni memcached — o sea que si el servidor de origen usa
|
|
# una, la migración se para en seco y se entera tarde.
|
|
#
|
|
# **Por qué valkey y no redis, que es el que todo el mundo tiene corriendo.** No es gusto: redis dejó
|
|
# de ser software libre en 2024 (RSALv2/SSPLv1, licencias que no pasan la OSI) y valkey es el fork que
|
|
# la Linux Foundation sacó del último commit BSD, manteniendo el protocolo y el formato de RDB/AOF. Un
|
|
# `redis-server` se reemplaza por `valkey-server` sin tocar los datos ni los clientes. Para una distro
|
|
# que publica su catálogo con el campo `license` poblado receta a receta, meter SSPL sería meter algo
|
|
# que después hay que sacar.
|
|
#
|
|
# `MALLOC=libc` — valkey trae jemalloc vendorizado y lo usa por default en Linux. No acá: jemalloc
|
|
# asume glibc en varios sitios y el corpus es musl. `libc` es lo que usa Alpine para lo mismo. Ojo
|
|
# con el costo real, que no es cero: jemalloc es lo que le da a valkey la defragmentación activa
|
|
# (`activedefrag`), así que con `MALLOC=libc` esa opción no existe. Es la decisión correcta igual —
|
|
# un valkey que arranca sin defrag le gana a uno que no compila— pero queda dicho y no escondido.
|
|
#
|
|
# **Lo que NO hizo falta parchear, y vale la pena por qué:** `src/debug.c` usa `backtrace()` de
|
|
# `execinfo.h`, que musl no tiene. Upstream ya lo resuelve bien en `src/config.h`: pide
|
|
# `__linux__ && __GLIBC__` para definir `HAVE_BACKTRACE`, y musl no define `__GLIBC__`. Sale sin el
|
|
# volcado de pila en los crashes, que es la misma renuncia que hace Alpine.
|
|
#
|
|
# ⚠ **`compiler = "gcc"`, Y ESTO ESTÁ MEDIDO CON UN CONTROL MÍNIMO, NO SUPUESTO.** Con el `zig cc`
|
|
# por defecto el link muere en los tres binarios con `ld.lld: error: undefined symbol: __cpu_model`.
|
|
# La causa no es valkey: `src/util.c`, `src/bitops.c` y `src/hyperloglog.c` usan
|
|
# `__builtin_cpu_supports()` para elegir en runtime las rutas AVX2/AVX-512, y ese builtin emite una
|
|
# referencia a `__cpu_model`, que provee la runtime del compilador (libgcc). El `compiler_rt` de
|
|
# zig 0.16.0 NO la trae. Comprobado fuera de valkey, con seis líneas:
|
|
#
|
|
# printf '#include <stdio.h>\nint main(void){__builtin_cpu_init();return printf("%%d",__builtin_cpu_supports("avx2"));}\n' > t.c
|
|
# zig cc -target x86_64-linux-musl -O2 -o t t.c ⇒ ld.lld: error: undefined symbol: __cpu_model
|
|
#
|
|
# Por eso el escape es declarativo y no un parche: `compiler = "gcc"` es exactamente la palanca que
|
|
# el lab expone para «lld estricto de zig no linkea esto», y libgcc sí define `__cpu_model`.
|
|
# Arrancarle el multiversioning a valkey a parches habría sido peor: se pierden las rutas SIMD que
|
|
# son la mitad del rendimiento de `BITCOUNT` y `PFCOUNT`, y el parche hay que rehacerlo en cada
|
|
# versión.
|
|
#
|
|
# `OPTIMIZATION=-O2` apaga el LTO que valkey enciende sola cuando la optimización es `-O3` (su
|
|
# `src/Makefile` añade `-flto=auto -ffat-lto-objects`). No es por el `__cpu_model` —eso falla con y
|
|
# sin LTO, se probó— sino porque un LTO de fábrica sobre un árbol con seis deps vendorizadas es
|
|
# superficie de fallo que esta receta no necesita para su primera versión sellada.
|
|
#
|
|
# La reproducibilidad la trae upstream y conviene decir dónde: `src/mkreleasehdr.sh` hornea un
|
|
# `REDIS_BUILD_ID` que por default es `uname -n` + `date +%s` —la familia exacta del sello de tiempo
|
|
# de nftables— pero el script mira `SOURCE_DATE_EPOCH`, que el lab exporta.
|
|
#
|
|
# Lo que sale, comprobado sobre el artefacto sellado y no sobre el código de salida: `valkey-server`
|
|
# (10,4 M), `valkey-cli`, `valkey-benchmark`, los symlinks de sentinel/check-rdb/check-aof y —esto
|
|
# importa para migrar— los seis alias `redis-*`, que upstream instala solo. `valkey-server --version`
|
|
# contesta `v=9.1.2 malloc=libc`. Su único NEEDED es `libc.so`, que lo provee `musl-shared`, raíz del
|
|
# perfil `base` ⇒ resuelve en cualquier imagen sin declarar nada acá.
|
|
#
|
|
# `link = "dynamic"`: valkey enlaza C y C++ (la dep `fast_float` es C++), y la runtime de C++ del
|
|
# corpus se publica compartida. Un `link = "static"` acá sellaría un binario dinámico igual y la
|
|
# receta estaría mintiendo — la familia de fallos del `link=static` por libtool, vista de otro lado.
|
|
name = "valkey"
|
|
version = "9.1.2"
|
|
license = "BSD-3-Clause"
|
|
|
|
[source]
|
|
tarball = "https://github.com/valkey-io/valkey/archive/refs/tags/9.1.2.tar.gz"
|
|
sha256 = "19c23908e7d57e8d91ef85b41f5646307582f10f4f0fb999bbf89ed24ec9c983"
|
|
|
|
[build]
|
|
compiler = "gcc"
|
|
target = "x86_64-linux-musl"
|
|
link = "dynamic"
|
|
flags = []
|
|
|
|
[build.phases]
|
|
# `configure = 'true'` NO ES RELLENO. valkey 9 trae `CMakeLists.txt` ADEMÁS del `Makefile` clásico,
|
|
# y la heurística del lab detecta CMake primero ⇒ inyecta un `cmake -S . -B _build …` que muere con
|
|
# `cmake: not found` (el corpus no tiene cmake en las deps de esta receta). El no-op apaga esa fase
|
|
# y deja el camino que upstream mantiene como principal, que es `make` sobre `src/Makefile`.
|
|
configure = 'true'
|
|
compile = 'make -j"$(nproc)" MALLOC=libc PREFIX=/usr OPTIMIZATION=-O2'
|
|
# ⚠ **`PREFIX=/out/usr` Y NO `DESTDIR=/out`, Y ESTO CASI PASA INADVERTIDO.** El `src/Makefile` de
|
|
# valkey **IGNORA `DESTDIR`**: define `INSTALL_BIN=$(PREFIX)/bin` a secas (línea 65), sin prefijar
|
|
# `$(DESTDIR)`. Con `PREFIX=/usr DESTDIR=/out` el `make install` imprime sus `INSTALL valkey-server`
|
|
# en verde, sale 0, y copia los binarios a `/usr/bin` DENTRO del sandbox — un overlay que se tira al
|
|
# terminar. El resultado fue un artefacto SELLADO con `.hammer/recipe.toml` y NADA MÁS: la regla 3
|
|
# del repo en vivo («un ausente falla ruidosamente; un vacío llega hasta el final diciendo que todo
|
|
# fue bien»), y peor, un cache-hit permanente que habría contestado «valkey ya está» para siempre.
|
|
# Se detectó mirando el árbol del artefacto, no el código de salida.
|
|
install = 'make install MALLOC=libc PREFIX=/out/usr'
|
|
|
|
[deps]
|
|
build = ["binutils", "busybox", "make", "pkgconf"]
|