# 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} %global musl_a64_prefix /usr/aarch64-linux-musl Name: musl-llvm Version: 1 Release: 3%{?dist} Summary: Clang C++ driver for the musl target License: MIT URL: https://musl.libc.org/ ExclusiveArch: x86_64 Source0: musl-clang++.in Source1: aarch64-linux-musl-clang.in Source2: aarch64-linux-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 probes. BuildRequires: clang BuildRequires: gcc BuildRequires: musl-devel BuildRequires: musl-libc-static BuildRequires: musl-libcxx BuildRequires: file # The aarch64 probes: cross toolchain plus explicit qemu emulation. BuildRequires: lld BuildRequires: musl-aarch64-devel BuildRequires: musl-aarch64-libc-static BuildRequires: musl-aarch64-compiler-rt BuildRequires: musl-aarch64-libcxx BuildRequires: qemu-user-static-aarch64 %package -n musl-aarch64-clang Summary: Clang drivers for the aarch64-linux-musl cross target Requires: clang Requires: lld Requires: musl-aarch64-devel Requires: musl-aarch64-libc-static Requires: musl-aarch64-compiler-rt Requires: musl-aarch64-libcxx %description -n musl-aarch64-clang aarch64-linux-musl-clang and aarch64-linux-musl-clang++ drive the distribution clang at the aarch64-linux-musl target against the musl-aarch64 sysroot: pure LLVM (compiler-rt builtins, LLVM unwinder, libc++, lld), producing self-contained static aarch64 binaries with -static. %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 sed -e 's|@MUSL_A64_PREFIX@|%{musl_a64_prefix}|g' \ %{SOURCE1} > aarch64-linux-musl-clang sed -e 's|@MUSL_A64_PREFIX@|%{musl_a64_prefix}|g' \ %{SOURCE2} > aarch64-linux-musl-clang++ for w in aarch64-linux-musl-clang aarch64-linux-musl-clang++ ; do grep -q -- '--sysroot=%{musl_a64_prefix}' $w if grep -q '@MUSL' $w ; then echo "unsubstituted marker in $w" exit 1 fi done %install mkdir -p %{buildroot}%{_bindir} install -m 755 musl-clang++ %{buildroot}%{_bindir}/musl-clang++ install -m 755 aarch64-linux-musl-clang %{buildroot}%{_bindir}/aarch64-linux-musl-clang install -m 755 aarch64-linux-musl-clang++ %{buildroot}%{_bindir}/aarch64-linux-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' # --- The aarch64 drivers: static C and C++ probes, both RUN under # --- explicit qemu emulation. cat > _probe_c.c <<'EOF' #include int main(void) { printf("C on aarch64 musl\n"); return 0; } EOF %{buildroot}%{_bindir}/aarch64-linux-musl-clang -static -o _probe_a64_c _probe_c.c file _probe_a64_c file _probe_a64_c | grep -q 'ARM aarch64' file _probe_a64_c | grep -q 'statically linked' out=$(/usr/bin/qemu-aarch64-static ./_probe_a64_c) test "$out" = "C on aarch64 musl" %{buildroot}%{_bindir}/aarch64-linux-musl-clang++ -std=c++23 -static \ -o _probe_a64 _probe.cpp file _probe_a64 file _probe_a64 | grep -q 'ARM aarch64' file _probe_a64 | grep -q 'statically linked' out=$(/usr/bin/qemu-aarch64-static ./_probe_a64) echo "$out" test "$out" = "std::format on musl, exception: unwound" # The meson probe guard, for the cross drivers too. %{buildroot}%{_bindir}/aarch64-linux-musl-clang++ -std=c++23 \ -Werror=unused-command-line-argument -c -o _probe_a64.o _probe.cpp %files %{_bindir}/musl-clang++ %files -n musl-aarch64-clang %{_bindir}/aarch64-linux-musl-clang %{_bindir}/aarch64-linux-musl-clang++ %changelog * Thu Aug 20 2026 Erik Berg - 1-3 - Add musl-aarch64-clang: aarch64-linux-musl-clang and aarch64-linux-musl-clang++, drivers for the aarch64-linux-musl cross target -- pure LLVM (compiler-rt, LLVM unwinder, libc++, lld), since the host libgcc is x86_64 code - %%check links static C and C++ probes with the installed drivers and runs both under explicit qemu-aarch64-static emulation * 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)