# 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 = "zig-cc"` 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**. # # ⚠⚠ **ACTUALIZACIÓN 2026-09-12: LA CAUSA ERA OTRA, Y LA RECETA VOLVIÓ A `zig-cc`.** Lo de arriba # describe lo que se midió el día 11 y sigue siendo cierto como SÍNTOMA, pero el diagnóstico se # quedó corto: el crash no es «zig no puede con estos plugins». Apareció otra vez en `dwarves` y ahí # se bisecó la línea de enlace real (`build/CMakeFiles/.dir/link.txt`, rehecha a mano fuera # del sandbox): # # tal cual → exit 139 (SIGSEGV) # quitando `-static` → exit 139 ⇒ no es el enlace estático # quitando `--dependency-file` → **exit 0** ⇒ ES ESO # # `-Xlinker --dependency-file=…` lo emite CMake ≥3.27 y el `lld` de zig 0.16.0 segfaultea # procesándolo. Con `-DCMAKE_LINK_DEPENDS_USE_LINKER=OFF` los cuatro binarios enlazan con zig, así # que **el escape a gcc sobra** — y con él se va también el `-static-libstdc++`, que sólo hacía falta # porque g++ enlaza contra la libstdc++ de GNU. abseil vuelve a `zig-cc` en el mismo movimiento: el # runtime de C++ de las dos tiene que coincidir, y eso no cambió. # # Se deja escrito el camino entero, con el diagnóstico corto incluido, porque la lección no es la # perilla: es que **esquivar un fallo sin conocer su causa funciona y cuesta caro después** — dos # recetas fuera del toolchain por defecto y un choque de runtimes de C++ que apareció sólo porque el # escape era parcial. # # **Ya NO hace falta `-static-libstdc++`**: lo llevaba mientras la receta iba con `g++`, que enlaza # contra la libstdc++ de GNU y habría dejado a `protoc` pidiendo `libstdc++.so.6`, una soname que # sólo vive en el LAB ([[needed-colgante-libstdcxx]]). Con `zig-cc` la libc++ va estática de fábrica. # Comprobado sobre el artefacto: el único NEEDED de `protoc` 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 = "zig-cc" target = "x86_64-linux-musl" link = "dynamic" flags = [] [build.phases] configure = "cmake -S . -B build -DCMAKE_LINK_DEPENDS_USE_LINKER=OFF -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" compile = 'cmake --build build -j"$(nproc)"' install = "DESTDIR=/out cmake --install build" [deps] build = ["binutils", "busybox", "make", "cmake", "abseil-cpp", "zlib"]