protoc: el catálogo tenía el PLUGIN y no el compilador — y abseil y protobuf tienen que compartir runtime de C++
`recipes/protoc-gen-go.toml` estaba SELLADO y era INERTE: un plugin de protoc no hace nada sin `protoc`, y `protoc` no estaba en el catálogo. Cualquier servicio gRPC lo necesita en tiempo de build — empezando por `qdrant`, que el censo del servidor de origen encontró corriendo como binario suelto, de los que se pierden al apagar la máquina vieja. Entran dos recetas: `abseil-cpp` (que protobuf exige) y `protobuf`. Verificado corriéndolo, no por el código de salida: `protoc --version` contesta `libprotoc 36.1`, y un `.proto` de prueba se compila a `.pb.h`/`.pb.cc` reales. Único NEEDED `libc.so`, que provee `musl-shared`. Las dos REPRODUCEN bit a bit. **Dos muros, y el segundo escondía al primero.** 1. **`zig c++` se cae al enlazar los tres plugins `protoc-gen-upb*`**: `Error running link command: Segmentation fault` — un crash del linker, no un error de símbolos. Se aisló FUERA de takana y fuera del sandbox, rehaciendo el link a mano sobre los mismos `.o` y las mismas `.a`: `zig c++` vuelve a segfaultear. No es presión de memoria (corrió solo) y no es el `-Wl,-rpath,::::::::::::::` que CMake emite — se probó sin él y cae igual. `protobuf_BUILD_LIBUPB=OFF` tampoco es escapatoria: queda `OFF` en el `CMakeCache` y los plugins se construyen igual. Con `g++` y el `ld` de GNU los cuatro binarios enlazan. 2. Al pasar **sólo** protobuf a `gcc`, con abseil todavía construida por `zig-cc`, el link murió con `undefined reference to std::__1::basic_string<…>::assign(char const*, unsigned long)`. **El `__1` es el namespace inline de libc++** —la libstdc++ que trae zig— y g++ usa la de GNU, con otro mangling para los mismos tipos. O sea: **abseil y protobuf tienen que compartir runtime de C++ o no enlazan**, y el error habla de `std::string` sin nombrar a abseil ni una vez. Es la familia de las dos glib estáticas en un proceso, pero en C++ y en tiempo de link. ⇒ Las dos recetas llevan `compiler = "gcc"` y está escrito en ambas que cambiar una sin la otra vuelve a romper. `-static-libstdc++ -static-libgcc` para que `protoc` no salga pidiendo una soname que sólo vive en el lab. Y una decisión que NO es «la última versión»: abseil va pineada a `20250512.1` porque es exactamente la que protobuf 36.1 declara en `cmake/dependencies.cmake`. Abseil no promete ABI estable entre releases; el disparador para subirla es que protobuf suba la suya, no que abseil publique.
Semántico sayk'uy
Mana ima sutichaypas t'ikrakurqanchu: qillqalla, yachachiylla utaq willaylla t'ikrakurqan.
4 qillqakuna · +162 −32
- docs/state/build-state.json +24 −32
- docs/state/repro-verificado.tsv +2 −0
- recipes/abseil-cpp.toml +64 −0
- recipes/protobuf.toml +72 −0
diff --git a/docs/state/build-state.json b/docs/state/build-state.json
index 704a6a92..9d4eb468 100644
--- a/docs/state/build-state.json
+++ b/docs/state/build-state.json
@@ -3,9 +3,7 @@
"totals": {
"recipes": 884,
"nodes": 886,
- "sealed": 881,
- "debt": 2,
- "never": 1,
+ "sealed": 884,
"ajeno": 2
},
"by_class": {
@@ -16,14 +14,10 @@
"kernel": 6,
"rust": 234
},
- "debt_by_class": {
- "c": 3
- },
+ "debt_by_class": {},
"by_queue": {
"corpus": {
- "sealed": 881,
- "debt": 2,
- "never": 1,
+ "sealed": 884,
"ajeno": 2
}
},
@@ -57,7 +51,7 @@
"iname": "abseil-cpp",
"version": "20250512.1",
"link": "static",
- "compiler": "zig-cc",
+ "compiler": "gcc",
"deps": [
"binutils",
"busybox",
@@ -67,10 +61,10 @@
"cls": "c",
"queue": "corpus",
"foreign": false,
- "hash": "b3:189049943e9217fbc35457c9b8ab5ce32b4a0f5a47a821d09622f8b1dc5c46f5",
+ "hash": "b3:a0d2ad6f771ecb64471a7e25db365cfcfb785574d75d4161ee2423beb7f35b5f",
"state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 0,
"perfiles": [],
"dependientes_total": 1
},
@@ -831,11 +825,9 @@
"cls": "c",
"queue": "corpus",
"foreign": false,
- "hash": "b3:3273cf2ab0c05edf56b1cc780977986e71736cb823cecbc2331fe400fa7057ed",
- "state": "debt",
- "blocked_by": [
- "puriy-costura"
- ],
+ "hash": "b3:b4ea2930336e7dcf342c19e37240296b70c626ca86a569ccde816efeac618b02",
+ "state": "sealed",
+ "blocked_by": [],
"unblocks": 0,
"perfiles": [
"escritorio-cosmic",
@@ -1023,7 +1015,7 @@
"hash": "b3:4b5fbf3b38baf6f9579d56353925cd8b7f4b4e5acce9be80534e1c896a160104",
"state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 0,
"perfiles": [
"base",
"cli",
@@ -1302,7 +1294,7 @@
"hash": "b3:2a2b1280c57affe906ce43ba20fd3867dda18b9ed4476ef64285baf018c4a5fd",
"state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 0,
"perfiles": [
"cli",
"escritorio-cosmic",
@@ -2600,7 +2592,7 @@
"hash": "b3:5f6c63a239018869d4b0f37e019ce081f2a5f077dbf3d441d8f14163c54dcb2f",
"state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 0,
"perfiles": [
"escritorio-cosmic",
"escritorio-gnome",
@@ -4565,7 +4557,7 @@
"hash": "b3:3d199174bac73245fd39133327e5eac7cf3d7def5aad46a25b732c0ee8f178fd",
"state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 0,
"perfiles": [
"escritorio-cosmic",
"escritorio-gnome",
@@ -5083,7 +5075,7 @@
"hash": "b3:aa605af4fdbb9498831040f2e757464ca15a46ccef30e7b7f34ec64f0d24041c",
"state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 0,
"perfiles": [
"escritorio-cosmic",
"escritorio-gnome",
@@ -10804,7 +10796,7 @@
"hash": "b3:57d38057b82cef4e871d68a3324fd485b298df81a766a5dcf8269e6fb63efe16",
"state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 0,
"perfiles": [
"base",
"cli",
@@ -13507,7 +13499,7 @@
"iname": "protobuf",
"version": "36.1",
"link": "dynamic",
- "compiler": "zig-cc",
+ "compiler": "gcc",
"deps": [
"abseil-cpp",
"binutils",
@@ -13519,8 +13511,8 @@
"cls": "c",
"queue": "corpus",
"foreign": false,
- "hash": "b3:7d500455a06f76d1d29d3f45ea30c3b4c7659a0e80d3ad066961be771f9fb5b5",
- "state": "never",
+ "hash": "b3:c01f39d4a566e48f09d077ac20a5c6249c6a36fe3c53196c1c6e5e4ce0bc5991",
+ "state": "sealed",
"blocked_by": [],
"unblocks": 0,
"perfiles": [],
@@ -13637,10 +13629,10 @@
"cls": "c",
"queue": "corpus",
"foreign": false,
- "hash": "b3:ae5d7a040fdf4046a0f5fec22e4a294d1f85d5a367de46c300a5f224320de2f5",
- "state": "debt",
+ "hash": "b3:e0d0e424a2d28fe4bfd99b708ac77acda3b01c0e60e268b07f31f17b6b9d479c",
+ "state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 0,
"perfiles": [
"escritorio-cosmic",
"escritorio-gnome",
@@ -13661,7 +13653,7 @@
"hash": "b3:27c7b73a96dd5b851ffabe892f9086be1e3c6f501b852a057132cb8bdcbd25d1",
"state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 0,
"perfiles": [
"escritorio-cosmic",
"escritorio-gnome",
@@ -13690,7 +13682,7 @@
"hash": "b3:ff5cf5e5080f20587b26946d0dfff36a58c9096d30eace4ae9cece24594d171e",
"state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 0,
"perfiles": [
"base",
"cli",
@@ -17909,7 +17901,7 @@
"hash": "b3:dc363f261a71239412f6090e50e8abc0c7f6e544ccefa48c5ee5f47d26e84ef3",
"state": "sealed",
"blocked_by": [],
- "unblocks": 1,
+ "unblocks": 0,
"perfiles": [
"base",
"cli",
diff --git a/docs/state/repro-verificado.tsv b/docs/state/repro-verificado.tsv
index 398ba6a6..ff8b05ba 100644
--- a/docs/state/repro-verificado.tsv
+++ b/docs/state/repro-verificado.tsv
@@ -76,3 +76,5 @@ logrotate 09698cb83519dc2423b8aa1905fa5803955ee1c79598590c30ff5b5b14e5e84d 2026-
chrony b9e26374f000ef5820bcc32bdb761b2b3e7306d1ed400c147271cfdbd77557e9 2026-09-11 reproduce
cronie 387347b89b107d97febbb2692ce2d292e74bc7b1fba105676befe396cc3ebf21 2026-09-11 reproduce
valkey 9571c1a691ff8dd2e91611a341d2ddab11a9cc9a030ed8054006a4626542a06f 2026-09-11 reproduce
+abseil-cpp a0d2ad6f771ecb64471a7e25db365cfcfb785574d75d4161ee2423beb7f35b5f 2026-09-11 reproduce
+protobuf c01f39d4a566e48f09d077ac20a5c6249c6a36fe3c53196c1c6e5e4ce0bc5991 2026-09-11 reproduce
diff --git a/recipes/abseil-cpp.toml b/recipes/abseil-cpp.toml
new file mode 100644
index 00000000..c64ec207
--- /dev/null
+++ b/recipes/abseil-cpp.toml
@@ -0,0 +1,64 @@
+# abseil-cpp 20250512.1 — la base de C++ de Google. No entra por sí misma: entra porque **protobuf la
+# exige**, y protobuf faltaba. El agujero se ve solo en el catálogo: `protoc-gen-go` está SELLADO y es
+# INERTE, porque un plugin de protoc no sirve sin `protoc`; y cualquier servicio gRPC —`qdrant`, el
+# que corre hoy en el servidor de origen como binario suelto— necesita `protoc` en tiempo de build.
+#
+# ⚠ **LA VERSIÓN NO ES «LA ÚLTIMA», Y ESO ES LA DECISIÓN.** La última publicada es `20260817.0`; acá
+# va `20250512.1` porque es **exactamente la que protobuf 36.1 declara** en
+# `cmake/dependencies.cmake` (`set(abseil-cpp-version "20250512.1")`). Abseil no promete ABI estable
+# entre releases —lo dice su propio README— y protobuf enlaza contra sus símbolos internos: emparejar
+# la versión con la que upstream probó es la diferencia entre un build y una tarde de errores de
+# plantillas. Subirla es su propia unidad de trabajo, y el disparador correcto es que protobuf suba
+# la suya, no que abseil publique.
+#
+# `-DBUILD_SHARED_LIBS=OFF` + `-DCMAKE_POSITION_INDEPENDENT_CODE=ON`: estático, pero compilado con
+# `-fPIC`. Las dos cosas a la vez no es contradicción — es lo que hace falta para que protobuf pueda
+# enlazar estas `.a` dentro de un `libprotobuf` que sí puede terminar siendo compartido. Sin el PIC,
+# el link del consumidor muere con «relocation R_X86_64_32 against … can not be used when making a
+# shared object», que es un error que no nombra a abseil por ningún lado.
+#
+# `-DABSL_PROPAGATE_CXX_STD=ON` es la palanca que abseil pide a gritos (avisa por consola si falta):
+# sin ella el estándar de C++ con el que se compiló abseil NO viaja a los consumidores por los
+# targets de CMake, y protobuf puede compilarse con otro ⇒ dos mitades del mismo binario con
+# `std::string_view` distinto. Es la familia de las dos glib estáticas en un proceso, en C++.
+#
+# ⚠ **`compiler = "gcc"` NO ES UNA PREFERENCIA: ES EL CONTRATO CON PROTOBUF, Y SE DESCUBRIÓ
+# ROMPIÉNDOLO.** Con `zig-cc` esta receta sella perfecto —669 ficheros, 88 `.a`— y después protobuf
+# muere al enlazar con:
+#
+# undefined reference to `std::__1::basic_string<…>::assign(char const*, unsigned long)'
+#
+# El `__1` de ese símbolo es el namespace inline de **libc++**, que es la libstdc++ que trae zig.
+# g++ usa **libstdc++ de GNU**, con otro mangling para los mismos tipos. O sea: abseil y protobuf
+# tienen que compartir runtime de C++ o no enlazan, y el error no nombra a abseil por ningún lado —
+# habla de `std::string`. Es la familia de [[dos-glib-estaticas-en-un-proceso]], en C++ y en tiempo
+# de link en vez de runtime.
+#
+# `-DABSL_PROPAGATE_CXX_STD=ON` cubre el OTRO eje del mismo problema —que el *estándar* (C++17) viaje
+# a los consumidores por los targets de CMake— pero no cubre éste: la *librería* no la propaga CMake,
+# la elige el compilador. Por eso la decisión vive en el campo `compiler` de las dos recetas, y
+# cambiar una sin la otra vuelve a romper.
+#
+# `CMAKE_INSTALL_LIBDIR=lib`: el lab usa `/usr/lib`, no `/usr/lib64`, o los `.cmake` y `.pc` quedan
+# donde nadie los busca.
+name = "abseil-cpp"
+version = "20250512.1"
+license = "Apache-2.0"
+
+[source]
+tarball = "https://github.com/abseil/abseil-cpp/archive/refs/tags/20250512.1.tar.gz"
+sha256 = "9b7a064305e9fd94d124ffa6cc358592eb42b5da588fb4e07d09254aa40086db"
+
+[build]
+compiler = "gcc"
+target = "x86_64-linux-musl"
+link = "static"
+flags = []
+
+[build.phases]
+configure = "cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_STANDARD=17 -DABSL_PROPAGATE_CXX_STD=ON -DABSL_BUILD_TESTING=OFF"
+compile = 'cmake --build build -j"$(nproc)"'
+install = "DESTDIR=/out cmake --install build"
+
+[deps]
+build = ["binutils", "busybox", "make", "cmake"]
diff --git a/recipes/protobuf.toml b/recipes/protobuf.toml
new file mode 100644
index 00000000..4446df49
--- /dev/null
+++ b/recipes/protobuf.toml
@@ -0,0 +1,72 @@
+# protobuf 36.1 — **`protoc`**, el compilador de `.proto`. Es el hueco que se ve solo al mirar el
+# catálogo: `recipes/protoc-gen-go.toml` está SELLADO y es **inerte**, porque un plugin de protoc no
+# hace nada sin protoc; y cualquier servicio gRPC necesita `protoc` en tiempo de build — empezando
+# por `qdrant`, que el censo del servidor de origen encontró corriendo como binario suelto (de los
+# que se pierden al apagar la máquina vieja) y cuyo `build.rs` lo invoca vía prost/tonic.
+#
+# **La dep de abseil no se vendoriza ni se descarga: se declara.** El tarball de release de protobuf
+# NO trae abseil adentro (comprobado: cero entradas bajo `third_party/abseil-cpp/`), y su
+# `cmake/abseil-cpp.cmake` tiene un fallback que hace `FetchContent` desde GitHub. Ese fallback en
+# este lab es una trampa doble: el sandbox está OFFLINE, así que fallaría igual — pero fallaría
+# hablando de red y no de dependencias — y si algún día no estuviera offline, metería una fuente sin
+# pinear en un build que se supone reproducible. `protobuf_LOCAL_DEPENDENCIES_ONLY=ON` apaga el
+# fallback ⇒ si abseil no está, el error dice *«Cannot find abseil-cpp dependency»*, que es lo que
+# uno necesita leer. `recipes/abseil-cpp.toml` está pineada a la versión exacta que este protobuf
+# declara.
+#
+# `-Dprotobuf_BUILD_TESTS=OFF`: la suite arrastra googletest, que es otra dep que no hace falta para
+# producir un `protoc`. `-Dprotobuf_BUILD_SHARED_LIBS=OFF` deja `protoc` monolítico salvo por la libc.
+#
+# ⚠ **`compiler = "gcc"` Y `-static-libstdc++`: DOS MUROS, Y EL SEGUNDO ESCONDÍA AL PRIMERO.**
+#
+# 1. **`zig c++` SE CAE AL ENLAZAR los tres plugins `protoc-gen-upb*`** — `Error running link
+# command: Segmentation fault`, no un error de símbolos. Se aisló FUERA de takana y fuera del
+# sandbox: rehaciendo a mano el link de `protoc-gen-upb` con el `zig` del lab, sobre los mismos
+# `.o` y las mismas `.a`, `zig c++` vuelve a segfaultear. No es presión de memoria (corrió solo) y
+# no es el `-Wl,-rpath,::::::::::::::` que CMake emite —se probó sin él y cae igual—. Con `g++` y
+# el `ld` de GNU los cuatro binarios enlazan. `protobuf_BUILD_LIBUPB=OFF` **no** es escapatoria:
+# se probó, queda `OFF` en el `CMakeCache` y los plugins se construyen igual.
+#
+# 2. **abseil y protobuf TIENEN QUE COMPARTIR RUNTIME DE C++.** Al pasar sólo protobuf a `gcc`, con
+# abseil todavía construida por `zig-cc`, el link murió con
+# `undefined reference to std::__1::basic_string<…>::assign(char const*, unsigned long)`. El `__1`
+# es el namespace inline de **libc++** (la que trae zig); g++ usa **libstdc++ de GNU**, con otro
+# mangling para los mismos tipos. El error habla de `std::string` y no nombra a abseil ni una vez.
+# Por eso `recipes/abseil-cpp.toml` también lleva `compiler = "gcc"`, y **cambiar una sin la otra
+# vuelve a romper**.
+#
+# `-static-libstdc++ -static-libgcc` en `CMAKE_EXE_LINKER_FLAGS` para que `protoc` no salga pidiendo
+# `libstdc++.so.6`, que es una soname que sólo vive en el LAB y que el corpus no publica — la familia
+# de [[needed-colgante-libstdcxx]]. Comprobado sobre el artefacto: el único NEEDED es `libc.so`, que
+# provee `musl-shared`.
+#
+# Lo que sale, verificado corriéndolo y no por el código de salida: `protoc` (13,3 M) más los tres
+# plugins de upb, y un `.proto` de prueba se compila a `.pb.h`/`.pb.cc` de verdad.
+#
+# `CMAKE_INSTALL_LIBDIR=lib` por lo de siempre: el lab usa `/usr/lib`, no `/usr/lib64`, o los `.pc` y
+# los `.cmake` quedan donde ningún consumidor los busca.
+#
+# ⚠ **La versión de protobuf ES contrato de generación, no sólo de API.** `protoc` decide qué código
+# emite, y el `.pb.cc`/`.pb.go` generado tiene que casar con la librería runtime que el consumidor
+# enlace. Subirla no es actualizar una herramienta: es mover el formato de lo que sale.
+name = "protobuf"
+version = "36.1"
+license = "BSD-3-Clause"
+
+[source]
+tarball = "https://github.com/protocolbuffers/protobuf/releases/download/v36.1/protobuf-36.1.tar.gz"
+sha256 = "dc74fa582f559cbd31614ddfefb4868f43c919d7184bde514bb47f90c6025eb8"
+
+[build]
+compiler = "gcc"
+target = "x86_64-linux-musl"
+link = "dynamic"
+flags = []
+
+[build.phases]
+configure = "cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17 -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_LOCAL_DEPENDENCIES_ONLY=ON -Dprotobuf_ABSL_PROVIDER=package -DCMAKE_EXE_LINKER_FLAGS='-static-libstdc++ -static-libgcc'"
+compile = 'cmake --build build -j"$(nproc)"'
+install = "DESTDIR=/out cmake --install build"
+
+[deps]
+build = ["binutils", "busybox", "make", "cmake", "abseil-cpp", "zlib"]