Use Fat LTO with Clang

Currently, when the clang toolchain is used, we use the
brp-llvm-compile-lto-to-elf script to post-process any shipped
object files or static libraries to convert the LLVM bitcode they
contain into ELF object code.

With LLVM 18, Clang has introduced support for fat LTO objects
(https://llvm.org/docs/FatLTO.html), which work essentially the
same way as with GCC: If `-ffat-lto-objects` is passed, then the
objects will contain both the ELF code, as well as the LLVM
bitcode in a special section.

This redhat-rpm-config change enables the use of fat LTO and
drops the brp-llvm-compile-lto-to-elf script. Instead, the
brp-strip-lto script used by GCC also strips the LLVM section
name now.

This is part of https://fedoraproject.org/wiki/Changes/LLVM-18.
This commit is contained in:
Nikita Popov 2023-12-06 10:09:28 +01:00
parent b7d1bfae1f
commit fed29a69be
4 changed files with 7 additions and 67 deletions

View File

@ -1,54 +0,0 @@
#!/usr/bin/bash -eu
if [ -z "$RPM_BUILD_ROOT" ] || [ "$RPM_BUILD_ROOT" = "/" ]; then
exit 0
fi
CLANG_FLAGS=$@
NCPUS=${RPM_BUILD_NCPUS:-1}
check_convert_bitcode () {
local file_name=$(realpath ${1})
local file_type=$(file ${file_name})
shift
CLANG_FLAGS="$@"
if [[ "${file_type}" == *"LLVM IR bitcode"* ]]; then
# Check the output of llvm-strings for the command line, which is in the LLVM bitcode because
# we pass -frecord-gcc-switches.
# Check for a line that has "-flto" after (or without) "-fno-lto".
llvm-strings ${file_name} | while read line ; do
flto=$(echo $line | grep -o -b -e -flto | tail -n 1 | cut -d : -f 1)
fnolto=$(echo $line | grep -o -b -e -fno-lto | tail -n 1 | cut -d : -f 1)
if test -n "$flto" && { test -z "$fnolto" || test "$flto" -gt "$fnolto"; } ; then
echo "Compiling LLVM bitcode file ${file_name}."
clang ${CLANG_FLAGS} -fno-lto -Wno-unused-command-line-argument \
-x ir ${file_name} -c -o ${file_name}
break
fi
done
elif [[ "${file_type}" == *"current ar archive"* ]]; then
echo "Unpacking ar archive ${file_name} to check for LLVM bitcode components."
# create archive stage for objects
local archive_stage=$(mktemp -d)
local archive=${file_name}
pushd ${archive_stage}
ar x ${archive}
for archived_file in $(find -not -type d); do
check_convert_bitcode ${archived_file} ${CLANG_FLAGS}
echo "Repacking ${archived_file} into ${archive}."
ar r ${archive} ${archived_file}
done
popd
fi
}
echo "Checking for LLVM bitcode artifacts"
export -f check_convert_bitcode
# Deduplicate by device:inode to avoid processing hardlinks in parallel.
find "$RPM_BUILD_ROOT" -type f -name "*.[ao]" -printf "%D:%i %p\n" | \
awk '!seen[$1]++' | cut -d" " -f2- | \
xargs -d"\n" -r -n1 -P$NCPUS sh -c "check_convert_bitcode \$@ $CLANG_FLAGS" ARG0

View File

@ -14,4 +14,5 @@ esac
# Strip ELF binaries
find "$RPM_BUILD_ROOT" -type f -name '*.[ao]' \! -regex "$RPM_BUILD_ROOT/*usr/lib/debug.*" -print0 | \
eu-elfclassify --not-program --not-library --not-linux-kernel-module --stdin0 --print0 | xargs -0 -r -P$NCPUS -n32 sh -c "$STRIP -p -R .gnu.lto_* -R .gnu.debuglto_* -N __gnu_lto_v1 \"\$@\"" ARG0
eu-elfclassify --not-program --not-library --not-linux-kernel-module --stdin0 --print0 | \
xargs -0 -r -P$NCPUS -n32 sh -c "$STRIP -p -R .gnu.lto_* -R .gnu.debuglto_* -R .llvm.lto -N __gnu_lto_v1 \"\$@\"" ARG0

5
macros
View File

@ -274,8 +274,6 @@ for k,_ in pairs(stripped_flags) do print(k .. " ") end
# __brp_mangle_shebangs_exclude_from_file - file from which to get files to ignore
%__brp_mangle_shebangs /usr/lib/rpm/redhat/brp-mangle-shebangs %{?__brp_mangle_shebangs_exclude:--shebangs "%{?__brp_mangle_shebangs_exclude}"} %{?__brp_mangle_shebangs_exclude_file:--shebangs-from "%{__brp_mangle_shebangs_exclude_file}"} %{?__brp_mangle_shebangs_exclude_from:--files "%{?__brp_mangle_shebangs_exclude_from}"} %{?__brp_mangle_shebangs_exclude_from_file:--files-from "%{__brp_mangle_shebangs_exclude_from_file}"}
%__brp_llvm_compile_lto_elf /usr/lib/rpm/redhat/brp-llvm-compile-lto-elf %{build_cflags} %{build_ldflags}
# note: %%__os_install_post_python is defined in python-srpm-macros and contains several policies
# redhat-rpm-config maintainers, don't remove it from %%__os_install_post unless coordinating the change with Python maintainers
# packagers, don't undefine the entire macro, see the individual macros in /usr/lib/rpm/macros.d/macros.python-srpm
@ -296,7 +294,6 @@ for k,_ in pairs(stripped_flags) do print(k .. " ") end
%{nil}
%__spec_install_post\
%[ "%{toolchain}" == "clang" ? "%{?__brp_llvm_compile_lto_elf}" : "%{nil}" ] \
%{?__debug_package:%{__debug_install_post}}\
%{__arch_install_post}\
%{__os_install_post}\
@ -394,7 +391,7 @@ for k,_ in pairs(stripped_flags) do print(k .. " ") end
# way we can detect installing an unusable .o/.a file. This is on the TODO
# list for F34.
%_gcc_lto_cflags -flto=auto -ffat-lto-objects
%_clang_lto_cflags -flto=thin
%_clang_lto_cflags -flto=thin -ffat-lto-objects
%_lto_cflags %{expand:%%{_%{toolchain}_lto_cflags}}
# Default fortification level.

View File

@ -4,7 +4,7 @@
# 2) When making changes, increment the version (in baserelease) by 1.
# rpmdev-bumpspec and other tools update the macro below, which is used
# in Version: to get the desired effect.
%global baserelease 287
%global baserelease 288
Summary: Red Hat specific rpm configuration files
Name: redhat-rpm-config
@ -59,9 +59,6 @@ Source158: macros.rpmautospec
# and an echo when the mangling happens
Source201: brp-mangle-shebangs
# for converting llvm LTO bitcode objects into ELF
Source204: brp-llvm-compile-lto-elf
# Dependency generator scripts (deprecated)
Source300: find-provides
Source304: find-requires
@ -133,10 +130,6 @@ Requires: %{_bindir}/grep
Requires: %{_bindir}/sed
Requires: %{_bindir}/xargs
# for brp-llvm-compile-lto-elf
Requires: (llvm if clang)
Requires: (gawk if clang)
# -fstack-clash-protection and -fcf-protection require GCC 8.
Conflicts: gcc < 8.0.1-0.22
@ -262,6 +255,9 @@ install -p -m 644 -t %{buildroot}%{_rpmluadir}/fedora common.lua
%doc buildflags.md
%changelog
* Thu Apr 11 2024 Nikita Popov <npopov@redhat.com> - 288-1
- Use Fat LTO with Clang
* Thu Mar 14 2024 Florian Weimer <fweimer@redhat.com> - 287-1
- Enable TLS descriptors on x86-64 (GCC only)