diff mbox series

[RFC,3/3] WIP backport: rust: enable dynamic LLVM linking by default

Message ID 20260626-ycongal-scarthgap-rust-segfault-v1-3-97df64b7b298@smile.fr
State RFC
Delegated to: Yoann Congal
Headers show
Series RFC: Fixing rust segfault (#16058) to support Ubuntu 26.04 on Scarthgap | expand

Commit Message

Yoann Congal June 26, 2026, 11:37 a.m. UTC
From: Sunil Dora <sunilkumar.dora@windriver.com>

Fixes [YOCTO #16058]

Enable dynamic linking with LLVM (link-shared) for all rust variants
(native, nativesdk and target) via a PACKAGECONFIG option, enabled
by default. This prevents segmentation faults when reusing sstate
artifacts built with different host toolchains.

Update multilib library symlinking to include shared libraries and
adjust the rust selftest to install llvm so the dynamically linked
compiler can run correctly.

Suggested-by: Alexander Kanavin <alex@linutronix.de>
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit d0671c3dad87a063b3a41dd07cde89b5684e692c)
[YC: WIP Backport:
* moveid from llvm to rust-llvm (llvm unification has not happened on
  scarthgap
* made changes limited to -native/nativesdk- to avoid changing target
  output without reason
* Redid FILES* packaging around $PN/$PN-dev split to handle LLVM.so files]
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
 meta/lib/oeqa/selftest/cases/rust.py           |  2 +-
 meta/recipes-devtools/rust/rust-llvm_1.75.0.bb | 39 ++++++++++++++++++++++++--
 meta/recipes-devtools/rust/rust_1.75.0.bb      |  8 ++++--
 3 files changed, 44 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/meta/lib/oeqa/selftest/cases/rust.py b/meta/lib/oeqa/selftest/cases/rust.py
index 26f132edc4d55f260f835a996181834588249d13..b6912f646e37d0edb07bb178d2d3671ac1a67542 100644
--- a/meta/lib/oeqa/selftest/cases/rust.py
+++ b/meta/lib/oeqa/selftest/cases/rust.py
@@ -51,7 +51,7 @@  class RustSelfTestSystemEmulated(OESelftestTestCase, OEPTestResultTestCase):
         bitbake("{} -c test_compile".format(recipe))
         builddir = get_bb_var("RUSTSRC", "rust")
         # build core-image-minimal with required packages
-        default_installed_packages = ["libgcc", "libstdc++", "libatomic", "libgomp"]
+        default_installed_packages = ["libgcc", "libstdc++", "libatomic", "libgomp", "llvm"]
         features = []
         features.append('IMAGE_FEATURES += "ssh-server-dropbear"')
         features.append('CORE_IMAGE_EXTRA_INSTALL += "{0}"'.format(" ".join(default_installed_packages)))
diff --git a/meta/recipes-devtools/rust/rust-llvm_1.75.0.bb b/meta/recipes-devtools/rust/rust-llvm_1.75.0.bb
index 4adaf5fbf6d31b1984a81e864285c1e06218e325..b32d3ee38cd2be3fa2dde1b8720f59c0b4b13c90 100644
--- a/meta/recipes-devtools/rust/rust-llvm_1.75.0.bb
+++ b/meta/recipes-devtools/rust/rust-llvm_1.75.0.bb
@@ -56,6 +56,9 @@  EXTRA_OECMAKE = " \
     -DCMAKE_INSTALL_PREFIX:PATH=${libdir}/llvm-rust \
 "
 
+EXTRA_OECMAKE:append:class-native = " -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON"
+EXTRA_OECMAKE:append:class-nativesdk = " -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON"
+
 # Forcibly disable the detection of these packages as otherwise
 # it will look at the host Python install
 EXTRA_OECMAKE += "\
@@ -87,6 +90,24 @@  do_install:append () {
     rm -rf "${D}/usr/lib/cmake"
 }
 
+symlink_llvm_libs() {
+    # Create symlinks in ${libdir} so that dynamic libraries can be found in standard paths
+    install -d ${D}${libdir}
+    for lib in ${D}${libdir}/llvm-rust/lib/libLLVM-*.so*; do
+        if [ -e "$lib" ]; then
+            ln -sf llvm-rust/lib/$(basename $lib) ${D}${libdir}/$(basename $lib)
+        fi
+    done
+}
+
+do_install:append:class-native () {
+    symlink_llvm_libs
+}
+
+do_install:append:class-nativesdk () {
+    symlink_llvm_libs
+}
+
 PACKAGES =+ "${PN}-bugpointpasses ${PN}-llvmhello ${PN}-liblto"
 
 # Add the extra locations to avoid the complaints about unpackaged files
@@ -94,7 +115,21 @@  FILES:${PN}-bugpointpasses = "${libdir}/llvm-rust/lib/BugpointPasses.so"
 FILES:${PN}-llvmhello = "${libdir}/llvm-rust/lib/LLVMHello.so"
 FILES:${PN}-liblto = "${libdir}/llvm-rust/lib/libLTO.so.*"
 FILES:${PN}-staticdev =+ "${libdir}/llvm-rust/*/*.a"
-FILES:${PN} += "${libdir}/libLLVM*.so.* ${libdir}/llvm-rust/lib/*.so.* ${libdir}/llvm-rust/bin"
-FILES:${PN}-dev += "${datadir}/llvm ${libdir}/llvm-rust/lib/*.so ${libdir}/llvm-rust/include ${libdir}/llvm-rust/share ${libdir}/llvm-rust/lib/cmake"
+FILES:${PN} += "${libdir}/libLLVM*.so* ${libdir}/llvm-rust/lib/libLLVM*.so* ${libdir}/llvm-rust/lib/libRemarks.so* ${libdir}/llvm-rust/bin"
+FILES:${PN}-dev += "${datadir}/llvm ${libdir}/llvm-rust/include ${libdir}/llvm-rust/share ${libdir}/llvm-rust/lib/cmake"
+
+# Prevent -dev from matching versioned libs ending in .so
+FILES:${PN}-dev:remove = "${libdir}/lib*.so"
+
+# Package unversioned dev symlinks in -dev
+FILES:${PN}-dev += " \
+    ${libdir}/llvm-rust/lib/libLLVM.so \
+    ${libdir}/llvm-rust/lib/libLTO.so \
+    ${libdir}/llvm-rust/lib/libRemarks.so \
+"
+
+# libLLVM-17.so ends in .so; skip dev-so check for host builds
+INSANE_SKIP:${PN}:class-native += "dev-so"
+INSANE_SKIP:${PN}:class-nativesdk += "dev-so"
 
 BBCLASSEXTEND = "native nativesdk"
diff --git a/meta/recipes-devtools/rust/rust_1.75.0.bb b/meta/recipes-devtools/rust/rust_1.75.0.bb
index f037bb33715dc4ba7cbb489ab1599ac6c8c875a4..b11f0ddd2816569e08e6cf908786ee32d49b79e1 100644
--- a/meta/recipes-devtools/rust/rust_1.75.0.bb
+++ b/meta/recipes-devtools/rust/rust_1.75.0.bb
@@ -20,6 +20,11 @@  DEPENDS += "rust-llvm (=${PV})"
 
 RDEPENDS:${PN}:append:class-target = " gcc g++ binutils"
 
+PACKAGECONFIG ??= ""
+PACKAGECONFIG:class-native ??= "llvm-shared"
+PACKAGECONFIG:class-nativesdk ??= "llvm-shared"
+PACKAGECONFIG[llvm-shared] = ",,,"
+
 # Otherwise we'll depend on what we provide
 INHIBIT_DEFAULT_RUST_DEPS:class-native = "1"
 # We don't need to depend on gcc-native because yocto assumes it exists
@@ -128,8 +133,7 @@  python do_configure() {
 
     # [llvm]
     config.add_section("llvm")
-    if d.getVar('PN') == "rust-native":
-        config.set("llvm", "link-shared", e(True))
+    config.set("llvm", "link-shared", e(bb.utils.contains('PACKAGECONFIG', 'llvm-shared', True, False, d)))
     config.set("llvm", "static-libstdcpp", e(False))
     if "llvm" in (d.getVar('TC_CXX_RUNTIME') or ""):
         config.set("llvm", "use-libcxx", e(True))