# Linux kernel UAPI headers 6.16.12 — tercera pieza del toolchain hammer-from-source (SDD 11 §7.2b).
#
# Tras make (pieza 1) y busybox (pieza 2), reemplazamos los headers del kernel que hoy el builder
# toma del paquete `linux-headers` de Alpine (`/toolchain/usr/include/{linux,asm,asm-generic,…}`).
# musl y busybox los `#include` al compilar (syscalls, ioctls, structs UAPI), así que son parte real
# del toolchain, no mero relleno.
#
# Versión clavada a la del toolchain Alpine actual: `usr/include/linux/version.h` declara 6.16.12
# (LINUX_VERSION_CODE 397324). Construir la MISMA versión es lo que mantiene musl/busybox bit-a-bit:
# un header distinto (un struct/constante que cambió entre versiones) cambiaría el binario resultante.
#
# A diferencia de make/busybox esto NO es un binario: `make headers_install` no compila nada del
# kernel, sólo pasa los headers UAPI por `unifdef` (un toolito host que el propio target construye con
# HOSTCC) y los copia saneados a INSTALL_HDR_PATH. El árbol resultante (`usr/include/*/`) se sella y
# el swap-directorio del builder (variante b) lo monta sobre los de Alpine.
#
# Tarball .tar.gz (no .xz): `tar` lo autodetecta por cabecera y el busybox-tar de adentro descomprime
# gzip nativo, sin depender de un `xz` en el rootfs del Stage 1. El sha256 clava el contenido (ADR 0006).

name    = "linux-headers"
version = "6.16.12"
license = "GPL-2.0-only WITH Linux-syscall-note"

[source]
tarball = "https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/linux-6.16.12.tar.gz"
sha256  = "ffc6af80b014ddebd55e116aa29a9f7a5256c87a29a8a9dd97270b6d49625109"
# Overlay de compatibilidad con el paquete linux-headers de Alpine (ADR 0006: contenido clavado en el
# patch, hasheado al artefacto). El paquete de Alpine NO es el `make headers` crudo: trae 5 archivos
# que difieren de la salida vainilla y que cualquier consumidor userspace (aquí, busybox) necesita
# byte-a-byte para reproducir. El patch los CREA bajo `alpine-overlay/` (no toca el árbol del kernel);
# el `install` los pisa sobre /out tras `make headers`. Por qué overlay y no patch-al-source: `make
# headers` corre unifdef (renombra los guards `_UAPI…`, borra `__force`/`#ifndef __KERNEL__`), así que
# parchear el source daría una salida distinta a la de Alpine; pisar la salida final garantiza igualdad.
#   • linux/kernel.h     — Alpine envuelve `#include <linux/sysinfo.h>` en `#ifdef __GLIBC__` (musl ya
#                          define `struct sysinfo`). Cosmético aquí (nadie del 4/4 lo incluye), pero lo
#                          igualamos para que `diff -r` contra Alpine quede limpio.
#   • linux/if_tunnel.h  — Alpine quita 3 `#include <linux/{if,ip,in6}.h>` (chocan con musl). Cosmético.
#   • scsi/{scsi,scsi_ioctl,sg}.h — REQUERIDOS: el applet `eject` de busybox hace `#include <scsi/sg.h>`
#                          y `<scsi/scsi.h>`. NO son UAPI (no salen de `make headers`); los del kernel en
#                          `include/scsi/` son `__KERNEL__`-only (no compilan en userspace). Alpine trae
#                          versiones legacy userspace-limpias; sin ellas busybox no compila ⇒ divergiría.
patches = ["linux-headers-alpine-compat.patch"]

[build]
compiler = "zig-cc"
target   = "x86_64-linux-musl"
link     = "static"

[deps]
build = ["make"]

[build.phases]
# El árbol del kernel detecta como BuildSys::Make ⇒ el default de compile sería `make -j$(nproc)`,
# que construiría el kernel ENTERO. No queremos eso: los headers no necesitan compilarse ni config.
# Override a no-op; todo el trabajo va en `install`.
compile = "true"
# El target `headers` (NO `headers_install`) construye `scripts/unifdef` con HOSTCC (zig cc) y satura
# los headers UAPI por unifdef hacia `./usr/include` (las líneas `HDRINST …`). Evitamos
# `headers_install` a propósito: su paso final hace un `rsync` de `usr/include` → INSTALL_HDR_PATH, y
# rsync NO está en el toolchain hermético (ADR 0003) — `headers_install` aborta con "rsync: not found".
# En su lugar copiamos el árbol ya saturado con `cp -a` (determinista: of_tree ignora timestamps y
# write-bit, los headers son 0644 sin exec). ARCH=x86 produce los `asm/` de x86_64. Sella
# `usr/include/{linux,asm,asm-generic,cxl,fwctl,misc,mtd,rdma,regulator,scsi,sound,video,xen}`,
# exactamente los subdirs que el paquete linux-headers de Alpine posee.
# 1) `make headers` satura los UAPI en ./usr/include. 2) copiamos a /out. 3) limpiamos lo que el
# rsync de `headers_install` filtra y que `cp -a` arrastró: los `.*.cmd` de kbuild, el Makefile y
# headers_check.pl del propio árbol, y drm/ (Alpine no lo empaqueta). 4) pisamos el overlay de Alpine
# (los 5 archivos del patch) para casar byte-a-byte. Resultado: `diff -r` contra Alpine = vacío.
install = '''
make ARCH=x86 HOSTCC='zig cc -mcpu=baseline' headers && \
mkdir -p /out/usr && cp -a usr/include /out/usr/ && \
find /out/usr/include -name '.*.cmd' -delete && \
rm -f /out/usr/include/Makefile /out/usr/include/headers_check.pl && \
rm -rf /out/usr/include/drm && \
cp -a alpine-overlay/. /out/usr/include/
'''
