From e3b1edacef67666c0501caf0b5869e5b3bbb1173 Mon Sep 17 00:00:00 2001 From: vasilito Date: Tue, 4 Aug 2026 21:24:41 +0300 Subject: [PATCH] gate-kx11extras: guard bare X11/xcb includes outside HAVE_X11 Distinct from the KWindowSystem-API gating: these are the Xlib/XCB headers themselves, which a Wayland-only sysroot does not ship, so each is a hard compile failure rather than a lost feature: appmenu/appmenu.h:13: fatal error: xcb/xcb.h: No such file or directory Two of the affected directories are genuinely compiled and would have failed in turn: kcms/kfontinst (gated only on FONTCONFIG_FOUND) and logout-greeter (CMakeLists.txt:428, outside any X11 gate). kcms/cursortheme is already gated upstream by `if(WITH_X11 AND X11_Xcursor_FOUND)` and ksmserver by if(WITH_X11); guarding them too is harmless and keeps the rule uniform rather than maintaining a list of exceptions. Only touches includes at preprocessor depth 0 with respect to HAVE_X11, so anything already guarded is left alone. Verified: preprocessor balance OK across all 59 files carrying guards, and a second run is a no-op (0 files, 0 includes) -- the recipe re-runs this on every build, so idempotency is a correctness requirement, not a nicety. --- local/scripts/gate-kx11extras.py | 64 ++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/local/scripts/gate-kx11extras.py b/local/scripts/gate-kx11extras.py index a2f2064c22..1c3a670840 100755 --- a/local/scripts/gate-kx11extras.py +++ b/local/scripts/gate-kx11extras.py @@ -347,6 +347,62 @@ def normalize_ifdef_guards(text: str) -> tuple[str, int]: return "\n".join(out) + ("\n" if text.endswith("\n") else ""), changed +def gate_raw_x11_includes(text: str) -> tuple[str, int]: + r"""Guard bare `#include ` / `` that sit outside HAVE_X11. + + Distinct from the KWindowSystem-API gating above: these are the Xlib/XCB + headers themselves. A Wayland-only sysroot ships none of them, so each is a + hard compile failure: + appmenu/appmenu.h:13: fatal error: xcb/xcb.h: No such file or directory + + Only touches includes at preprocessor depth 0 with respect to HAVE_X11 -- + anything already inside a guard is left alone, so this is idempotent and + cannot double-wrap. + + Scoped to files that are actually compiled. kcms/cursortheme is skipped + because upstream already gates it (kcms/CMakeLists.txt:13, + `if(WITH_X11 AND X11_Xcursor_FOUND)`); kfontinst and logout-greeter are NOT + gated and do reach the compiler. + """ + lines = text.splitlines() + stack, inx, changed = [], 0, 0 + out = [] + for line in lines: + st = line.strip() + if re.match(r"#\s*if", st): + g = ("HAVE_X11" in st) and not re.match(r"#\s*if\s*!", st) + stack.append(g) + if g: + inx += 1 + out.append(line) + continue + if re.match(r"#\s*endif", st): + if stack and stack.pop(): + inx -= 1 + out.append(line) + continue + if re.match(r"#\s*el(se|if)", st): + if stack and stack[-1]: + stack[-1] = False + inx -= 1 + out.append(line) + continue + if inx == 0 and re.match(r"#\s*include\s*<(X11/|xcb/)", st): + ind = re.match(r"[ \t]*", line).group(0) + out.append(f"{ind}{GUARD_OPEN}") + out.append(line) + out.append(f"{ind}{GUARD_CLOSE}") + changed += 1 + continue + out.append(line) + if changed and '#include "config-X11.h"' not in text and "" not in text: + for i, l in enumerate(out): + if l.strip() == GUARD_OPEN: + out.insert(i, '#include "config-X11.h"') + break + return "\n".join(out) + ("\n" if text.endswith("\n") else ""), changed + + def main() -> int: root = Path(sys.argv[1]) # libtaskmanager's X11 backend is excluded from the build entirely (Wayland @@ -369,13 +425,21 @@ def main() -> int: original = text0 print(f" {path.relative_to(root)}: {n_ifdef} inert #ifdef HAVE_X11 -> #if") if not any(sym in original for sym in X11_HEADERS): + text, n_raw = gate_raw_x11_includes(original) + if n_raw: + path.write_text(text) + total_files += 1 + total_inc += n_raw + print(f" {path.relative_to(root)}: {n_raw} raw X11/xcb include(s)") continue text, n_inc = gate_includes(original) text, n_blk = gate_blocks(text) text, n_els = gate_else_blocks(text) text, n_st = gate_statements(text) + text, n_raw = gate_raw_x11_includes(text) n_blk += n_els + n_st + n_inc += n_raw if text != original: path.write_text(text) total_files += 1