Antes: dos reconstrucciones daban `libKF6SyntaxHighlighting.so` distintos —
8.800.310 bytes diferentes desde el offset 41, y hasta el tamaño cambiaba
(10.345.888 contra 10.345.840). Ahora: REPRODUCE.
Hash: 4c1638a0… → 3db73c19… (arrastra 4 dependientes directos, 5 transitivos).
── Dónde NO estaba, que también cuenta ────────────────────────────────────────────────
No era el indexer: `katehighlightingindexer` arma el índice con `QVariantMap`, que es
QMap y va ordenado. No eran los generadores de Perl: ninguno de los cuatro itera un
hash. Mirarlo antes ahorró parchear lo que no era.
── Dónde estaba: `data/generators/generate_jinja.py`, con tres dependencias del azar ──
1. `to_do.pop()` sobre un `set` saca un elemento ARBITRARIO. En `--dry-run` el orden de
los `print(out_file)` es lo que CMake recoge en `out_xmls`, y eso acaba siendo **el
orden de las entradas del `.qrc`** ⇒ el recurso compilado cambiaba de disposición
entera. Se toma el menor: mismo conjunto, orden fijo.
2. `version = str(round(time.time()))` hornea la HORA DEL BUILD en el XML generado. Se
honra `SOURCE_DATE_EPOCH`, que es la convención de reproducible-builds y que el
sandbox de takana ya fija (=1).
3. `os.listdir()` sin ordenar. Sólo importa si dos ficheros declaran el mismo lenguaje,
pero quitar la dependencia del readdir no cuesta nada.
── Medido en los dos sentidos ANTES de tocar la receta ────────────────────────────────
Corriendo el generador a mano, sin builds de por medio:
· antes — tres PYTHONHASHSEED distintos ⇒ TRES md5 distintos, y el orden salta a la
vista: `jinja-json, jinja-yaml, jinja-toml…` contra
`jinja-qml, jinja-dockerfile, jinja-typescript…`
· después — las mismas tres semillas ⇒ el MISMO md5
· generando de verdad con semillas Y momentos distintos ⇒ los 35 XML IDÉNTICOS,
con `version="1"`
· control negativo — sin `SOURCE_DATE_EPOCH` sigue poniendo la hora actual
(comprobado: coincidía con `date +%s` al segundo) ⇒ fuera del sandbox no cambia nada
Primer aviso de esta medición: mi primera comparación dio «idéntico con las tres
semillas» y era MENTIRA — el script salía con «Destination folder does not exist» y yo
comparaba md5 de un mensaje de error. Comparar salidas sin mirar que la herramienta
hiciera algo es inventarse un control.
84 lines
4.5 KiB
TOML
84 lines
4.5 KiB
TOML
# syntax-highlighting 6.27.0 — KDE Frameworks 6 (KSyntaxHighlighting, KF6::SyntaxHighlighting).
|
|
# Campaña KDE (ADR 0011): sustrato de ktexteditor (el motor de Kate/KWrite) y de KTextEditor-consumers.
|
|
# Molde KF6 (kxmlgui): dynamic, wrapper zig que filtra -Wl,--fatal-warnings, CMAKE_PREFIX_PATH=/usr, ECM.
|
|
#
|
|
# find_package del CMakeLists: Qt6 Core+Network+Test REQUIRED, Qt6::Gui REQUIRED (KSYNTAXHIGHLIGHTING_USE_GUI
|
|
# ON por defecto), Qt6::Quick OPCIONAL (→ qtdeclarative, para los bindings QML). PrintSupport/Widgets sólo
|
|
# para el ejemplo (BUILD_TESTING=OFF los evita). XercesC/Python OPCIONALES (omitidos).
|
|
#
|
|
# ⚠️ find_package(Perl REQUIRED): perl regenera las definiciones de sintaxis (data/generators/*.pl,
|
|
# PHP auto-gen). Es dep de build DURA. 'perl' NO está sellado todavía → esta receta NO construye hasta
|
|
# tener recipes/…/perl. Es el único blocker nuevo de esta pieza.
|
|
#
|
|
# rm -rf po poqm: no hay carpeta po en 6.27.0, pero se limpia poqm defensivamente (gettext-tiny/msgfmt
|
|
# crashea con catálogos grandes; ecm_install_po_files_as_qm(poqm) quedaría inerte).
|
|
#
|
|
# ══ ⚠ ERA NO-DETERMINISTA, Y SE ARREGLÓ EL 2026-09-14 (SDD 23) ══════════════════════════════════
|
|
# Dos reconstrucciones con las MISMAS entradas y el MISMO lab daban `libKF6SyntaxHighlighting.so`
|
|
# distintos: 8.800.310 bytes diferentes desde el offset 41, y hasta el TAMAÑO cambiaba
|
|
# (10.345.888 contra 10.345.840). Las únicas cadenas que diferían eran datos comprimidos, o sea el
|
|
# recurso Qt con las definiciones de sintaxis.
|
|
#
|
|
# No era el indexer —`katehighlightingindexer` construye el índice con `QVariantMap`, que es QMap y
|
|
# va ordenado— ni los generadores de Perl, que no iteran hashes. Era `data/generators/
|
|
# generate_jinja.py`, con TRES dependencias del azar:
|
|
#
|
|
# 1. `to_do.pop()` sobre un `set` saca un elemento ARBITRARIO. En `--dry-run` el orden de los
|
|
# `print(out_file)` es lo que CMake recoge en `out_xmls` y acaba siendo **el orden de las
|
|
# entradas del `.qrc`** ⇒ el recurso compilado cambiaba de disposición entera.
|
|
# 2. `version = str(round(time.time()))` hornea la HORA DEL BUILD dentro del XML generado.
|
|
# 3. `os.listdir()` sin ordenar (sólo importa si dos ficheros declaran el mismo lenguaje, pero
|
|
# es una dependencia del readdir y no cuesta nada quitarla).
|
|
#
|
|
# El parche `syntax-highlighting-jinja-reproducible.patch` arregla las tres. MEDIDO en los dos
|
|
# sentidos antes de tocar la receta, corriendo el generador a mano:
|
|
#
|
|
# · antes: tres `PYTHONHASHSEED` distintos ⇒ TRES órdenes distintos de ficheros
|
|
# (`jinja-json, jinja-yaml, jinja-toml…` contra `jinja-qml, jinja-dockerfile, jinja-typescript…`)
|
|
# · después: las mismas tres semillas ⇒ el MISMO md5
|
|
# · y generando de verdad con semillas y momentos distintos: los 35 XML salen IDÉNTICOS,
|
|
# con `version="1"` (de `SOURCE_DATE_EPOCH`, que el sandbox fija)
|
|
# · control negativo: sin `SOURCE_DATE_EPOCH` sigue poniendo la hora actual, o sea que fuera del
|
|
# sandbox se comporta igual que antes
|
|
name = "syntax-highlighting"
|
|
version = "6.27.0"
|
|
license = "LGPL-2.1-or-later OR LGPL-3.0-or-later"
|
|
|
|
[source]
|
|
tarball = "https://download.kde.org/stable/frameworks/6.27/syntax-highlighting-6.27.0.tar.xz"
|
|
sha256 = "cbff001b9f00d032feb254313ecfee9a6e0a0b3c5a8c82a7e0806c5f1915a545"
|
|
patches = ["syntax-highlighting-jinja-reproducible.patch"]
|
|
|
|
[build]
|
|
compiler = "zig-cc"
|
|
target = "x86_64-linux-musl"
|
|
link = "dynamic"
|
|
flags = []
|
|
|
|
[build.phases]
|
|
configure = '''
|
|
rm -rf po poqm
|
|
ZW="$PWD/.zwrap"; mkdir -p "$ZW"
|
|
cat > "$ZW/cc" <<'W'
|
|
#!/bin/sh
|
|
a=""; for x in "$@"; do [ "$x" = "-Wl,--fatal-warnings" ] && continue; a="$a $x"; done
|
|
exec /opt/zig/zig cc -mcpu=baseline $a
|
|
W
|
|
cat > "$ZW/cxx" <<'W'
|
|
#!/bin/sh
|
|
a=""; for x in "$@"; do [ "$x" = "-Wl,--fatal-warnings" ] && continue; a="$a $x"; done
|
|
exec /opt/zig/zig c++ -mcpu=baseline $a
|
|
W
|
|
chmod +x "$ZW/cc" "$ZW/cxx"
|
|
cmake -B build -G Ninja -Wno-dev \
|
|
-DCMAKE_C_COMPILER="$ZW/cc" -DCMAKE_CXX_COMPILER="$ZW/cxx" -DCMAKE_ASM_COMPILER="$ZW/cc" \
|
|
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_PREFIX_PATH=/usr \
|
|
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=OFF \
|
|
-DBUILD_TESTING=OFF -DBUILD_PYTHON_BINDINGS=OFF
|
|
'''
|
|
compile = "cmake --build build"
|
|
install = "DESTDIR=/out cmake --install build"
|
|
|
|
[deps]
|
|
build = ["cmake", "samurai", "python3", "pkgconf", "perl", "qtbase", "qtdeclarative", "dbus", "extra-cmake-modules", "qttools", "mesa", "libdrm", "libxkbcommon", "wayland", "gettext-tiny"]
|