Pre-existing uncommitted first-party work, surfaced by the first-party
integrity gate. Committing rather than reverting: this code exists nowhere but
this project, so a revert would destroy it outright, and it is coherent and
self-consistent -- a DMI entry for the board plus a test in toml_loader.rs that
parses the REAL 50-system.toml and asserts the entry matches while LG entries
do not.
The quirk carries no flags by design; its comment states it is a bare-metal
anchor so future board-specific quirks can be added precisely. Related to the
Ryzen 7000 / X670E work in .omo/plans/ryzen-7000-x670e-compat.md.
Not authored in this session -- committed here because it blocked every build
and the gate's guidance is to commit or revert, and reverting irreplaceable
work is the wrong call.
plasma-desktop cleared configure and failed in the build:
/bin/sh: .../sysroot/lib/libexec/kf6/kconfig_compiler_kf6: cannot execute
KF6 exports these generators as imported targets whose IMPORTED_LOCATION is the
TARGET (Redox) binary in the sysroot, so cmake tries to run a Redox ELF on the
build host.
Overlays the HOST binary onto the path the imported target points at. Their
output is plain text/XML, so a host build is equivalent, and this keeps the
features ENABLED rather than switching them off. Same block plasma-workspace
already carries -- verified /usr/lib/kf6/kconfig_compiler_kf6 exists on this
host before relying on it.
kcms/keyboard links X11::xkbfile (CMakeLists.txt:37) and cmake aborted with
"Target kded_keyboard links to X11::xkbfile but the target was not found".
libxkbfile was sitting in recipes/wip/x11; promoted, given its util-macros
dependency, and wired into plasma-desktop and the config.
Also clears 9 build directories stranded by the earlier `git mv` out of wip.
Autotools bakes the absolute srcdir into its generated Makefiles, so a moved
recipe keeps building against a path that no longer exists:
No rule to make target
'.../recipes/wip/x11/libxkbfile/source/src/cout.c', needed by 'cout.lo'
The cook-side auto-invalidation added earlier only inspects CMakeCache.txt, so
autotools recipes are not covered by it -- these were latent failures that
would have surfaced one package at a time (libx11, libxcb, libxdmcp, libxft,
libxrender, x11proto, x11proto-kb, xcb-proto, xtrans).
Verified: cook libxkbfile - successful, libxkbfile.a staged.
feature_summary aborted on two REQUIRED packages:
* X11 -- "Required for building the X11 based workspace". The libraries exist
(promoted out of wip and building), but plasma-desktop did not depend on
them, so they were absent from its sysroot and cmake reported X11 missing.
Exactly the gap libxcb had earlier. Added libx11, libxext, libxfixes, libxi,
libxrender, libxau, libxdmcp.
This is where providing the real X11 stack pays off: the alternative was
patching plasma-desktop to stop requiring X11 at all, which is a much larger
and more invasive change than declaring a dependency that already builds.
* KF6DocTools -- not ported, and REQUIRED only because BUILD_DOC defaults ON.
Disabled: this drops generated handbook pages, not functionality; every
settings module still builds.
kcms/touchpad/CMakeLists.txt:18 carries the identical FATAL_ERROR to
kcms/mouse, on the same missing xorg-libinput (the X SERVER input driver, not
portable to a system with no X server). Disabled pre-emptively rather than
after another ~15-minute cycle rediscovers it.
Both KCMs keep their KWin+Wayland backends -- BUILD_KCM_MOUSE_KWIN_WAYLAND and
BUILD_KCM_TOUCHPAD_KWIN_WAYLAND remain ON -- so neither module is lost, only
its unusable X11-session path.
kcms/mouse/CMakeLists.txt:4 gates an X11-specific backend on xorg-libinput,
X11_Xi and X11_Xinput, and aborts naming the remedy:
Missing X11 dependencies for kcm_mouse: xorg-libinput;X11_Xi;X11_Xinput.
Install dependencies or set CMake option -DBUILD_KCM_MOUSE_X11=OFF.
xorg-libinput is the X SERVER input driver -- there is no X server here, so it
is not a porting candidate. This drops only the X11-session backend; the mouse
KCM still builds with its Wayland/libinput backend, which is the one actually
used.
The single sed with an embedded \n had to survive TOML unescaping, then the
shell, then sed's insert parsing -- and it did not. The generated file began
with 'nclude(CheckIncludeFiles)', losing the leading 'i', so configure failed
with
ConfigureChecks.cmake:2 (nclude): Unknown CMake command
My earlier dry-run passed because I ran the sed by hand in the shell rather
than the form the recipe actually produces after parsing. Verified this time by
extracting the commands from the PARSED TOML and running those: the file now
starts with include(CheckFunctionExists) / include(CheckIncludeFiles).
ConfigureChecks.cmake calls check_function_exists() and check_include_files()
without including the modules that define them:
ConfigureChecks.cmake:14: Unknown CMake command "check_function_exists"
Upstream gets away with it because a native KDE configure has already pulled
those modules in transitively by that point; that does not happen here. CMake
documents both as requiring an explicit include(), so adding them is what
upstream should have done rather than a workaround.
ConfigureChecks.cmake:7 does
pkg_get_variable(XKBDIR xkeyboard-config xkb_base)
if (NOT EXISTS "${CMAKE_SYSROOT}/${XKBDIR}")
assuming pkg-config returns an unprefixed path. This build sets
PKG_CONFIG_SYSROOT_DIR, so pkg-config already applies the sysroot and XKBDIR
comes back absolute. Prefixing again produced
.../sysroot//mnt/data/.../sysroot/usr/share/X11/xkb
and configure aborted although the directory is present (verified: the xkb
directory IS in plasma-desktop's sysroot, and xkeyboard-config.pc correctly
records xkb_base=/usr/share/X11/xkb).
Accepts either form instead of un-prefixing XKBDIR: which one pkg-config
returns depends on PKG_CONFIG_SYSROOT_DIR, so testing both is correct in both
configurations and keeps the check meaningful rather than disabling it.
plasma-desktop requires it unconditionally:
CMakeLists.txt:244 pkg_check_modules(XKBREGISTRY xkbregistry REQUIRED ...)
and configure aborted with "The following required packages were not found:
- xkbregistry". The recipe had -Denable-xkbregistry=false.
xkbregistry provides the keyboard-layout registry the keyboard KCM reads, so
this restores a real feature rather than routing around one. Its dependency,
libxml2, was already in the tree (recipes/libs/libxml2) and is now declared and
added to the config.
-Denable-x11 is deliberately left false for now: it is a separate switch, not
required by this failure, and turning it on alongside would blur which change
fixed what if the rebuild misbehaves.
I tried resetting the build dir whenever rsync reported changed files, to catch
stale GENERATED build files after a recipe edit -- the xcb-util-image case where
the staged source said `SUBDIRS = image` but build/Makefile still said
`SUBDIRS = image test`, so a correct fix looked like it had no effect.
That signal is wrong. --delete restores the pristine tree, undoing the previous
build's seds, so rsync reports changes on EVERY run. Measured on a plain
kirigami rebuild: 6 "changed" files that were only the sed undo, and the build
dir was wiped. Shipping it would have forced a full rebuild of every recipe on
every build.
Reverted, with the reasoning recorded at the call site so it is not attempted
again. Stale generated files are the job of the content-hash invalidation the
cookbook already performs against the PRISTINE source; the staged copy is not a
valid basis for that comparison.
Verified after revert: kirigami is cached again rather than rebuilding.
Three separate defects, one per class:
1. script.rs passed autoreconf only -I${COOKBOOK_HOST_SYSROOT}/share/aclocal, so
macros installed by a DEPENDENCY into the per-recipe sysroot were invisible.
util-macros was built and declared as a dependency, yet configure still said
configure.ac:10: error: must install xorg-macros 1.16.0 or later
Now also searches ${COOKBOOK_SYSROOT}/usr/share/aclocal and exports
ACLOCAL_PATH. Fixed generically -- every autotools recipe benefits.
2. Upstream builds test/test_xcb_image_shm unconditionally (Makefile.am:15
SUBDIRS = image test) and it needs SysV shared memory, which Redox lacks.
The library itself does not: configure only probes sys/shm.h and adapts. So
dropping test/ removes a test binary, not functionality.
3. libxcb is a STATIC archive here, so its libXau/libXdmcp dependencies do not
propagate to consumers as a shared library's DT_NEEDED would:
xcb_auth.c: undefined reference to `XauGetBestAuthByAddr'
Named them via LIBS, not LDFLAGS: autoconf emits LDFLAGS BEFORE the objects
and LIBS AFTER, and a static archive only satisfies symbols referenced by
objects preceding it. With -lXau in LDFLAGS the link still failed while
libXau.a sat in the sysroot. Same ordering rule as -lgcc in
redox-toolchain.cmake and -licudata in plasma-workspace -- third occurrence.
Verified: cook xcb-util-image - successful, libxcb-image.a staged.
xcb-util and xcb-util-image start configure.ac with XORG_MACROS_VERSION(), so
autoreconf dies before configure runs:
configure.ac:10: error: must install xorg-macros 1.16.0 or later before
running autoconf/autogen
libice failed identically earlier -- it was dropped as unnecessary, but
xcb-util-image is genuinely required (plasma-desktop needs the XCB IMAGE
component), so the macros had to be ported rather than routed around.
util-macros ships only autoconf m4 text and a pkg-config file -- no compiled
code, so no cross-compilation concern. Installed into the sysroot's
share/aclocal, which is already the directory the cookbook passes to
autoreconf (-I .../sysroot//share/aclocal), so consumers need no other change.
Verified by cooking it standalone before wiring it in: builds successfully and
stages usr/share/aclocal/xorg-macros.m4. The recipe asserts that file exists,
since a silent no-op would resurface as the same "must install xorg-macros"
error in a consumer, far from the cause.
plasma-desktop's CMakeLists.txt:223 does
find_package(XCB REQUIRED COMPONENTS XCB SHM IMAGE)
and configure aborted with "Could NOT find XCB (missing: XCB_LIBRARIES XCB SHM
IMAGE)" -- libxcb was promoted but plasma-desktop did not depend on it, so it
was absent from that recipe's sysroot.
libxcb supplies xcb and xcb-shm (libxcb-shm.a confirmed staged); IMAGE comes
from xcb-util-image, which needs xcb-util. Both promoted out of recipes/wip/x11
and their tarballs fetched and blake3-verified.
This is the case for xcb on Wayland, not X11 nostalgia: KDE's XWayland
integration and Qt's xcb platform plugin both reference these.
plasma-workspace now builds and installs, so plasma-desktop configured for the
first time and stopped at:
The following required packages were not found: - libwacom
kcms/tablet requires libwacom (CMakeLists.txt:175), which is not ported -- it
needs libgudev plus upstream's tablet-definition database. Disabled via
upstream's own option (CMakeLists.txt:44, default ON), not an invented switch;
it gates exactly three sources (tabletsmodel.cpp, kcmtablet.cpp,
tabletmoduledata.cpp) and nothing else in plasma-desktop is affected.
THIS REMOVES THE DRAWING-TABLET SETTINGS MODULE. Tracked as a real port; the
option goes back ON in the same change that lands libwacom.
plasma-workspace COMPILED AND LINKED COMPLETELY and then failed at install:
file INSTALL cannot copy ".../libnotificationmanager/plasmanotifyrc"
to "/etc/xdg/plasmanotifyrc": Permission denied
`cmake --install --prefix` re-roots only RELATIVE destinations. KDE's
KDE_INSTALL_FULL_* paths are absolute, so cmake tried to write into the BUILD
HOST's /etc -- only the host's permissions stopped it from polluting the host
filesystem. DESTDIR re-roots absolute destinations too. Same fix already
applied to kf6-ktexteditor, kde-cli-tools and sddm.
plasma-desktop gets the same fix pre-emptively: it ships /etc/xdg config and
has never been built, so this would otherwise have cost another full cycle.
54 other KDE recipes use the --prefix form but install nothing to an absolute
path, which is why they build clean; left alone rather than churned.
kcm_users failed with 'ld: cannot find -lcrypt' although libc.a exports crypt
and crypt_r. relibc now ships empty libcrypt.a/libutil.a so the link resolves
from libc, matching what it already does for libdl/libpthread/librt.
KWindowSystem ships fixx11h.h (X11 macro cleanup), netwm.h and netwm_def.h
(EWMH) only with its X11 component, so a Wayland-only install lacks them. They
carry no X11/ or xcb/ path prefix, so the prefix-only rule missed them:
logout-greeter/shutdowndlg.cpp:51: fatal error: fixx11h.h: No such file
The single remaining unguarded case is libtaskmanager/xwindowtasksmodel.cpp,
which upstream excludes from the build via if(HAVE_X11) in
libtaskmanager/CMakeLists.txt -- it is never compiled, so it is left alone
rather than edited for appearance.
Converting `#ifdef HAVE_X11` to `#if HAVE_X11` changes the question from "does
this macro exist" to "what is its value", so the definition must actually be in
scope. Doing the conversion without guaranteeing the include turned a silently
inert guard into a hard error:
shell/panelview.h:13: error: 'HAVE_X11' is not defined, evaluates to 0
KDE builds with -Werror=undef, so an undefined macro in #if is fatal. The
previous commit fixed the guard form and introduced this; the transform now
inserts #include <config-X11.h> when it converts a guard in a file that lacks
it.
Verified: panelview.h now carries the include, and a second run is a no-op.
fetch_offline hashed source.tar BEFORE checking it exists, so a missing tarball
surfaced as
repo: failed to fetch: Opening file for blake3 failed at
"recipes/x11/libice/source.tar": No such file (os error 2)
which names neither the recipe nor the remedy. That message sent me to work
around the symptom by hand twice -- libogg/libvorbis, then four newly promoted
X11 recipes -- because it points at hashing rather than at a missing download.
Now it reports the recipe, the upstream URL and the exact curl command.
Also drops libice/libsm from redbear-full. They are X11 session-management
libraries used only by ksmserver, which sits inside if(WITH_X11) and is not
built, and they need xorg util-macros, which no recipe in the tree provides.
Including them would have meant porting a build dependency for code that is
never compiled.
Reverses this session's approach. Gating X11 out kept producing failures in a
new syntactic shape each build -- API calls, else-chains, standalone statements,
inert #ifdef guards, bare X11/xcb includes, namespace definitions -- six shapes,
each needing its own rule in gate-kx11extras.py. Providing the real headers and
libraries removes the cause rather than adding a seventh rule.
The stack was already ported and building; it was just parked in recipes/wip.
Verified before promoting: xcb-proto, libxcb, libx11, x11proto and xtrans cook
(cached from earlier builds), libxrender and libxft built successfully, and the
key headers are staged -- xcb/xcb.h, X11/Xlib.h, X11/Xft/Xft.h -- with 25 libs
and 33 headers from libxcb alone. Real upstream releases pinned by blake3
(libxcb 1.17.0, libX11 1.8.12), not stubs.
Promoted: x11proto-kb, xtrans, xcb-proto, libxcb, libx11, libxdmcp, libxext,
libxfixes, libxi, libxrender, libxft, libice, libsm (recipes/x11/) and
libpthread-stubs (recipes/libs/). x11proto was already in the config.
xcb is needed on Wayland too -- Qt's xcb platform plugin, libxkbcommon-x11 and
KDE's XWayland integration all reference it -- so this is not X11-only value.
These remain CLIENT libraries: isPlatformX11() stays false at runtime and the
X11 paths do not execute unless Xwayland is up. The port buys compilation
compatibility, not X11 functionality.
libtaskmanager/virtualdesktopinfo.cpp defines namespace X11Info at namespace
scope in terms of QNativeInterface::QX11Application, which does not exist in a
Qt built without the xcb platform:
error: 'QX11Application' is not a member of 'QNativeInterface'
All three call sites were already inside #if HAVE_X11 -- only the definition
was exposed -- so wrapping the block changes no reachable behaviour.
Restricted to depth-0 'namespace' blocks whose body names an X11-only native
interface. Narrow on purpose: brace-matching arbitrary function definitions is
much easier to get wrong, and a bad transform here produces invalid C++ rather
than a clean failure.
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.
config-X11.h.cmake declares the macro with `#cmakedefine01 HAVE_X11`, which
always DEFINES it -- as 0 when X11 is off, not undefined. So `#ifdef HAVE_X11`
is true in BOTH configurations and the guard does nothing:
#ifdef HAVE_X11
#include <xcb/xcb.h> <- compiled even with HAVE_X11 == 0
#endif
That is how appmenu.h reached
appmenu/appmenu.h:13:10: fatal error: xcb/xcb.h: No such file or directory
while looking correctly guarded. `#if HAVE_X11` reads the value and behaves as
intended.
An upstream bug invisible on any system that has X11 headers installed, because
there the include just succeeds. 3 occurrences across appmenu.h and
panelview.h; plasma-desktop has none. Normalisation runs on every file rather
than only those using the X11-only KWindowSystem APIs, since the defect is
about the guard form, not the guarded content.
-Wa,--noexecstack did not reach icudt75l_dat.o: ICU builds it through pkgdata,
which drives the assembler with its own flags and ignores CFLAGS. Verified
empirically -- after a full ICU rebuild readelf still showed 0 GNU-stack
sections, and plasma-workspace failed identically.
Patching the archive member is deterministic where the flag was not. The added
section is empty and read-only: it declares a non-executable stack, which is
exactly true for a pure data blob. Verified objcopy 0 -> 1 section on the real
archive before committing.
Without it, binutils warns "missing .note.GNU-stack section implies executable
stack", and KDE's ECM links with -Wl,--fatal-warnings, so every KDE consumer of
static ICU fails (plasma-workspace applets/digital-clock, ld exit 1).
Asserts the section is present afterwards rather than swallowing errors: a
silent no-op here resurfaces as a link failure in a different package, far from
the cause.
Both found by pre-checking plasma-desktop against the failure classes already
catalogued, before it was ever attempted -- rather than discovering them one
~15-minute build at a time.
1. KSMServerDBusInterface. plasma-desktop hard-requires it (CMakeLists.txt:191,
CONFIG REQUIRED), but upstream generates it in ksmserver/CMakeLists.txt and
add_subdirectory(ksmserver) sits inside if(WITH_X11) -- OFF here -- so a
Wayland-only build never installs it. Only the D-Bus INTERFACE is needed:
the XML is a platform-independent description and upstream's
KSMServerDBusInterfaceConfig.cmake.in is a single variable pointing at it.
ksmserver itself is X11-only (links X11::X11/SM/ICE and PW::KScreenLocker)
and stays unbuilt. XML copied verbatim from the upstream tree. Same shape and
same remedy as kscreenlocker.
KRunnerAppDBusInterface, also REQUIRED by plasma-desktop, needs nothing:
add_subdirectory(krunner) is outside the X11 gate.
2. X11-only KWindowSystem headers, reusing gate-kx11extras.py unchanged:
KX11Extras (4 files), KUserTimestamp (1), KWindowInfo (2).
Dry-run on the plasma-desktop tree: 3 files gated, 5 includes, 6 blocks;
preprocessor balance OK across all 5 files carrying guards; no malformed
'#endif <code>'; no unguarded references left. Source restored afterwards --
the recipe applies this at build time.
ICU emits its data as generated assembly (icudt75l_dat.S). Without
-Wa,--noexecstack the assembler produces an object with no .note.GNU-stack
section, and modern binutils warns:
ld: warning: icudt75l_dat.o: missing .note.GNU-stack section implies
executable stack
Harmless alone -- except KDE's ECM links with -Wl,--fatal-warnings, so every
KDE consumer of static ICU fails outright (first hit: plasma-workspace
applets/digital-clock, collect2: error: ld returned 1). Fixed at the source
rather than suppressed downstream, which would have to be repeated per consumer.
Also gates the '#'-inside-a-backslash-continuation trap, which terminates the
continuation and silently drops every remaining argument. It has now bitten
three times, most recently while writing THIS commit: the noexecstack rationale
was first placed between two continued configure flags, which would have
dropped the rest of ICU's configure line. Moved above the invocation.
The check scans the RAW file, not the parsed TOML. In a multi-line basic string
a trailing backslash is itself a TOML line-continuation escape, so the newline
is gone before the value is handed over and the parsed string has no trailing
backslashes at all. The first version scanned the parsed value and silently
found nothing -- caught by a self-test, not by review, which is the same class
of invisible failure the gate exists to prevent.
ICU is built static here (--enable-static --disable-shared, and
--with-data-packaging=static), so the data blob lives in libicudata.a. CMake's
builtin FindICU exposes ICU::uc and ICU::i18n but not ICU::data, and a static
archive carries no DT_NEEDED to pull the data in the way libicuuc.so would on a
normal system. The digital-clock plugin failed to link:
udata.cpp:(.text+0xea1): undefined reference to `icudt75_dat'
STANDARD_LIBRARIES rather than LINKER_FLAGS: the latter is emitted before the
object files, where a static archive contributes nothing. Same reasoning as the
-lgcc entry in redox-toolchain.cmake.
Scoped to this recipe rather than the shared toolchain: not every recipe using
that toolchain stages ICU, so a blanket -licudata would become "cannot find
-licudata" for them.
Two coupled problems, both restored by the `git checkout -- local/recipes/`
revert that undid this session's uncommitted recipe work.
1. A '#' comment block sat INSIDE the backslash-continued cmake invocation. A
comment line terminates the continuation, so every flag after it was silently
dropped -- SCREENLOCKER, TABBOX, GLOBALSHORTCUTS, RUNNERS and the rest took
cmake's defaults instead of the values written here. The recipe already
carries a NOTE warning about exactly this trap; the rationale text is now
above the invocation where it cannot truncate anything.
2. With the flag dropped, KWIN_BUILD_SCREENLOCKER defaulted ON, and kwin gates
find_package(KScreenLocker) on it (source/CMakeLists.txt:376), so configure
aborted:
The following REQUIRED packages have not been found:
* KScreenLocker For screenlocker integration in kwin_wayland
kscreenlocker ships only the ScreenSaverDBusInterface package; the library
still needs its Wayland-only port.
Set OFF explicitly. THIS MEANS THERE IS NO LOCK SCREEN -- documented at the flag
and in the kscreenlocker recipe. Turn it back ON in the same change that lands
the library port.
Verified: 0 comment lines remain inside the invocation.
QQmlEngine::networkAccessManager() exists only under QT_CONFIG(qml_network),
a qtdeclarative feature separate from QT_FEATURE_network, which was already ON.
kirigami failed on it:
src/primitives/icon.cpp:469: 'class QQmlEngine' has no member named
'networkAccessManager'
qtbase builds libQt6Network here, so enabling the feature restores kirigami's
remote icon loading instead of compiling the capability out.
This rewrite was lost when `git checkout -- local/recipes/` reverted every
uncommitted recipe edit, so the full-build version came back and the build tried
to compile the X11 locker on a Wayland-only target:
globalaccel.cpp:8 fatal error: KKeyServer
x11locker.h:15 fatal error: X11/Xlib.h
greeter/greeterapp.cpp:63 fatal error: X11/Xatom.h
plasma-workspace needs only ScreenSaverDBusInterface (CMakeLists.txt:127), used
in three qt_add_dbus_interface calls that generate a D-Bus client proxy from the
XML; it never links the library. The one consumer that does link
PW::KScreenLocker is ksmserver, which sits inside if(WITH_X11) and is not built.
The library port (~61 X11/XCB sites) and KWIN_BUILD_SCREENLOCKER remain open
work, documented in the recipe. Both installed files are verbatim upstream
artefacts -- nothing fabricated.
A recipe whose script exits 0 but installs nothing currently reports success,
and the damage lands far from the cause. qtspeech produced a 136-byte package
because upstream `return()`s with only a NOTICE when Qt6::Multimedia is absent;
that surfaced much later as an unresolved symbol in a consumer, not as a
qtspeech failure.
Zero regular files staged is unambiguous -- every real package installs at
least one file -- so this needs no per-recipe size threshold and cannot
false-positive on a small-but-valid package. The error names the likely cause
(a configure step soft-bailing on a missing optional dependency) rather than
just reporting emptiness. Metapackages that genuinely stage nothing opt out by
mentioning COOKBOOK_ALLOW_EMPTY_PACKAGE in their script.
This is the same failure shape as the libudev/libpciaccess API-surface risk: a
gap that reports success locally and only becomes visible as a link error in
something downstream.
These three carried only `path = "source"` with no origin recorded anywhere, so
nothing could distinguish them from Red Bear's own code and the first-party
integrity gate classified them as ours. URLs and versions taken from evidence
in each source tree, not guessed:
libepoxy github.com/anholt/libepoxy meson version 1.5.10
libxcvt gitlab.freedesktop.org/xorg/lib/libxcvt meson version 0.1.3
libdisplay-info gitlab.freedesktop.org/emersion/... meson version 0.4.0
NOT applied to libpciaccess or libudev, which were named alongside these as
upstream. Their source trees are 2 files / 272 lines and 3 files / 1314 lines
respectively -- these are Red Bear's own minimal implementations of those APIs,
not vendored copies of the upstream projects, which are far larger. Recording a
fake upstream for them would downgrade the gate from fatal to a warning on
first-party code, which is the one error direction that loses work that exists
nowhere else. Flagged for confirmation rather than assumed.
brush records `# Upstream: https://github.com/reubeno/brush`, but the check
matched `upstream:` case-sensitively AND required the URL to end in .tar/.git,
so it missed on both counts and filed a genuine fork as first-party.
Now matches an explicit upstream/snapshot/origin label followed by a URL, any
case. Deliberately NOT any bare URL in a comment: a stray bug-tracker link must
never read as provenance, since that error direction (first-party treated as
vendored) is the one that loses irreplaceable work.
Remaining inaccuracy is missing DATA, not detection. libepoxy, libpciaccess,
libudev, libxcvt and libdisplay-info are upstream projects whose recipes carry
only `path = "source"` with no origin recorded anywhere, so nothing can tell
them apart from our own code. They classify first-party, which is merely
stricter. The real fix is to record their upstream in the recipe.
The name list was wrong in principle. It started as redbear-*, then needed cub,
then tlc -- and protection that depends on someone remembering to edit this file
is not protection. A new internal program starts out unguarded and the omission
stays invisible until the code is already gone. tlc proved it: first-party,
exempt from out-of-tree staging, protected by nothing but this gate, and
matching no pattern.
The real property is structural -- our code has no upstream to restore from. A
recipe is first-party when its recipe.toml records no fetchable origin: no
`tar =`, no `git =`, no upstream URL. That identifies ~96 recipes against the 3
the list covered, so the list was guarding roughly 3% of the exposure.
The heuristic errs toward first-party deliberately. A vendored recipe recording
its origin only in prose gets treated as ours, which just makes drift fatal
instead of a warning. The opposite error loses irreplaceable work, so the
default fails in the safe direction.
Verified: fires on redbear-netctl, cub and tlc (none of which are named
anywhere in the code now); does NOT fire on vendored kirigami; silent on a
clean tree; every probe restores.
Extends the fatal first-party check beyond redbear-* to cub (system) and tlc
(tui). Both are Red Bear's own programs with no upstream anywhere, so the
"restore it from the tarball" recovery that makes vendored drift a warning does
not exist for them.
They sit on opposite sides of the staging boundary, which is why both need the
gate for different reasons:
cub is staged out of tree (no escaping cargo path deps), so staging already
keeps recipe seds off the tracked copy.
tlc is EXEMPT from staging: its manifest has a path dependency escaping the
source tree, so nothing keeps a sed off the real files. For tlc this
gate is the only protection.
The check is now a redbear_is_firstparty() helper rather than an inline glob, so
adding the next internal program is one line.
Verified: silent on a clean tree; fires on a one-line edit to cub and to tlc;
both restore cleanly.
redbear-* recipes are not vendored upstream code -- they are Red Bear's own
programs and exist nowhere else. A vendored tree can be restored from its
tarball or git remote; first-party source cannot. If a recipe sed or an `rm`
damages it and that gets committed, the work is gone.
Not hypothetical. Seven redbear-* recipes rewrite their own source during the
build (greeter, btusb, btctl, ime, dnsd, accessibility, keymapd), and all seven
are exempt from out-of-tree staging because their cargo manifests carry path
dependencies escaping the source tree. They are simultaneously the least
protected and the most irreplaceable code here.
Uncommitted drift in them now fails preflight instead of printing a note that
scrolls past. Vendored trees keep the existing warn-by-default behaviour.
Override: REDBEAR_ALLOW_DIRTY_FIRSTPARTY=1.
Verified: gate is silent on a clean tree, fires on a one-line edit to
redbear-authd, and the tree restores cleanly.
redbear-greeter's manifest has
redbear-login-protocol = { path = "../../redbear-login-protocol/source" }
Cargo resolves that relative to the manifest, so out-of-tree staging pointed it
at <recipe>/target/redbear-login-protocol/source:
failed to read .../target/redbear-login-protocol/source/Cargo.toml
No such file or directory (os error 2)
Rewriting the manifest would silently change dependency paths behind the
recipe's back. Leaving these in tree is the honest option: they are cargo
recipes that do not sed their source, so the mutation risk staging exists to
prevent does not apply to them.
Two systemic fixes for failure classes this session kept re-hitting.
1. COOK_JOBS default 4 -> 1. Recipes are not isolated: redbear_qt_ensure_dep_
sysroots repairs OTHER recipes' sysroots, so one cook can relink the include/
or lib/ directory another is compiling against. The tell was a failure that
MOVED between source files across runs (kirigami died in KirigamiTemplates on
build 59, KirigamiPrivateplugin on 61) with a sibling's rm -f/ln -sf
interleaved in the log. Making the relink atomic closed one window; the
sharing itself remains unsound. Compilation is still parallel -- each recipe
keeps the full -j budget -- only the number of recipes in flight drops to 1.
An intermittent build costs more than a serial one.
2. Auto-reset build dirs whose CMakeCache records a different source path.
CMake stores CMAKE_HOME_DIRECTORY and hard-aborts when the source moves:
CMake Error: The source ".../source-staged/..." does not match the source
... used to generate cache
Out-of-tree staging moved every tracked recipe's source and stranded 66 build
dirs. Two rounds of clearing them by hand were not a fix: the next source-path
change strands them again, and the abort surfaces in a downstream recipe
rather than at the cause. cook now detects the mismatch and resets the dir.
Out-of-tree staging made the checker scan source-staged/, which holds the same
upstream third-party patches as source/ -- already skipped because they are not
ours to fix. qtdeclarative's bundled yoga patch then failed the build at
preflight. Same rationale as the existing /source/ entry.
Two defects in the out-of-tree staging from 221a91cba4/a3d9240d62, both found
by actually running it rather than by inspection.
1. Submodules were staged. `git ls-files --error-unmatch` succeeds on a
gitlink, so relibc looked like an ordinary tracked tree and was copied
wholesale, losing the nested-repo context cargo needs -- crt0, crti, crtn
and ld_so all failed to build. Fork submodules are already covered by the
stricter REFUSING-TO-BUILD dirty gate, so skipping them loses no protection.
2. `rm -rf` before the copy made the staged path vanish mid-build. Qt bakes its
COOKBOOK_SOURCE into installed cmake files (QtSeparateDebugInfo.cmake
try_compile()s ${QT_SOURCE_TREE}/config.tests/...), so once that path was the
staged tree, rebuilding qtbase pulled it out from under consumers:
CMake Error: The source ".../qtbase/.../source-staged/config.tests/
binary_for_strip/CMakeLists.txt" does not ...
(qtsvg and qtshadertools). Now rsync -a --delete refreshes in place: same
pristine result, but the directory never stops existing. Verified with 4000
probes across a full kirigami rebuild -- 0 observations of it missing.
Staging is confirmed working: a 26-package run staged 10 trees, skipped relibc,
and left 0 dirty tracked source files (previously 22-29).
redbear_qt_ensure_dep_sysroots repairs OTHER recipes' sysroots, so with
COOKBOOK_COOK_JOBS>1 it runs while a parallel cook is compiling against the
very directory it is relinking. It did `rm -f` then `ln -sf`, leaving a window
where the path did not exist. kirigami died in that window:
cstdio:47: fatal error:
.../qtdeclarative/target/.../sysroot/include/stdio.h: No such file
with another cook's `rm -f`/`ln -sf` on qtdeclarative's sysroot interleaved in
the same log.
Now: skip entirely when the link already points at the right target (the
common case, and the cheapest way to stop the churn), otherwise replace via
ln -s to a temp name + `mv -T`, a single rename(2) -- readers see the old link
or the new one, never nothing.
Verified with 300 concurrent relinks against 3000 probes: 0 missing
observations, where the old sequence reproduced the gap.
The out-of-tree staging added in 221a91cba4 never actually ran. Recipes are
reached through the overlay path `recipes/<cat>/<name>`, a symlink into
`local/recipes/...`, and `git ls-files --error-unmatch` refuses any pathspec
that traverses a symlink ("pathspec is behind a symbolic link"). The check
therefore reported every tracked vendored tree as untracked, staging was
skipped, and builds went on mutating git-tracked sources -- 22 dirty source
files after a 42-package run.
Canonicalize the path before both the git query and the copy. Verified: the
check fails via the symlink, succeeds via the resolved path, and cooking
kirigami now logs
[out-of-tree] staged tracked source -> .../kirigami/target/.../source-staged
with the recipe's sed rewriting the staged copy instead of the tracked tree.
Points the relibc submodule at 4e9fbf4c. sys/timerfd.h and sys/signalfd.h
declare their prototypes in the cbindgen trailer, which is emitted outside the
extern "C" block cpp_compat generates, so C++ consumers linked against a
mangled name while relibc exports the plain C symbol:
alignedtimer.cpp:(.text+0x29a): undefined reference to
`timerfd_create(int, int)'
(plasma-workspace libclock). C callers were unaffected, which is why it
survived until a C++ consumer appeared.
Also refreshes the tracked-source baseline. This should become largely static
now that cook stages tracked vendored sources out of tree.
libcanberra: plasma-workspace calls find_package(Canberra) TYPE REQUIRED and
includes <canberra.h> from four translation units with no HAVE_CANBERRA guard,
one of them libnotificationmanager (the core notification library). It cannot
be made optional, so it is ported for real. Built shared: it dlopens its
backend through libltdl, the libtool recipe stages libltdl.so only (no .a), so
a static build left every consumer with an undefined lt_dlopenext.
Audio is SILENT. Upstream 0.30 offers alsa/oss/pulse/gstreamer/null and none
speak Redox; the pulse driver needs PulseAudio's client library, which PipeWire
does not provide. The null driver is real upstream code, so the API/ABI is
genuine and all consumers work -- but nothing reaches the speakers until a
native /scheme/audio driver exists.
KX11Extras et al: gate the five X11-only KWindowSystem headers behind the
HAVE_X11 that plasma-workspace already defines. X11 is compiled OUT, not added.
gate-kx11extras.py brace-matches each block and keeps any trailing else outside
the guard, since wrapping a whole if/else-if chain yields invalid C++.
check-recipe-escapes.py: a single backslash in a TOML multi-line string is a
TOML escape, so a sed written as \bFoo\b parses to <BS>Foo<BS> and silently
matches nothing -- no TOML error, no sed error. This class bit the tree three
times. Now gated in preflight; it also found openssh, which used an invalid \$
and could not be parsed by any compliant parser.
cook_build.rs: build git-tracked vendored sources OUT OF TREE. Recipe scripts
rewrite their source, so builds were mutating version-controlled files: a
no-op sed became indistinguishable from a working one, and the integrity gate
fired so often that clearing it stopped being protective. Uses
cp -a --reflink=auto, not cp -al: sed -i is link-safe but `cp -f` and `>`
truncate in place and would write through a hard link into the tracked
original. Content hashing still runs against the pristine tree, so hashes now
describe committed state. Escape hatch: REDBEAR_IN_TREE_BUILD=1.
Unblocks plasma-workspace/plasma-desktop, which required 14 packages that had
no in-tree recipe. Sources are reproducible from each recipe's tar= + blake3;
the vendored source/ trees are deliberately not committed here (212M).
New recipes:
KF6 6.28.0 kf6-kholidays, kf6-krunner, kf6-kstatusnotifieritem,
kf6-kunitconversion
Plasma 6.7.2 knighttime, layer-shell-qt, libkscreen, libksysguard,
plasma-activities-stats, plasma5support, kscreenlocker
Qt 6.11.1 qtpositioning, qtspeech, qttools
libksysguard carries P0-redox-process-backend.patch: processes_local_p.cpp
dispatches on platform macros and had no __redox__ arm, so ProcessesLocal was
entirely undefined. Adds a real backend reading /scheme/proc/ps (pid, ppid,
real+effective ids, thread count, state) and /scheme/sys/mem, with kill() for
signals. Upstream's generic fallback is a pure stub and was not used. Absent
facilities (no setpriority/sched_setscheduler/ioprio on a microkernel) report
NotSupported rather than pretending.
Restored, no longer disabled:
- night colour: kcms/nighttime + kwin's nightlight plugin, now that
KNightTime/Qt6Positioning/KF6Holidays exist
- KIO FileWidgets (file dialog, places model), wrongly swept in with the
unportable kiod/kssld/kioworkers subdirs
- kf6-ktexteditor text-to-speech: removes a disguised stub that rewrote
speechEngine() to return nullptr and mangled call sites into invalid C++
- kwin KWIN_BUILD_SCREENLOCKER=ON (needs kscreenlocker; see below)
Toolchain and recipe fixes:
- redox-toolchain.cmake: append -lgcc. __extendhfsf2/__extendbfsf2 are
global in libgcc.a but hidden in libgcc_s.so (the Redox libgcc version map
stops at GCC_7.0.0 and never emits the GCC_12/13 nodes upstream exports),
and GCC omits -lgcc for -shared, so no C++23 shared library using
std::format<_Float16|bfloat16_t> could link.
- qtmultimedia: rewrite /usr/src/.../meta_types paths and stage metatypes,
so consumers using qt_internal_add_qml_module can configure.
- qtspeech: qtmultimedia is mandatory, not optional -- upstream return()s
with only a NOTICE without it, yielding a green build over an empty
package. Asserts its own output so that cannot recur.
- narrow Linux-only guards with AND NOT REDOX where the toolchain sets
CMAKE_SYSTEM_NAME=Linux purely to get UNIX=TRUE (kio LibMount,
libksysguard NL/Sensors, plasma-workspace NetworkManagerQt).
- drop REQUIRED components that are declared but referenced nowhere
(Location, QCoro6, Qt6 Test) -- verified by exhaustive grep.
- DESTDIR installs where KDE emits absolute KDE_INSTALL_FULL_* paths that
--prefix cannot re-root, which otherwise write into the build host.
Auth stack:
- pam-redbear: add PAM_MODULE_UNKNOWN (28), missing from both the header and
lib.rs; realign 30/31 to Linux-PAM's PAM_CONV_AGAIN/PAM_INCOMPLETE, which
previously held Red Bear-only names on standard values, so anything built
against stock PAM headers mis-decoded them.
- redbear-authd: support yescrypt ($y$ -- the default shadow format on
current Debian/Ubuntu/Fedora, previously an unexplained login failure),
bcrypt and md5-crypt. Plaintext shadow entries now require the
/etc/redbear/allow-plaintext-passwords sentinel and warn on every use,
instead of being compared silently. 19/19 host tests pass.
Build-system hardening:
- verify-tracked-sources.sh, wired into preflight: fails on deletion of any
tracked vendored source, and on modifications with no baseline entry.
local/sources/ had a dirty gate and version checks; local/recipes/*/source/
had none, which allowed an rm -rf to delete 7958 tracked files and a
pristine re-extract to silently overwrite committed fixes (kwin's
std::expected/vulkan-hpp and X11 gating, kio's Q_OS_REDOX resolver guards).
- validate-source-trees.py: resolve recipe.toml through the overlay symlink;
it reported false MISSING for symlinked recipes.
- test-sddm-virgl-qemu.sh: the null-proxy check used report(), which PASSES
on regex match -- so the known Qt6 Wayland null+8 fault would report PASS
when present. Added report_absent().
kscreenlocker builds only its cmake-level Wayland-only changes so far; the
C++ X11 removal (61 call sites) is not yet applied, so kwin's screenlocker
flag is blocked on it.