new file mode 100644
@@ -0,0 +1,5 @@
+version = 3
+
+[[package]]
+name = "rust-static-musl-test"
+version = "0.1.0"
new file mode 100644
@@ -0,0 +1,4 @@
+[package]
+name = "rust-static-musl-test"
+version = "0.1.0"
+edition = "2021"
new file mode 100644
@@ -0,0 +1,3 @@
+fn main() {
+ println!("static-musl-ok");
+}
new file mode 100644
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: MIT
+# Minimal Rust binary to test static musl linking (bug 16076)
+
+SUMMARY = "Minimal Rust binary for static musl linking regression test"
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
+
+SRC_URI = "file://Cargo.toml \
+ file://Cargo.lock \
+ file://src/main.rs \
+ "
+
+S = "${UNPACKDIR}"
+CARGO_SRC_DIR = ""
+
+inherit cargo
+
+COMPATIBLE_HOST = ".*-musl.*"
+
+SSTATE_SKIP_CREATION = "1"
@@ -161,6 +161,7 @@ WRAPPER_TARGET_CC = "${CC}"
WRAPPER_TARGET_CXX = "${CXX}"
WRAPPER_TARGET_CCLD = "${CCLD}"
WRAPPER_TARGET_LDFLAGS = "${LDFLAGS}"
+WRAPPER_TARGET_LDFLAGS:append:libc-musl = " -L${STAGING_DIR_TARGET}${libdir}"
WRAPPER_TARGET_EXTRALD = ""
# see recipes-devtools/gcc/gcc/0018-Add-ssp_nonshared-to-link-commandline-for-musl-targe.patch
# we need to link with ssp_nonshared on musl to avoid "undefined reference to `__stack_chk_fail_local'"
@@ -429,6 +429,8 @@ def rust_gen_target(d, thing, wd, arch):
tspec['has-thread-local'] = True
tspec['position-independent-executables'] = True
tspec['panic-strategy'] = d.getVar("RUST_PANIC_STRATEGY")
+ if "musl" in tspec['llvm-target']:
+ tspec['crt-static-respected'] = True
# write out the target spec json file
with open(wd + rustsys + '.json', 'w') as f:
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: MIT
+import os
import subprocess
import time
from oeqa.core.decorator import OETestTag
@@ -144,3 +145,32 @@ class RustSelfTestSystemEmulated(OESelftestTestCase, OEPTestResultTestCase):
test_results = parse_results(resultlog)
for test in test_results:
self.ptest_result(ptestsuite, test, test_results[test])
+
+# Regression test for bug 16076 - verify static linking with TCLIBC=musl
+class RustStaticMuslTest(OESelftestTestCase):
+
+ RECIPE = "rust-static-musl-test"
+
+ def setUp(self):
+ super().setUp()
+ self.write_config(
+ 'TCLIBC = "musl"\n'
+ 'RUSTFLAGS:append:pn-%s = " -C target-feature=+crt-static"\n' % self.RECIPE
+ )
+ result = bitbake(self.RECIPE, ignore_status=True)
+ self.assertEqual(result.status, 0,
+ msg="bitbake %s failed:\n%s" % (self.RECIPE, result.output))
+
+ def test_static_musl_linking(self):
+ workdir = get_bb_var("WORKDIR", self.RECIPE)
+ cargo_target_subdir = get_bb_var("CARGO_TARGET_SUBDIR", self.RECIPE)
+ pn = get_bb_var("PN", self.RECIPE)
+ binary = os.path.join(workdir, "build", "target",
+ cargo_target_subdir, pn)
+
+ result = runCmd("file %s" % binary, ignore_status=True)
+ self.assertIn("ELF", result.output,
+ msg="Not an ELF binary: %s" % result.output)
+ self.assertIn("statically linked", result.output,
+ msg="Binary is not statically linked. Regression of bug 16076.\n"
+ "file output: %s" % result.output)
@@ -31,6 +31,11 @@ LIC_FILES_CHKSUM = "file://libcxx/LICENSE.TXT;md5=55d89dd7eec8d3b4204b680e27da39
OECMAKE_TARGET_COMPILE = "cxxabi cxx"
OECMAKE_TARGET_INSTALL = "install-cxxabi install-cxx"
+# LLVM libunwind.a needed for static Rust musl builds.
+# GNU libunwind never produces .a on musl so no collision risk.
+OECMAKE_TARGET_COMPILE:append:libc-musl = " unwind"
+OECMAKE_TARGET_INSTALL:append:libc-musl = " install-unwind"
+
CC = "${CCACHE}${HOST_PREFIX}clang ${HOST_CC_ARCH}${TOOLCHAIN_OPTIONS}"
CXX = "${CCACHE}${HOST_PREFIX}clang++ ${HOST_CC_ARCH}${TOOLCHAIN_OPTIONS}"
BUILD_CC = "${CCACHE}clang ${BUILD_CC_ARCH}"
@@ -17,10 +17,7 @@ inherit cargo
CVE_PRODUCT = "rust"
-DEPENDS:append:libc-musl = " libunwind"
-# rv32 does not have libunwind ported yet
-DEPENDS:remove:riscv32 = "libunwind"
-DEPENDS:remove:riscv64 = "libunwind"
+DEPENDS:append:libc-musl = " libcxx"
# Embed bitcode in order to allow compiling both with and without LTO
RUSTFLAGS += "-Cembed-bitcode=yes"