diff mbox series

[v2] llvm/mesa/rust: simplify llvm-config handling

Message ID 20260610112611.649074-1-Deepesh.Varatharajan@windriver.com
State New
Headers show
Series [v2] llvm/mesa/rust: simplify llvm-config handling | expand

Commit Message

Varatharajan, Deepesh June 10, 2026, 11:26 a.m. UTC
From: Deepesh Varatharajan <Deepesh.Varatharajan@windriver.com>

Replace PATH-based llvm-config discovery with explicit sysroot-native
resolution and simplify the target llvm-config wrapper to act as a pure
pass-through while preserving Yocto alternate path handling.

The previous implementation relied on:

* `which -a llvm-config | sed -n 2p`
   which is unreliable in cross-build environments because it only
   searches executables present in $PATH. Native sysroot tools
   (e.g. recipe-sysroot-native llvm-config) are not guaranteed to be
   exposed via PATH, so they may not be discovered at all.

* `echo $base_libdir | sed -n '/lib64/p'`
   which depends on a BitBake variable that may be empty or unset
   in certain build contexts, leading to incorrect libdir selection.

Update the wrapper to:

* Use an @LLVM_CONFIG_PATH@ placeholder that is replaced during the
  build with the appropriate native llvm-config path.
* Detect libdir using filesystem inspection rather than variable
  parsing.
* Preserve `YOCTO_ALTERNATE_EXE_PATH` and
  `YOCTO_ALTERNATE_LIBDIR` handling.
* Delegate all arguments directly to the native llvm-config.

Update rust and mesa recipes to replace the placeholder with the native
llvm-config path during target and nativesdk builds.

Also remove the native llvm-config copy logic and lib/lib64 symlink
workarounds, relying instead on explicit native tool resolution.

Signed-off-by: Deepesh Varatharajan <Deepesh.Varatharajan@windriver.com>
---
 ...unwind.pc.in-and-llvm-config-scripts.patch | 52 +++----------------
 meta/recipes-devtools/rust/rust_1.96.0.bb     | 51 +++++-------------
 meta/recipes-graphics/mesa/mesa.inc           | 16 ++++++
 3 files changed, 38 insertions(+), 81 deletions(-)

Comments

Varatharajan, Deepesh June 10, 2026, 11:30 a.m. UTC | #1
Hello Everyone,

The patch has been tested on the following architectures:
x86-64
x86
arm64
arm
riscv64

The following recipes were successfully built and validated:
rust
clang
mesa
nativesdk-rust
nativesdk-clang
nativesdk-mesa

Additionally, with multilib enabled, rust, clang, and mesa were tested successfully on x86-64.

Regards,
Deepesh
diff mbox series

Patch

diff --git a/meta/recipes-devtools/clang/clang/0026-llvm-Add-libunwind.pc.in-and-llvm-config-scripts.patch b/meta/recipes-devtools/clang/clang/0026-llvm-Add-libunwind.pc.in-and-llvm-config-scripts.patch
index eeb802732b..72ffdc6c1f 100644
--- a/meta/recipes-devtools/clang/clang/0026-llvm-Add-libunwind.pc.in-and-llvm-config-scripts.patch
+++ b/meta/recipes-devtools/clang/clang/0026-llvm-Add-libunwind.pc.in-and-llvm-config-scripts.patch
@@ -8,6 +8,7 @@  These are added by OE project
 Upstream-Status: Inappropriate [ OE-Specific ]
 
 Signed-off-by: Khem Raj <raj.khem@gmail.com>
+Signed-off-by: Deepesh Varatharajan <Deepesh.Varatharajan@windriver.com>
 ---
  libunwind/libunwind.pc.in          |  9 ++++++
  llvm/tools/llvm-config/llvm-config | 52 ++++++++++++++++++++++++++++++
@@ -35,56 +36,19 @@  new file mode 100644
 index 000000000000..6a0dd54b8eab
 --- /dev/null
 +++ b/llvm/tools/llvm-config/llvm-config
-@@ -0,0 +1,52 @@
+@@ -0,0 +1,15 @@
 +#!/bin/bash
 +#
-+# Wrapper script for llvm-config. Supplies the right environment variables
-+# for the target and delegates to the native llvm-config for anything else. This
-+# is needed because arguments like --ldflags, --cxxflags, etc. are set by the
-+# native compile rather than the target compile.
++# The llvm-config wrapper will act as a pure pass-through to the native llvm-config
++# while preserving Yocto-specific environment variables used for alternate executable
++# and library path resolution.
 +#
 +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
-+NEXT_LLVM_CONFIG="$(which -a llvm-config | sed -n 2p)"
++NEXT_LLVM_CONFIG="@LLVM_CONFIG_PATH@"
 +export YOCTO_ALTERNATE_EXE_PATH="${YOCTO_ALTERNATE_EXE_PATH:="$(readlink -f "$SCRIPT_DIR/../llvm-config")"}"
-+if [ -n "$( echo $base_libdir | sed -n '/lib64/p')" ]; then
++if [ -d "$(readlink -f "$SCRIPT_DIR/../../lib64")" ]; then
 +    export YOCTO_ALTERNATE_LIBDIR="${YOCTO_ALTERNATE_LIBDIR:="/lib64"}"
 +else
 +    export YOCTO_ALTERNATE_LIBDIR="${YOCTO_ALTERNATE_LIBDIR:="/lib"}"
 +fi
-+if [[ $# == 0 ]]; then
-+  exec "$NEXT_LLVM_CONFIG"
-+fi
-+
-+remain=""
-+output=""
-+for arg in "$@"; do
-+  case "$arg" in
-+    --cppflags)
-+      output="${output} ${CPPFLAGS}"
-+      ;;
-+    --cflags)
-+      output="${output} ${CFLAGS}"
-+      ;;
-+    --cxxflags)
-+      output="${output} ${CXXFLAGS}"
-+      ;;
-+    --ldflags)
-+      output="${output} ${LDFLAGS}"
-+      ;;
-+    --shared-mode)
-+      output="${output} shared"
-+      ;;
-+    --link-shared)
-+      break
-+      ;;
-+    *)
-+      remain="${remain} ${arg}"
-+      ;;
-+  esac
-+done
-+
-+if [ "${remain}" != "" ]; then
-+      output="${output} "$("$NEXT_LLVM_CONFIG" ${remain})
-+fi
-+
-+echo "${output}"
++exec "$NEXT_LLVM_CONFIG" "$@"
diff --git a/meta/recipes-devtools/rust/rust_1.96.0.bb b/meta/recipes-devtools/rust/rust_1.96.0.bb
index 3eb2a36406..f4158522b8 100644
--- a/meta/recipes-devtools/rust/rust_1.96.0.bb
+++ b/meta/recipes-devtools/rust/rust_1.96.0.bb
@@ -31,7 +31,7 @@  PV .= "${@bb.utils.contains('RUST_CHANNEL', 'stable', '', '-${RUST_CHANNEL}', d)
 
 export FORCE_CRATE_HASH = "${BB_TASKHASH}"
 
-RUST_ALTERNATE_EXE_PATH ?= "${STAGING_BINDIR}/llvm-config"
+RUST_ALTERNATE_EXE_PATH = "${STAGING_BINDIR_CROSS}/llvm-config"
 RUST_ALTERNATE_EXE_PATH_NATIVE = "${STAGING_BINDIR_NATIVE}/llvm-config"
 
 # We don't want to use bitbakes vendoring because the rust sources do their
@@ -192,37 +192,22 @@  python do_configure() {
     bb.build.exec_func("setup_cargo_environment", d)
 }
 
-# llvm-config expects static/dynamic libraries to be in the 'lib' directory rather than 'lib64' when
-# multilibs enabled. Since we are copying the natively built llvm-config into the target sysroot
-# and executing it there, it will default to searching in 'lib', as it is unaware of the 'lib64'
-# directory. To ensure llvm-config can locate the necessary libraries, create a symlink from 'lib'
-do_compile:append:class-target() {
-    # Ensure llvm-config can find static libraries in multilib setup
-    lib64_dir="${STAGING_DIR_TARGET}/usr/lib64"
-    lib_dir="${STAGING_DIR_TARGET}/usr/lib"
-
-    if [ -d "$lib64_dir" ]; then
-        # If lib does not exist, symlink it to lib64
-        if [ ! -e "$lib_dir" ]; then
-            ln -s lib64 "$lib_dir"
-        fi
-
-        # Only do per-file symlinking if lib is a real directory (not symlink)
-        if [ -d "$lib_dir" ] && [ ! -L "$lib_dir" ]; then
-            for lib64_file in "${lib64_dir}"/libLLVM*.a "${lib64_dir}"/libLLVM*.so*; do
-                if [ -e "$lib64_file" ]; then
-                    lib_name=$(basename "${lib64_file}")
-                    target_link="${lib_dir}/${lib_name}"
-
-                    if [ ! -e "${target_link}" ]; then
-                        ln -s "../lib64/${lib_name}" "${target_link}"
-                    fi
-                fi
-            done
-        fi
+replace_llvm_config_path() {
+    if [ -f "${STAGING_BINDIR_CROSS}/llvm-config" ]; then
+        sed -i \
+            's#@LLVM_CONFIG_PATH@#${RUST_ALTERNATE_EXE_PATH_NATIVE}#g' \
+            ${RUST_ALTERNATE_EXE_PATH}
     fi
 }
 
+do_compile:append:class-target() {
+    replace_llvm_config_path
+}
+
+do_compile:append:class-nativesdk() {
+    replace_llvm_config_path
+}
+
 rust_runx () {
     echo "COMPILE ${PN}" "$@"
 
@@ -236,14 +221,6 @@  rust_runx () {
 
     export RUSTFLAGS="${RUST_DEBUG_REMAP} -Clink-arg=-lz -Clink-arg=-lzstd"
 
-    # Copy the natively built llvm-config into the target so we can run it. Horrible,
-    # but works!
-    if [ ${RUST_ALTERNATE_EXE_PATH_NATIVE} != ${RUST_ALTERNATE_EXE_PATH} -a ! -f ${RUST_ALTERNATE_EXE_PATH} ]; then
-        mkdir -p `dirname ${RUST_ALTERNATE_EXE_PATH}`
-        cp ${RUST_ALTERNATE_EXE_PATH_NATIVE} ${RUST_ALTERNATE_EXE_PATH}
-        patchelf --remove-rpath ${RUST_ALTERNATE_EXE_PATH}
-    fi
-
     oe_cargo_fix_env
 
     python3 src/bootstrap/bootstrap.py ${@oe.utils.parallel_make_argument(d, '-j %d')} "$@" --verbose
diff --git a/meta/recipes-graphics/mesa/mesa.inc b/meta/recipes-graphics/mesa/mesa.inc
index 15dad6eedd..f40fed5ebc 100644
--- a/meta/recipes-graphics/mesa/mesa.inc
+++ b/meta/recipes-graphics/mesa/mesa.inc
@@ -51,6 +51,22 @@  ANY_OF_DISTRO_FEATURES = "opencl opengl vulkan"
 
 PLATFORMS ??= "${@bb.utils.filter('PACKAGECONFIG', 'x11 wayland', d)}"
 
+replace_llvm_config_path() {
+    if [ -f "${STAGING_BINDIR_CROSS}/llvm-config" ]; then
+        sed -i \
+            's#@LLVM_CONFIG_PATH@#${STAGING_BINDIR_NATIVE}/llvm-config#g' \
+            ${STAGING_BINDIR_CROSS}/llvm-config
+    fi
+}
+
+do_configure:prepend:class-target() {
+    replace_llvm_config_path
+}
+
+do_configure:prepend:class-nativesdk() {
+    replace_llvm_config_path
+}
+
 # set the MESA_BUILD_TYPE to either 'release' (default) or 'debug'
 # by default the upstream mesa sources build a debug release
 # here we assume the user will want a release build by default