# The C++ driver for the musl target: musl-clang++, the counterpart of # Fedora's musl-clang (which covers C only). # # Unlike musl-clang, this wrapper does not use ld.musl-clang: that ld # wrapper keeps only the -L/-l arguments between its -l-user-start/-end # markers, and clang++'s implicitly appended C++ runtime libraries land # outside them and are silently dropped. The wrapper instead relies on # --sysroot/-B/-L and the merged libc++.a from musl-libcxx, so the stock # link path works and user flags appended after the wrapper's own win. %global musl_prefix /usr/x86_64-linux-musl # Only a shell script is shipped: debuginfo extraction would produce an # empty debugsource and fail the build. %global debug_package %{nil} Name: musl-llvm Version: 1 Release: 2%{?dist} Summary: Clang C++ driver for the musl target License: MIT URL: https://musl.libc.org/ ExclusiveArch: x86_64 Source0: musl-clang++.in Requires: clang Requires: musl-devel Requires: musl-libcxx # A -static link needs libc.a; the crt begin/end objects and libgcc.a # come from the host GCC installation. Requires: musl-libc-static Requires: gcc # For the %%check link-and-run probe. BuildRequires: clang BuildRequires: gcc BuildRequires: musl-devel BuildRequires: musl-libc-static BuildRequires: musl-libcxx BuildRequires: file %description musl-clang++ drives the distribution clang++ at the x86_64-linux-musl target against the musl-libcxx runtimes, the way musl-clang does for C. With musl-libc-static installed, musl-clang++ -static links self-contained static C++ binaries. %prep %setup -q -c -T %build sed -e 's|@MUSL_PREFIX@|%{musl_prefix}|g' \ -e 's|@MUSL_INCLUDEDIR@|%{_musl_includedir}|g' \ -e 's|@MUSL_LIBDIR@|%{_musl_libdir}|g' \ %{SOURCE0} > musl-clang++ # Assert every sed: an @-marker surviving means a substitution went dead. grep -q -- '-B%{_musl_libdir}' musl-clang++ if grep -q '@MUSL' musl-clang++ ; then echo "unsubstituted marker in musl-clang++" exit 1 fi %install mkdir -p %{buildroot}%{_bindir} install -m 755 musl-clang++ %{buildroot}%{_bindir}/musl-clang++ %check # The point of the package: the installed wrapper links a static C++ # program -- std::format, a thrown exception, a std::thread -- and it # runs. cat > _probe.cpp <<'EOF' #include #include #include #include #include int main() { std::string out; std::thread t([&] { out = std::format("std::{} on {}", "format", "musl"); }); t.join(); try { throw std::runtime_error("unwound"); } catch (const std::exception &e) { std::printf("%s, exception: %s\n", out.c_str(), e.what()); } return 0; } EOF %{buildroot}%{_bindir}/musl-clang++ -std=c++23 -static -o _probe _probe.cpp file _probe file _probe | grep -q 'statically linked' out=$(./_probe) echo "$out" test "$out" = "std::format on musl, exception: unwound" # meson runs its compiler probes with -Werror=unused-command-line- # argument; the wrapper's link-only flags must not trip it. %{buildroot}%{_bindir}/musl-clang++ -std=c++23 \ -Werror=unused-command-line-argument -c -o _probe.o _probe.cpp # A non-static link must also work (libc++.a into a musl-dynamic # binary); it cannot run in this chroot without ld-musl, so link only. %{buildroot}%{_bindir}/musl-clang++ -std=c++23 -o _probe_dyn _probe.cpp interp=$(readelf -l _probe_dyn | grep 'interpreter') echo "$interp" echo "$interp" | grep -q 'ld-musl-x86_64' %files %{_bindir}/musl-clang++ %changelog * Thu Aug 20 2026 Erik Berg - 1-2 - Add -Qunused-arguments: the wrapper's link-only flags warn on every compile-only invocation, and meson runs its compiler probes with -Werror=unused-command-line-argument, failing them all (the mingw clang drivers hit the same trap) * Thu Aug 20 2026 Erik Berg - 1-1 - Initial package: musl-clang++, the C++ counterpart of musl-clang, driving the distribution clang++ against the musl-libcxx runtimes - Deliberately not built on ld.musl-clang, which silently drops the driver's implicitly appended C++ runtime libraries (they land outside its -l-user-start/-end markers)