llvm-native: re-architect as a PURE HOST build (fixes libclc host-LLVM)

llvm-native's job is to supply a COMPLETE host LLVM dev tree (host clang +
host static component libs + matching cmake/llvm export) that libclc's
find_package(LLVM) and host clang need for Mesa's iris/radeonsi CLC path. The
redoxer toolchain ships host clang + libLLVM.so but strips the static libs, so
find_package fails — and stubbing them violates the no-stub policy.

The recipe was WRONGLY cross-compiling LLVM for the Redox target via
cookbook_cmake: that (a) produces host-unusable Redox binaries and (b) fails to
link because Redox's libstdc++ lacks symbols LLVM uses (std::random_device
etc.). My earlier LLVM_USE_HOST_TOOLS=OFF / tblgen-var / native.cmake patches
were all treating symptoms of that wrong architecture.

Rewrite: build entirely with the host gcc, targeting the host, exactly like
libclc builds its own host prepare_builtins tool — invoke cmake directly (not
cookbook_cmake) with /usr/bin/gcc and no CMAKE_SYSTEM_NAME so CROSSCOMPILING is
false (LLVM builds one native tblgen with host gcc; no NATIVE sub-project, no
Redox-header leak). Drop all Redox build-deps and the llvm21.runtime package
dep. Validated: host GCC 16.1.1 configures LLVM 21 and builds llvm-min-tblgen +
libLLVMSupport.a/libLLVMTableGen.a cleanly.

This is how upstream-style host LLVM tooling should be produced; it supersedes
the cross-build patch chain (312659fe21, 5d426d89a7, 872935057c, b2d9a31a4f).
This commit is contained in:
2026-07-31 08:18:46 +03:00
parent b2d9a31a4f
commit ecc971b4ec
+69 -143
View File
@@ -3,158 +3,84 @@ same_as = "../../../../recipes/dev/llvm21"
[build]
template = "custom"
dependencies = [
"llvm21",
"llvm21.runtime",
"llvm21.dev",
"clang21",
"lld21",
"zstd",
]
# PURE HOST build — needs nothing from the Redox cross sysroot. (It shares the
# llvm21 SOURCE via [source] same_as, which is a source relationship, not a
# build dependency.)
dependencies = []
script = """
DYNAMIC_INIT
ARCH="$(echo "${TARGET}" | cut -d - -f1)"
# Save and unset the cross-compile flags DYNAMIC_INIT exports so the host cc
# in the native sub-build (CROSS_TOOLCHAIN_FLAGS_NATIVE below) links against
# the host libc, not the Redox sysroot's relibc — otherwise the native cmake
# try_compile fails with "undefined reference to __libc_start_main". The cross
# build restores them via -DCMAKE_*_FLAGS further down. Mirrors the llvm21
# recipe, which solved this exact failure.
_SAVED_LDFLAGS="${LDFLAGS:-}"
_SAVED_CFLAGS="${CFLAGS:-}"
_SAVED_CXXFLAGS="${CXXFLAGS:-}"
unset LDFLAGS CFLAGS CXXFLAGS
# Use /usr (host sysroot) for the native build, NOT $COOKBOOK_TOOLCHAIN (the
# Redox cross sysroot whose libc.a lacks __libc_start_main).
generate_cookbook_cmake_file "$COOKBOOK_HOST_TARGET" "" "/usr" native.cmake
# The generated native.cmake still inherits CMAKE_*_FLAGS / sysroot from the
# cross toolchain via the cache; CACHE FORCE is required because try_compile
# creates a sub-cache that re-reads the parent values unless explicitly forced.
cat >> native.cmake <<'NATIVE_EOF'
# Override cross-sysroot flags so the host cc links against the host libc.
set(CMAKE_C_FLAGS "" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS "" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "" CACHE STRING "" FORCE)
set(CMAKE_C_FLAGS_DEBUG "" CACHE STRING "" FORCE)
set(CMAKE_C_FLAGS_RELEASE "" CACHE STRING "" FORCE)
set(CMAKE_LDFLAGS "" CACHE STRING "" FORCE)
set(CMAKE_LDFLAGS_DEBUG "" CACHE STRING "" FORCE)
set(CMAKE_LDFLAGS_RELEASE "" CACHE STRING "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS "" CACHE STRING "" FORCE)
set(CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "" FORCE)
set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "" CACHE STRING "" FORCE)
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "" CACHE STRING "" FORCE)
set(CMAKE_SYSROOT "" CACHE STRING "" FORCE)
set(CMAKE_FIND_ROOT_PATH "" CACHE STRING "" FORCE)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE STRING "" FORCE)
set(ENV{LDFLAGS} "")
set(ENV{CFLAGS} "")
set(ENV{CXXFLAGS} "")
NATIVE_EOF
case "${ARCH}" in
x86 | x86_64) LLVM_TARGETS_TO_BUILD="X86";;
aarch64) LLVM_TARGETS_TO_BUILD="AArch64";;
riscv64gc) LLVM_TARGETS_TO_BUILD="RISCV";;
x86 | x86_64) LLVM_HOST_ARCH="X86";;
aarch64) LLVM_HOST_ARCH="AArch64";;
riscv64gc) LLVM_HOST_ARCH="RISCV";;
esac
# The *-tblgen references below must be VERSION-MATCHED to this LLVM source
# tree. cookbook does not export COOKBOOK_HOST_SYSROOT, so an unset value
# collapses them to "/bin/{llvm,clang}-tblgen" — the rolling distro LLVM (now
# 22), whose -gen-opt-parser-defs backend requires a `SubCommand` class that
# LLVM 21's OptParser.td does not define. Point at the redoxer toolchain's
# host-runnable LLVM 21.1.2 tblgen, matching the clang21/lld21 recipes.
export COOKBOOK_HOST_SYSROOT="${COOKBOOK_HOST_SYSROOT:-${HOME}/.redoxer/${TARGET}/toolchain}"
# ============================================================================
# llvm-native is a PURE HOST build of LLVM/Clang/LLD 21.
#
# Its whole purpose is to supply a COMPLETE host LLVM dev tree (host-runnable
# clang + host static component libs + a matching cmake/llvm export) that
# libclc's `find_package(LLVM)` and host `clang` need to compile the OpenCL-C
# builtins bitcode Mesa's iris/radeonsi CLC path consumes. The redoxer
# toolchain ships a host clang + libLLVM.so but STRIPS the static component
# libs, so its LLVMExports references files that don't exist and find_package
# fails — and faking them with stub archives violates the no-stub policy.
#
# It must NOT be cross-compiled for Redox (the previous mistake): a
# Redox-target LLVM (a) produces binaries that can't run on the build host and
# (b) fails to LINK because Redox's libstdc++ lacks symbols LLVM uses
# (e.g. std::random_device). So we build entirely with the HOST gcc, targeting
# the host, exactly the way libclc builds its own host prepare_builtins tool.
#
# We deliberately do NOT use cookbook_cmake (which configures a Redox
# cross-build). We invoke cmake directly with the host gcc and no
# CMAKE_SYSTEM_NAME, so CMAKE_CROSSCOMPILING is false: LLVM builds its own
# native tblgen once (host gcc → no Redox-header leak) and there is no NATIVE
# external sub-project.
# ============================================================================
COOKBOOK_CMAKE_FLAGS+=(
-DLLVM_ENABLE_PROJECTS="clang;lld"
-DLLVM_BUILD_LLVM_DYLIB=On
-DLLVM_LINK_LLVM_DYLIB=On
-DLLVM_INCLUDE_UTILS=On
-DLLVM_INSTALL_UTILS=On
-DLLVM_TARGETS_TO_BUILD="$LLVM_TARGETS_TO_BUILD"
-DLLVM_ENABLE_ZLIB=Off
-DLLVM_USE_STATIC_ZSTD=On
-DLLVM_ENABLE_LIBXML2=Off
-DCLANG_LINK_CLANG_DYLIB=ON
-DLIBCLANG_BUILD_STATIC=1
-DCROSS_TOOLCHAIN_FLAGS_NATIVE="-DCMAKE_TOOLCHAIN_FILE=$(realpath native.cmake)"
-DBUILD_SHARED_LIBS=False
-DLLVM_BUILD_EXAMPLES=Off
-DLLVM_BUILD_TESTS=Off
-DLLVM_DEFAULT_TARGET_TRIPLE="${TARGET}"
-DLLVM_ENABLE_LTO=Off
-DLLVM_ENABLE_RTTI=On
-DLLVM_ENABLE_THREADS=On
-DLLVM_INCLUDE_EXAMPLES=Off
-DLLVM_INCLUDE_TESTS=Off
# OFF on purpose: this recipe PROVIDES host-runnable, version-matched
# tblgens via LLVM_TABLEGEN/CLANG_TABLEGEN below (the redoxer toolchain's
# LLVM 21.1.2). LLVM_OPTIMIZED_TABLEGEN=On would build a second optimized
# native tblgen instead of using them. Off => LLVM uses what we provide.
-DLLVM_OPTIMIZED_TABLEGEN=Off
# OFF is REQUIRED here. LLVM_USE_HOST_TOOLS defaults ON when cross-compiling
# and makes llvm/CMakeLists.txt create the NATIVE external project
# (llvm_create_cross_target LLVM NATIVE), a full second host LLVM build that
# inherits the Redox cross flags and dies compiling native llvm-config/etc.
# We already supply host-runnable, version-matched tblgens via
# LLVM_TABLEGEN/CLANG_TABLEGEN (the only native tools a cross-build needs),
# so the NATIVE project is pure waste. OFF => no native sub-build; LLVM uses
# the provided tblgens for .inc generation.
-DLLVM_USE_HOST_TOOLS=OFF
-DLLVM_TARGET_ARCH=$ARCH
-DLLVM_TOOLS_INSTALL_DIR=bin
-DLLVM_UTILS_INSTALL_DIR=bin
-DUNIX=1
# CRITICAL: the cache vars LLVM/Clang read to SKIP building a native tblgen
# when cross-compiling are LLVM_TABLEGEN / CLANG_TABLEGEN (see
# llvm/cmake/modules/TableGen.cmake: "Native TableGen executable. Saves
# building one when cross-compiling"). The *_TABLEGEN_EXE names used
# previously are NOT read by a from-scratch LLVM build, so LLVM built its
# own native tblgen via the CROSS_TOOLCHAIN_FLAGS_NATIVE sub-build — which
# ran the HOST gcc against the Redox relibc headers leaked through
# CMAKE_CXX_FLAGS and died on host/redox <stdlib.h> conflicts
# (__deprecated/__noreturn undeclared, duplicate div_t). Passing the
# correct var names makes LLVM use the provided host tblgens (LLVM 21.1.2)
# and skip the native sub-build entirely. (lld21/clang21 build against a
# PREBUILT llvm and locate tblgen via find_program on LLVM_TABLEGEN_EXE —
# a different cache var owned by those projects — so they are correct.)
-DLLVM_TABLEGEN=${COOKBOOK_HOST_SYSROOT}/bin/llvm-tblgen
-DCLANG_TABLEGEN=${COOKBOOK_HOST_SYSROOT}/bin/clang-tblgen
)
# Drop every cross-compile flag DYNAMIC_INIT exported so the host gcc never
# sees the Redox sysroot / relibc.
unset LDFLAGS CFLAGS CXXFLAGS CPPFLAGS
COOKBOOK_SOURCE="$COOKBOOK_SOURCE/llvm"
# Restore the cross-compile flags for the CROSS build via cmake vars rather
# than the environment: an exported LDFLAGS leaks into the native try_compile
# and re-introduces the Redox libc link failure. (Native.cmake above keeps the
# host sub-build clean.)
if [ -n "${_SAVED_LDFLAGS}" ]; then
COOKBOOK_CMAKE_FLAGS+=(-DCMAKE_EXE_LINKER_FLAGS="${_SAVED_LDFLAGS}")
COOKBOOK_CMAKE_FLAGS+=(-DCMAKE_SHARED_LINKER_FLAGS="${_SAVED_LDFLAGS}")
fi
if [ -n "${_SAVED_CFLAGS}" ]; then
COOKBOOK_CMAKE_FLAGS+=(-DCMAKE_C_FLAGS="${_SAVED_CFLAGS}")
fi
# LLVM 21 REQUIRES C++17 (its headers use std::remove_reference_t, std::size,
# std::shared_timed_mutex, etc.). The main build gets -std=gnu++17 from LLVM's
# own CMAKE_CXX_STANDARD=17, appended after CMAKE_CXX_FLAGS so it wins — but the
# CROSS_TOOLCHAIN_FLAGS_NATIVE sub-build (native llvm-tblgen) inherits
# CMAKE_CXX_FLAGS with a DIFFERENT flag order where a stale "--std=gnu++11"
# would win, breaking <shared_mutex> ("'_M_rwlock' was not declared"). Pass
# gnu++17 here so no target can regress to C++11 regardless of flag order.
if [ -n "${_SAVED_CXXFLAGS}" ]; then
COOKBOOK_CMAKE_FLAGS+=(-DCMAKE_CXX_FLAGS="--std=gnu++17 ${_SAVED_CXXFLAGS}")
else
COOKBOOK_CMAKE_FLAGS+=(-DCMAKE_CXX_FLAGS="--std=gnu++17")
fi
"${COOKBOOK_CMAKE}" "${COOKBOOK_SOURCE}" \
-G Ninja \
-Wno-dev \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++ \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DLLVM_ENABLE_PROJECTS="clang;lld" \
-DLLVM_BUILD_LLVM_DYLIB=On \
-DLLVM_LINK_LLVM_DYLIB=On \
-DLLVM_INCLUDE_UTILS=On \
-DLLVM_INSTALL_UTILS=On \
-DLLVM_TARGETS_TO_BUILD="$LLVM_HOST_ARCH" \
-DLLVM_ENABLE_ZLIB=Off \
-DLLVM_ENABLE_ZSTD=Off \
-DLLVM_ENABLE_LIBXML2=Off \
-DLLVM_ENABLE_WERROR=Off \
-DCLANG_LINK_CLANG_DYLIB=On \
-DLIBCLANG_BUILD_STATIC=1 \
-DBUILD_SHARED_LIBS=False \
-DLLVM_BUILD_EXAMPLES=Off \
-DLLVM_BUILD_TESTS=Off \
-DLLVM_INCLUDE_EXAMPLES=Off \
-DLLVM_INCLUDE_TESTS=Off \
-DLLVM_DEFAULT_TARGET_TRIPLE="${TARGET}" \
-DLLVM_ENABLE_LTO=Off \
-DLLVM_ENABLE_RTTI=On \
-DLLVM_ENABLE_THREADS=On \
-DLLVM_TARGET_ARCH="$LLVM_HOST_ARCH" \
-DLLVM_TOOLS_INSTALL_DIR=bin \
-DLLVM_UTILS_INSTALL_DIR=bin \
-DUNIX=1
cookbook_cmake
"${COOKBOOK_NINJA}" -j"${COOKBOOK_MAKE_JOBS}"
DESTDIR="${COOKBOOK_STAGE}" "${COOKBOOK_NINJA}" install
# Create unprefixed symlinks for native use
for tool in clang clang++ clang-cpp clang-cl clang-check clang-format clang-tidy \
@@ -184,8 +110,8 @@ rm -f "${COOKBOOK_STAGE}"/usr/lib/*.la
"""
[package]
description = "Native LLVM/Clang/LLD 21 toolchain for Red Bear OS"
dependencies = ["llvm21.runtime"]
description = "Native (host) LLVM/Clang/LLD 21 toolchain for Red Bear OS — host build-time tool tree consumed by libclc; not shipped to the target image"
dependencies = []
[[optional-packages]]
name = "dev"