recipes: yoga, el submódulo de fcitx5 que el tarball trae vacío
fcitx5 >=5.1.20 maqueta su ventana de candidatos con yoga y lo trae como
submódulo git. Un archive de GitHub no materializa submódulos: third_party/yoga
es el ÚNICO directorio vacío del tarball, y su rama else() hace
add_subdirectory de algo que no existe ⇒ falla al CONFIGURAR.
Se pinea el gitlink exacto que fcitx5 5.1.21 declara (042f5013), no el último
tag de yoga — mismo criterio que sonic con espeak-ng.
Dos parches obligatorios al árbol, los dos con su comprobación para que el día
que upstream mueva la línea falle ruidosamente:
· add_subdirectory(tests) baja googletest POR RED, y es incondicional. No se
puede esquivar con -S yoga: las reglas de install y el export del paquete
cmake viven en el CMakeLists RAÍZ, así que eso daría la .a sin
yogaConfig.cmake y el find_package de fcitx5 no la encontraría.
· -Werror de upstream, calibrado contra otros compiladores. No vale
-Wno-error por CMAKE_CXX_FLAGS: van antes de add_compile_options y en clang
gana el último.
Delta semántico
Ninguna definición cambió: el cambio es de texto, documentación o datos.
1 archivos · +129 −0
- recipes/yoga.toml +129 −0
diff --git a/recipes/yoga.toml b/recipes/yoga.toml
new file mode 100644
index 00000000..cfacd3b0
--- /dev/null
+++ b/recipes/yoga.toml
@@ -0,0 +1,129 @@
+# yoga — el motor de maquetación flexbox de Meta. Entra como DEP OBLIGATORIA de fcitx5 ≥5.1.20.
+#
+# ══ POR QUÉ ESTA RECETA EXISTE: ES UN SUBMÓDULO Y EL TARBALL VIENE VACÍO ═══════════════════════
+# `fcitx5` usa yoga para maquetar la ventana de candidatos de su UI clásica (`src/ui/classic`), y lo
+# trae como **submódulo git** (`third_party/yoga` → `https://github.com/facebook/yoga`). Un archive
+# de GitHub NO materializa submódulos: medido, `third_party/yoga` es el **único** directorio vacío
+# del tarball de fcitx5 5.1.21. Y su CMakeLists no tiene salida por red:
+#
+# if (USE_SYSTEM_YOGA) find_package(yoga REQUIRED); set(YOGA_TARGET yoga::yogacore)
+# else() add_subdirectory(third_party/yoga/yoga) ← directorio VACÍO acá
+#
+# ⇒ `USE_SYSTEM_YOGA=On` + esta receta es el único camino. Es la misma figura que `sonic` con
+# espeak-ng, con una diferencia que importa: allá el fallback era un `git clone` en tiempo de build;
+# acá es un `add_subdirectory` de algo que no existe, así que falla al CONFIGURAR y no al enlazar.
+#
+# ══ EL COMMIT ES EL QUE FCITX5 PINEA ═══════════════════════════════════════════════════════════
+# `042f5013…` es exactamente el gitlink que `fcitx5` 5.1.21 declara para su submódulo (leído por la
+# API de GitHub, no adivinado). Se pinea ese y no el último tag de yoga porque es el emparejamiento
+# que upstream prueba — mismo criterio que `sonic`. Si fcitx5 mueve su submódulo, esta receta lo
+# sigue y el `git log` dirá por qué.
+#
+# La versión de upstream es literalmente `0.0.0` en su `package.json`: yoga no versiona el paquete
+# nativo, versiona los bindings. El sufijo del commit es lo único que identifica este artefacto.
+#
+# ══ ⚠ DOS PARCHES AL ÁRBOL, Y LOS DOS SON OBLIGATORIOS ═════════════════════════════════════════
+# 1. **`add_subdirectory(tests)` baja googletest POR RED.** El CMakeLists raíz lo añade **sin
+# condición** (no hay perilla `BUILD_TESTING` que lo cubra), y `tests/CMakeLists.txt` hace
+# `FetchContent_Declare(googletest URL https://github.com/google/googletest/…zip)`. El sandbox de
+# takana no tiene red a propósito, así que eso mata el configure.
+#
+# ⚠ Y NO se puede esquivar configurando `-S yoga` (el subdirectorio de la biblioteca): **las
+# reglas de `install` y el `export` del paquete cmake viven en el CMakeLists RAÍZ**, no en
+# `yoga/`. Construir sólo el subdirectorio daría la `.a` sin `yogaConfig.cmake`, y entonces el
+# `find_package(yoga REQUIRED)` de fcitx5 no la encontraría: artefacto sellado, con contenido, y
+# sin lo único que el consumidor busca. ⇒ se conserva la raíz y se le quita la línea.
+#
+# 2. **`-Werror` está en `cmake/project-defaults.cmake`** (con `-Wall`), y está calibrado contra los
+# compiladores de Meta. El clang de zig es otra versión y avisa de otras cosas; un aviso nuevo
+# cualquiera convertiría el build en un fallo que no dice nada de yoga. No vale pasar
+# `-Wno-error` por `CMAKE_CXX_FLAGS`: esos van ANTES de los `add_compile_options`, y en clang
+# gana el último. ⇒ se quita de la fuente, que es determinista y se ve en el diff.
+#
+# Los dos parches se comprueban: si el `sed` no cambia nada —porque upstream movió la línea— el
+# configure falla ruidosamente en vez de volver a bajar googletest por una red que no hay.
+#
+# ══ LO QUE NO HACE FALTA TOCAR ═════════════════════════════════════════════════════════════════
+# · `add_library(yogacore STATIC …)` está codificado, y `project-defaults.cmake` ya pone
+# `CMAKE_POSITION_INDEPENDENT_CODE ON`. O sea que la `.a` es PIC y **puede entrar en un `.so`**,
+# que es justo lo que hace falta: la UI clásica de fcitx5 es un addon que el daemon abre con
+# `dlopen`. Sin ese PIC estaríamos en el muro del 19-oct otra vez.
+# · El `check_ipo_supported` de upstream escribe la propiedad con el nombre equivocado
+# (`CMAKE_INTERPROCEDURAL_OPTIMIZATION` en vez de `INTERPROCEDURAL_OPTIMIZATION`), así que es un
+# no-op y **no hay LTO**. Conviene que siga así: una `.a` con LTO entrando en un `.so` es un
+# problema que no queremos buscar.
+# · fcitx5 incluye `<yoga/Yoga.h>` y el `install(DIRECTORY)` deja las cabeceras exactamente en
+# `/usr/include/yoga/`, así que resuelve por la ruta de sistema.
+#
+# ⚠ `CMAKE_INSTALL_LIBDIR=lib` EXPLÍCITO: el CMakeLists raíz hace `include(GNUInstallDirs)`, que en
+# algunas distros de 64 bits elige `lib64`. Todo este corpus vive en `/usr/lib`, y un artefacto que
+# caiga en `/usr/lib64` se sella igual y no lo encuentra nadie.
+name = "yoga"
+version = "0.0.0-042f501"
+license = "MIT"
+
+[source]
+tarball = "https://github.com/facebook/yoga/archive/042f5013152eb81c1552dec945b88f7b95ca350f/yoga.tar.gz"
+sha256 = "4742f41722a16f181e3da37abf943390db1e928f00f26402cb154662ae7f110f"
+
+[build]
+compiler = "zig-cc"
+target = "x86_64-linux-musl"
+link = "static"
+flags = []
+
+[build.phases]
+configure = '''
+set -e
+ZW="$PWD/.zwrap"; mkdir -p "$ZW"
+printf '#!/bin/sh\nexec /opt/zig/zig cc -mcpu=baseline "$@"\n' > "$ZW/cc"
+printf '#!/bin/sh\nexec /opt/zig/zig c++ -mcpu=baseline "$@"\n' > "$ZW/cxx"
+chmod +x "$ZW/cc" "$ZW/cxx"
+
+# Parche 1: fuera los tests, que bajan googletest por red. Se COMPRUEBA que la línea existía.
+grep -q '^add_subdirectory(tests)' CMakeLists.txt || {
+ echo "yoga: no encuentro 'add_subdirectory(tests)' en el CMakeLists raíz — upstream lo movió." >&2
+ echo " Sin ese parche el configure intenta bajar googletest por red y muere sin decir por qué." >&2
+ exit 1
+}
+sed -i '/^add_subdirectory(tests)$/d' CMakeLists.txt
+
+# Parche 2: fuera el -Werror de upstream. También se comprueba.
+grep -q -- '-Werror' cmake/project-defaults.cmake || {
+ echo "yoga: no encuentro '-Werror' en cmake/project-defaults.cmake — upstream lo movió." >&2
+ exit 1
+}
+sed -i '/^\s*-Werror$/d' cmake/project-defaults.cmake
+
+rm -rf build
+cmake -B build -G Ninja -Wno-dev \
+ -DCMAKE_C_COMPILER="$ZW/cc" -DCMAKE_CXX_COMPILER="$ZW/cxx" \
+ -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr \
+ -DCMAKE_INSTALL_LIBDIR=lib \
+ -DBUILD_FUZZ_TESTS=OFF
+'''
+compile = "cmake --build build"
+# Guardián escrito contra las reglas de `install` del CMakeLists raíz, que es la fuente que decide
+# qué queda — y contra lo que el consumidor busca de verdad: `find_package(yoga REQUIRED)` más el
+# target `yoga::yogacore`. Las tres piezas cubren fallos distintos:
+# · la `.a` sin el config ⇒ find_package no la ve: sellaría un paquete invisible
+# · el config sin targets ⇒ find_package pasa y `yoga::yogacore` no existe, y el error sale
+# DENTRO de fcitx5, culpando a fcitx5 de algo que es de acá
+# · sin cabeceras ⇒ compila fcitx5 y no encuentra <yoga/Yoga.h>
+install = '''
+set -e
+DESTDIR=/out cmake --install build
+[ -f /out/usr/lib/libyogacore.a ] || { echo "yoga: no quedó /usr/lib/libyogacore.a — NO sello" >&2; find /out -name 'libyoga*' 2>/dev/null >&2; exit 1; }
+for f in yogaConfig.cmake yogaTargets.cmake; do
+ [ -f "/out/usr/lib/cmake/yoga/$f" ] || { echo "yoga: falta lib/cmake/yoga/$f — el find_package(yoga REQUIRED) de fcitx5 no encontraría nada" >&2; ls -R /out/usr/lib/cmake 2>/dev/null >&2; exit 1; }
+done
+# El namespace importa: fcitx5 enlaza contra `yoga::yogacore`, y ese nombre lo fija el
+# `NAMESPACE yoga::` del install(EXPORT). Si upstream lo cambiara, el config existiría y el target no.
+grep -q 'yoga::yogacore' /out/usr/lib/cmake/yoga/yogaTargets.cmake || { echo "yoga: yogaTargets.cmake no define el target yoga::yogacore — es el nombre exacto que fcitx5 enlaza" >&2; exit 1; }
+[ -f /out/usr/include/yoga/Yoga.h ] || { echo "yoga: falta include/yoga/Yoga.h — fcitx5 incluye <yoga/Yoga.h>" >&2; exit 1; }
+h=$(find /out/usr/include/yoga -name '*.h' | wc -l)
+echo "yoga: libyogacore.a + yogaConfig/yogaTargets + $h cabecera(s)"
+'''
+
+[deps]
+build = ["cmake", "samurai"]