Files
Sergio c0a25cef22 protobuf/abseil vuelven a zig: la causa raíz quita el escape a gcc — y lo valida en un segundo proyecto
Ayer estas dos huyeron a `compiler = "gcc"` para esquivar un crash del linker en los tres
`protoc-gen-upb*`. **Esquivé el fallo sin conocer su causa, y salió caro:** al mover sólo protobuf, el
link murió con `undefined reference to std::__1::basic_string<…>` —el `__1` de libc++— porque abseil
seguía en zig, así que hubo que arrastrar las dos fuera del toolchain por defecto.

La causa apareció al día siguiente en `dwarves`, bisecando la línea de enlace real:

    tal cual                      → exit 139 (SIGSEGV)
    quitando `-static`            → exit 139     ⇒ no es el enlace estático
    quitando `--dependency-file`  → **exit 0**   ⇒ ES ESO

El `lld` de zig 0.16.0 segfaultea con el `--dependency-file` que CMake ≥3.27 mete en la línea de
enlace. Con `-DCMAKE_LINK_DEPENDS_USE_LINKER=OFF` **los cuatro binarios de protobuf enlazan con zig**,
incluidos los tres plugins que se caían.

Esto es, además, la validación de la causa raíz en un proyecto INDEPENDIENTE de dwarves: dos
proyectos sin relación, mismo síntoma, misma perilla, los dos arreglados.

Con el escape se va también el `-static-libstdc++`, que sólo hacía falta porque g++ enlaza contra la
libstdc++ de GNU. Comprobado sobre el artefacto: el único NEEDED de `protoc` es `libc.so`, que provee
`musl-shared`.

Verificado de punta a punta, no por el código de salida: `protoc --version` → `libprotoc 36.1`, y un
`.proto` compila a `m.pb.h`/`m.pb.cc` **y** a `p/m.pb.go` pasando por `protoc-gen-go` — o sea que la
cadena plugin↔driver que abrí anteayer sigue entera. Las dos REPRODUCEN bit a bit.

Se deja escrito el camino completo en las recetas, diagnóstico corto incluido, porque la lección no
es la perilla: es que **un escape que funciona sin explicar el fallo se paga después**, y acá se pagó
con dos recetas fuera del toolchain por defecto y un choque de runtimes de C++ que sólo apareció
porque el escape era parcial.
2026-09-12 10:46:19 +00:00

72 lines
4.4 KiB
TOML

# 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++.
#
# ⚠ **EL `compiler` DE ESTA RECETA Y EL DE PROTOBUF TIENEN QUE SER EL MISMO, Y SE DESCUBRIÓ
# ROMPIÉNDOLO.** Con esta en `zig-cc` y protobuf en `gcc`, 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**.
#
# **Las dos volvieron a `zig-cc` el 2026-09-12.** La huida a `gcc` fue para esquivar un crash del
# linker de zig en los plugins `protoc-gen-upb*` de protobuf, esquivado SIN conocer la causa. La
# causa apareció al día siguiente en `dwarves` y es otra: el `lld` de zig 0.16.0 **segfaultea con el
# `--dependency-file` que CMake ≥3.27 mete en la línea de enlace**, y se apaga con
# `-DCMAKE_LINK_DEPENDS_USE_LINKER=OFF`. Con la causa arreglada el escape sobra — y vale más quitarlo
# que dejarlo: el toolchain por defecto del proyecto es zig, y cada `compiler = "gcc"` es una
# excepción que alguien tiene que entender después.
#
# `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 = "zig-cc"
target = "x86_64-linux-musl"
link = "static"
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 -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"]