syntax-highlighting: arreglado el no-determinismo — era el generador de Jinja
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.
This commit is contained in:
@@ -233,3 +233,4 @@ ksvg 05e2b73bac4834d960374052796d24ff28fa5d093baf6d4e59169e70001da7c0 2026-09-14
|
||||
qqc2-desktop-style 215bdf3d07e98d5585254060e2cc574c4247b6656e2c221274a0478e5734da49 2026-09-14 reproduce
|
||||
kirigami-addons d826d6b1bddbaa0b78529ca82e915ac92a64ab3148a913fed2ace4958d8a94c1 2026-09-14 reproduce
|
||||
libplasma 73ec5fb279ea44e6bcfdf4c58d8703ed1307ae7985e56ce55a5da078ea098b7e 2026-09-14 reproduce
|
||||
syntax-highlighting 3db73c19bdbddcb046a80d11ec112bc7dc60134eeec75b26e907cc756d25d081 2026-09-14 reproduce
|
||||
|
||||
|
@@ -0,0 +1,50 @@
|
||||
Hacer determinista generate_jinja.py (reproducibilidad — SDD 23)
|
||||
|
||||
El generador de las definiciones Jinja tenía TRES dependencias del azar, y entre
|
||||
ellas hacían que `libKF6SyntaxHighlighting.so` saliera distinto en cada build
|
||||
(8.800.310 bytes distintos y hasta el tamaño cambiaba):
|
||||
|
||||
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 usa para `out_xmls`, que 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 el sandbox de takana ya fija),
|
||||
que es la convención de reproducible-builds; fuera del sandbox se comporta
|
||||
igual que antes.
|
||||
|
||||
3. `os.listdir()` devuelve el orden del sistema de ficheros. Sólo importa si dos
|
||||
ficheros declaran el mismo lenguaje (gana el último), pero ordenarlo cuesta
|
||||
nada y quita la última dependencia del orden de readdir.
|
||||
|
||||
--- a/data/generators/generate_jinja.py
|
||||
+++ b/data/generators/generate_jinja.py
|
||||
@@ -113,7 +113,7 @@
|
||||
to_visit = set()
|
||||
|
||||
for grammar_dir in grammar_dirs:
|
||||
- for file_name in os.listdir(grammar_dir):
|
||||
+ for file_name in sorted(os.listdir(grammar_dir)):
|
||||
if not file_name.lower().endswith('.xml'):
|
||||
continue
|
||||
file_path = os.path.join(grammar_dir, file_name)
|
||||
@@ -151,7 +151,7 @@
|
||||
lang_tag = grammar.getroot()
|
||||
lang_tag.set('name', jinja_tag.get('name') + '/' + lang_tag.get('name'))
|
||||
lang_tag.set('section', jinja_tag.get('section'))
|
||||
- lang_tag.set('version', str(round(time.time())))
|
||||
+ lang_tag.set('version', os.environ.get('SOURCE_DATE_EPOCH') or str(round(time.time())))
|
||||
lang_tag.set('license', jinja_tag.get('license'))
|
||||
lang_tag.set('priority', lang_tag.get('priority', '0'))
|
||||
lang_tag.set('kateversion', max(lang_tag.get('kateversion'),
|
||||
@@ -265,7 +265,8 @@
|
||||
sys.exit(2)
|
||||
|
||||
while to_do:
|
||||
- lang = to_do.pop()
|
||||
+ lang = min(to_do)
|
||||
+ to_do.remove(lang)
|
||||
out_file = os.path.join(args.output_dir,
|
||||
args.prefix + os.path.basename(xmls[lang]))
|
||||
infuse_header(grammars[lang], jinja.getroot(), args.xtra_ext)
|
||||
@@ -12,6 +12,34 @@
|
||||
#
|
||||
# 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"
|
||||
@@ -19,6 +47,7 @@ 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"
|
||||
|
||||
Reference in New Issue
Block a user