@@ -17,6 +17,8 @@ READELF = "${HOST_PREFIX}readelf"
PREFERRED_PROVIDER_virtual/${MLPREFIX}cross-cc = "${MLPREFIX}gcc-cross-${TARGET_ARCH}"
PREFERRED_PROVIDER_virtual/${MLPREFIX}cross-c++ = "${MLPREFIX}gcc-cross-${TARGET_ARCH}"
PREFERRED_PROVIDER_virtual/${MLPREFIX}compilerlibs = "${MLPREFIX}gcc-runtime"
+# libatomic, which gcc links by default, comes from compiler-rt in this case
+BASE_DEFAULT_DEPS:append:class-target = "${@' ${MLPREFIX}compiler-rt' if d.getVar('LIBATOMIC_PROVIDER') == 'compiler-rt' else ''}"
PREFERRED_PROVIDER_virtual/${MLPREFIX}cross-cc:class-nativesdk = "gcc-crosssdk-${SDK_SYS}"
PREFERRED_PROVIDER_virtual/${MLPREFIX}cross-c++:class-nativesdk = "gcc-crosssdk-${SDK_SYS}"
@@ -406,6 +406,8 @@ FILESYSTEM_PERMS_TABLES ?= "files/fs-perms.txt \
TCMODE ??= "default"
TCLIBC ??= "glibc"
TC_CXX_RUNTIME ??= "gnu"
+# Recipe providing libatomic for the target: "gcc-runtime" or "compiler-rt"
+LIBATOMIC_PROVIDER ??= "gcc-runtime"
TMPDIR ?= "${TOPDIR}/tmp"
CACHE = "${TMPDIR}/cache"
@@ -35,7 +35,12 @@ RPROVIDES:${PN}-dev += "${@bb.utils.contains("TC_CXX_RUNTIME", "llvm", "libgcc-d
RPROVIDES:${PN}-dbg += "${@bb.utils.contains("TC_CXX_RUNTIME", "llvm", "libgcc-dbg", "", d)}"
PACKAGECONFIG ??= "${@bb.utils.contains("TC_CXX_RUNTIME", "llvm", "crt", "", d)}"
+PACKAGECONFIG:append:class-target = "${@' libatomic' if d.getVar('LIBATOMIC_PROVIDER') == 'compiler-rt' else ''}"
PACKAGECONFIG[crt] = "-DCOMPILER_RT_BUILD_CRT:BOOL=ON,-DCOMPILER_RT_BUILD_CRT:BOOL=OFF"
+PACKAGECONFIG[libatomic] = "-DCOMPILER_RT_BUILD_STANDALONE_LIBATOMIC=ON \
+ -DCOMPILER_RT_LIBATOMIC_LINK_FLAGS=-nostartfiles \
+ -DCOMPILER_RT_LIBATOMIC_LINK_LIBS_${COMPILER_RT_ARCH}=c, \
+ -DCOMPILER_RT_BUILD_STANDALONE_LIBATOMIC=OFF,patchelf-native"
PACKAGECONFIG[profile] = "-DCOMPILER_RT_BUILD_PROFILE=ON,-DCOMPILER_RT_BUILD_PROFILE=OFF"
# Context Profiling, might need to enable 'profile' too
PACKAGECONFIG[ctx-profile] = "-DCOMPILER_RT_BUILD_CTX_PROFILE=ON,-DCOMPILER_RT_BUILD_CTX_PROFILE=OFF"
@@ -57,6 +62,8 @@ def get_compiler_rt_arch(bb, d):
return 'armhf'
return d.getVar('HOST_ARCH')
+COMPILER_RT_ARCH = "${@get_compiler_rt_arch(bb, d)}"
+
INSTALL_VER ?= "${MAJOR_VER}.${MINOR_VER}.${PATCH_VER}${VER_SUFFIX}"
INSTALL_VER:class-native = "${@oe.utils.trim_version("${PV}", 1)}"
@@ -115,8 +122,29 @@ do_install:append () {
ln -sf clang/${INSTALL_VER}/lib/linux/clang_rt.crtend-${@get_compiler_rt_arch(bb, d)}.o ${D}${nonarch_libdir}/crtend.o
ln -sf clang/${INSTALL_VER}/lib/linux/clang_rt.crtend-${@get_compiler_rt_arch(bb, d)}.o ${D}${nonarch_libdir}/crtendS.o
fi
+ if ${@bb.utils.contains('PACKAGECONFIG', 'libatomic', 'true', 'false', d)}; then
+ # Install libatomic with the same names and layout as gcc-runtime
+ install -d ${D}${libdir}
+ mv ${D}${nonarch_libdir}/clang/${INSTALL_VER}/lib/linux/libclang_rt.atomic-${COMPILER_RT_ARCH}.so \
+ ${D}${libdir}/libatomic.so.1.2.0
+ patchelf --set-soname libatomic.so.1 ${D}${libdir}/libatomic.so.1.2.0
+ ln -sf libatomic.so.1.2.0 ${D}${libdir}/libatomic.so.1
+ ln -sf libatomic.so.1.2.0 ${D}${libdir}/libatomic.so
+ ${AR} rcs ${D}${libdir}/libatomic.a \
+ ${B}/compiler-rt/lib/builtins/CMakeFiles/clang_rt.atomic*-${COMPILER_RT_ARCH}.dir/atomic.c.o
+ ln -sf libatomic.a ${D}${libdir}/libatomic_asneeded.a
+ # gcc links -latomic_asneeded by default
+ printf '/* GNU ld script\n Add DT_NEEDED entry for -latomic only if needed. */\nINPUT ( AS_NEEDED ( -latomic ) )\n' \
+ > ${D}${libdir}/libatomic_asneeded.so
+ fi
}
+PACKAGES =+ "${@bb.utils.contains('PACKAGECONFIG', 'libatomic', 'libatomic libatomic-dev libatomic-staticdev', '', d)}"
+SUMMARY:libatomic = "C11/C++11 atomics support library from compiler-rt"
+FILES:libatomic = "${libdir}/libatomic.so.*"
+FILES:libatomic-dev = "${libdir}/libatomic.so ${libdir}/libatomic_asneeded.so"
+FILES:libatomic-staticdev = "${libdir}/libatomic.a ${libdir}/libatomic_asneeded.a"
+
FILES:${PN} += "${nonarch_libdir}/clang/${INSTALL_VER}/lib/linux/lib*${SOLIBSDEV} \
${nonarch_libdir}/clang/${INSTALL_VER}/*.txt \
${nonarch_libdir}/clang/${INSTALL_VER}/share/*.txt \
@@ -47,7 +47,10 @@ RUNTIMELIBITM:loongarch64 = ""
RUNTIMELIBSSP ?= ""
RUNTIMELIBSSP:mingw32 ?= "libssp"
-RUNTIMETARGET = "${RUNTIMELIBSSP} libstdc++-v3 libgomp libatomic ${RUNTIMELIBITM} \
+# compiler-rt can provide libatomic for the target instead
+RUNTIMELIBATOMIC = "${@'' if d.getVar('LIBATOMIC_PROVIDER') == 'compiler-rt' else 'libatomic'}"
+RUNTIMELIBATOMIC:class-nativesdk = "libatomic"
+RUNTIMETARGET = "${RUNTIMELIBSSP} libstdc++-v3 libgomp ${RUNTIMELIBATOMIC} ${RUNTIMELIBITM} \
${@bb.utils.contains('FORTRAN', ',fortran', 'libquadmath', '', d)} \
"
# Only build libstdc++ for newlib
@@ -193,9 +196,7 @@ PACKAGES = "\
libgomp \
libgomp-dev \
libgomp-staticdev \
- libatomic \
- libatomic-dev \
- libatomic-staticdev \
+ ${@'${RUNTIMELIBATOMIC} ${RUNTIMELIBATOMIC}-dev ${RUNTIMELIBATOMIC}-staticdev' if d.getVar('RUNTIMELIBATOMIC') else ''} \
libitm \
libitm-dev \
libitm-staticdev \
Add LIBATOMIC_PROVIDER to select the recipe providing libatomic for the target. It defaults to "gcc-runtime", which keeps the current behaviour. With LIBATOMIC_PROVIDER = "compiler-rt" - compiler-rt builds its standalone shared libatomic from atomic.c and installs it with the same layout as gcc-runtime: libatomic.so.1.2.0 with soname libatomic.so.1, the libatomic.so.1 and libatomic.so symlinks, a libatomic.a archive, and the libatomic_asneeded.a and libatomic_asneeded.so files gcc 16 links by default. They go in the libatomic, libatomic-dev and libatomic-staticdev packages, so package names and runtime dependencies stay the same. - gcc-runtime no longer builds or packages libatomic for the target. - Recipes built with gcc also depend on compiler-rt, since gcc links -latomic_asneeded into every link. The upstream standalone libatomic does not link as is, LLVM links shared libraries with -z defs and compiler-rt uses -nodefaultlibs, but the generic __atomic_* functions call memcpy/memcmp, so link with libc. atomic.c has no constructors, so link it with -nostartfiles. The shared library keeps one lock table per process for atomics that are not lock free, e.g. 64-bit atomics on riscv32, as libatomic does. The atomic builtins in the static libclang_rt.builtins archive would instead give each executable and shared library its own hidden lock table, which loses updates when they access the same object. Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com> --- meta/classes/toolchain/gcc.bbclass | 2 ++ meta/conf/bitbake.conf | 2 ++ .../recipes-devtools/clang/compiler-rt_git.bb | 28 +++++++++++++++++++ meta/recipes-devtools/gcc/gcc-runtime.inc | 9 +++--- 4 files changed, 37 insertions(+), 4 deletions(-)