fix: cross-build host-tool resolution and staging correctness

Four distinct ways the cross build reached for the wrong thing:

mesa-clc: 'unset LDFLAGS' left only /usr/lib on the link path, so the
HOST libLLVM won over llvm-native. Arch-family builds use
-DLLVM_LINK_LLVM_DYLIB, so libLLVM re-exports libstdc++ symbols under its
own version node; mesa_clc then recorded std::string::reserve@LLVM_21.1,
which no llvm-native build provides. When it instead resolved the host
libLLVM at runtime, clang derived its resource dir from the HOST install,
and with host clang 22 beside an llvm-runtime 21.1 the directory
/usr/lib/clang/21 does not exist, so every OpenCL compile died with
"'opencl-c-base.h' file not found" -- nowhere near the cause. Put
llvm-native back on the link path with a matching -rpath, and pin the
staged tools' RUNPATH to this recipe's own sysroot. Also wipe build-clc
before meson setup: re-running setup on a configured dir reinterprets -D
flags as option CHANGES and aborts on any option the old configuration
lacked ("Unknown option: mesa-clc").

breeze: kconfig_compiler_kf6 resolved to the cross-compiled Redox binary,
which the host cannot execute ('cannot execute: required file not found'
is ENOENT on the ELF interpreter). Point at the host tool.

kde-cli-tools: installs to KDE_INSTALL_FULL_BINDIR, an ABSOLUTE /usr/bin.
'cmake --install --prefix' only re-roots relative destinations, so cmake
wrote straight into the BUILD HOST's filesystem and only file permissions
stopped it. Use DESTDIR, which re-roots absolute paths too. kstart is
X11-only (Qt private X11 interop header) and cannot work without an X
server, so exclude it as kdesu already is.

sddm: QML_INSTALL_DIR fell back to 'qmake -query QT_INSTALL_QML', i.e.
the HOST Qt, so SddmComponents installed into the host build tree. Every
greeter theme does 'import SddmComponents 2.0', so this broke the login
UI at runtime with no build-time error.

polkit: dbus-1.pc's system_bus_services_dir comes back sysroot-prefixed
under a cross build, dropping a bogus /mnt/... tree into the image.
This commit is contained in:
2026-08-03 09:10:21 +03:00
parent 63614382d6
commit aa075024ca
5 changed files with 100 additions and 1 deletions
+64
View File
@@ -40,6 +40,27 @@ unset LDFLAGS CFLAGS CXXFLAGS CPPFLAGS
export CC=/usr/bin/gcc
export CXX=/usr/bin/g++
# ...but put OUR host LLVM back on the link path. Clearing LDFLAGS leaves the
# linker with only the default /usr/lib, so on a host that ships its own
# llvm-runtime the system libLLVM.so wins over llvm-native's. That mislink is
# silent and produces two failures far from the cause:
#
# * Arch/Manjaro build libLLVM with -DLLVM_LINK_LLVM_DYLIB, so it re-exports
# libstdc++ symbols under its own LLVM_<ver> version node. mesa_clc then
# records a versioned reference (e.g. std::string::reserve@LLVM_21.1) that
# NO llvm-native build provides, and dies at runtime with
# "undefined symbol: ..., version LLVM_21.1".
# * If it instead resolves the host libLLVM at runtime too, clang derives its
# resource dir from the HOST install. When the host's clang major differs
# from its llvm-runtime major (clang 22 + libLLVM 21.1 here), that directory
# does not exist and every OpenCL compile fails with
# "'opencl-c-base.h' file not found".
#
# -L puts llvm-native's libs ahead of /usr/lib for the linker; the matching
# -rpath makes the runtime loader agree, so link-time and run-time resolve to
# the same libLLVM.
export LDFLAGS="-L${COOKBOOK_SYSROOT}/usr/lib -Wl,-rpath,${COOKBOOK_SYSROOT}/usr/lib"
# Use llvm-native's CLEAN host LLVM/Clang (staged in the sysroot at usr/bin).
# Do NOT use the redoxer toolchain's llvm-config: its includedir
# (<toolchain>/include) also holds the Redox *target* libc headers
@@ -74,6 +95,19 @@ done
# Configure a NATIVE mesa restricted to the shader compilers. No window-system
# platforms / GL runtime — we only need the clc/precomp tool executables.
#
# Always configure from scratch. `meson setup` on an ALREADY-configured build
# dir does not re-run configuration: it reinterprets the -D flags as option
# *changes* against the stored configuration and aborts on any option the old
# configuration did not define, e.g.
# Directory already configured.
# ERROR: Unknown option: "mesa-clc".
# That is exactly what happens after a Mesa version bump (the option set moves)
# or when a build dir survives from an earlier run, and the failure message
# points at the option rather than at the stale directory. Wiping is cheap here
# because the cookbook only re-enters this script on a content-hash miss.
rm -rf build-clc
meson setup build-clc "${COOKBOOK_SOURCE}" \
--buildtype=release \
--prefix=/usr \
@@ -119,5 +153,35 @@ for t in $_targets; do
echo "mesa-clc: WARN target build-clc/$t not found after build"
fi
done
# Pin the RUNPATH to THIS recipe's sysroot (host LLVM/Clang), regenerated on
# every build.
#
# These are NATIVE host tools that the cross Mesa build executes out of *mesa's*
# sysroot. Two wrong answers to guard against:
#
# 1. A stale absolute path (e.g. left over from a moved checkout). The loader
# then silently falls back to the host's /usr/lib. That is not a
# missing-library error — it succeeds against whatever host LLVM runtime
# happens to be installed, and clang derives its resource dir from that
# install. With host LLVM 21.1 libs present but the host clang at 22,
# /usr/lib/clang/21 does not exist and every OpenCL compile dies with
# "'opencl-c-base.h' file not found" — nowhere near the real cause.
#
# 2. $ORIGIN/../lib. Tempting because it is relocatable, but WRONG here: it
# resolves inside the *consumer's* sysroot (mesa's), which also contains
# the Redox TARGET relibc. A host binary then loads the target libc.so.6
# and dies with "undefined symbol: __fini_array_end".
#
# COOKBOOK_SYSROOT is this recipe's own sysroot and contains host-only
# libraries, so it is the correct target. It is absolute, so a checkout move
# requires re-cooking mesa-clc — acceptable, since the content-hash cache
# re-cooks it whenever the recipe or its deps change anyway.
for t in $_targets; do
_b="${COOKBOOK_STAGE}/usr/bin/$(basename "$t")"
[ -f "${_b}" ] || continue
patchelf --set-rpath "${COOKBOOK_SYSROOT}/usr/lib" "${_b}"
done
ls -la "${COOKBOOK_STAGE}/usr/bin/"
'''
+2
View File
@@ -55,6 +55,8 @@ cmake "${COOKBOOK_SOURCE}" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH="${COOKBOOK_SYSROOT}" \
-DKF6_HOST_TOOLING=/usr/lib/cmake \
-DKConfigCompiler_EXECUTABLE=/usr/lib/kf6/kconfig_compiler_kf6 \
-DBUILD_TESTING=OFF \
-DBUILD_QT5=OFF \
-DBUILD_QT6=ON \
+17 -1
View File
@@ -41,6 +41,13 @@ done
# Disable kdesu — no sudo/kdesu backend on Redox
sed -i 's/^add_subdirectory(kdesu/#add_subdirectory(kdesu/' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
# kstart is an X11-only tool: it sets X11 window properties on the app it
# launches and includes Qt's private X11 interop header, which qtbase does not
# install on a Wayland-only build:
# kstart/kstart.cpp:19:10: fatal error: private/qtx11extras_p.h: No such file
# It cannot function without an X server, so exclude it exactly as kdesu above.
# Idempotent: once commented, ^add_subdirectory no longer matches.
sed -i 's/^add_subdirectory(kstart/#add_subdirectory(kstart/' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
rm -f CMakeCache.txt
rm -rf CMakeFiles
@@ -58,7 +65,16 @@ cmake "${COOKBOOK_SOURCE}" \
-DUSE_DBUS=OFF \
-Wno-dev
cmake --build . -j"${COOKBOOK_MAKE_JOBS}"
cmake --install . --prefix "${COOKBOOK_STAGE}/usr"
# Must be DESTDIR, not --prefix. kde-cli-tools installs several targets to
# ${KDE_INSTALL_FULL_BINDIR}, i.e. an ABSOLUTE /usr/bin. `--prefix` only
# re-roots relative destinations, so absolute ones escape the stage and cmake
# writes straight into the BUILD HOST's filesystem:
# -- Up-to-date: /usr/bin/keditfiletype5
# CMake Error: file INSTALL cannot copy ... to "/usr/bin/keditfiletype":
# Permission denied.
# Only the host's file permissions prevented this from polluting /usr/bin.
# DESTDIR re-roots absolute destinations too, which is why sddm uses it.
DESTDIR="${COOKBOOK_STAGE}" cmake --install . --prefix /usr
find "${COOKBOOK_STAGE}" -name '*.so*' -exec patchelf --remove-rpath {} \\; 2>/dev/null || true
"""
+7
View File
@@ -155,6 +155,12 @@ cd build
rm -f CMakeCache.txt
rm -rf CMakeFiles
# QML_INSTALL_DIR must be set explicitly. SDDM's CMakeLists falls back to
# `qmake -query QT_INSTALL_QML`, and the only qmake available in a cross build
# is the host one under build/qt-host-build — so SddmComponents would install
# into the HOST Qt's qml dir instead of the target's /usr/qml. The greeter
# themes all `import SddmComponents 2.0`, so getting this wrong means the
# login UI fails to load at runtime with no build-time error.
cmake "${COOKBOOK_SOURCE}" \
-DKF_SKIP_PO_PROCESSING=ON \
-DCMAKE_TOOLCHAIN_FILE="${COOKBOOK_ROOT}/local/recipes/qt/redox-toolchain.cmake" \
@@ -174,6 +180,7 @@ cmake "${COOKBOOK_SOURCE}" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DUID_MIN=1000 \
-DUID_MAX=65000 \
-DQML_INSTALL_DIR=/usr/qml \
-DLIBXKB_INCLUDE_DIR="${COOKBOOK_SYSROOT}/usr/include" \
-DLIBXKB_LIBRARIES="${COOKBOOK_SYSROOT}/usr/lib/libxkbcommon.so" \
-Wno-dev
+10
View File
@@ -41,6 +41,16 @@ export RANLIB="x86_64-unknown-redox-ranlib"
export CFLAGS="-I${COOKBOOK_SYSROOT}/usr/include --sysroot=${COOKBOOK_SYSROOT} -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-error=implicit-function-declaration"
export LDFLAGS="--sysroot=${COOKBOOK_SYSROOT}"
# dbus-1.pc's system_bus_services_dir comes back sysroot-prefixed under a cross
# build, so upstream's pkg-config branch resolves to an absolute HOST path and
# installs org.freedesktop.PolicyKit1.service into
# <sysroot>/usr/share/dbus-1/system-services — which lands in the image as a
# bogus /mnt/... directory tree. Upstream's own fallback branch already computes
# the correct target-relative layout, so pin the value to that.
# Idempotent: after the first pass the line no longer matches.
sed -i "s|^ dbus_system_bus_services_dir = dbus_dep.get_pkgconfig_variable.*| dbus_system_bus_services_dir = pk_prefix / pk_datadir / 'dbus-1' / 'system-services'|" \\
"${COOKBOOK_SOURCE}/meson.build"
cookbook_meson \\
-Dlibs-only=true \\
-Dintrospection=false \\