mirror of
https://anongit.gentoo.org/git/repo/gentoo.git
synced 2025-07-22 06:57:59 +02:00
The current implementation checks repeatedly if `tc-is-lto` is true. In addition to running a small compile check redundantly, this has a potential correctness downside. An ebuild could do this: ``` lto-guarantee-fat tc-is-lto && myeconfargs+=( --enable-lto ) filter-lto ``` The idea is, the configure script has special handling and simply adding -flto is too "simple" to work. e.g. not all sources build with LTO. When this happens, strip-lto-bytecode "thinks" we didn't build with LTO at all, and returns early. By tracking state across functions -- and across phases -- we can reliably tell if `lto-guarantee-fat` actually "succeeded". Bug: https://bugs.gentoo.org/958412 Acked-by: Sam James <sam@gentoo.org> Signed-off-by: Eli Schwartz <eschwartz@gentoo.org>
128 lines
3.4 KiB
Bash
128 lines
3.4 KiB
Bash
# Copyright 2025 Gentoo Authors
|
|
# Distributed under the terms of the GNU General Public License v2
|
|
|
|
# @ECLASS: dot-a.eclass
|
|
# @MAINTAINER:
|
|
# Toolchain Ninjas <toolchain@gentoo.org>
|
|
# @AUTHOR:
|
|
# Sam James <sam@gentoo.org>
|
|
# Eli Schwartz <eschwartz@gentoo.org>
|
|
# @SUPPORTED_EAPIS: 8
|
|
# @BLURB: Functions to handle stripping LTO bytecode out of static archives.
|
|
# @DESCRIPTION:
|
|
# This eclass provides functions to strip LTO bytecode out of static archives
|
|
# (.a files).
|
|
#
|
|
# Static libraries when built with LTO will contain LTO bytecode which is
|
|
# not portable across compiler versions or compiler vendors. To avoid pessimising
|
|
# the library and always filtering LTO, we can build it with -ffat-lto-objects
|
|
# instead, which builds some components twice. The installed part will then
|
|
# have the LTO contents stripped out, leaving the regular objects in the
|
|
# static archive.
|
|
#
|
|
# Use should be passing calling lto-guarantee-fat before configure-time
|
|
# and calling strip-lto-bytecode after installation.
|
|
#
|
|
# Most packages installing static libraries should be using this eclass,
|
|
# though it's not strictly necessary if the package filters LTO.
|
|
#
|
|
# @EXAMPLE:
|
|
# @CODE
|
|
#
|
|
# inherit dot-a
|
|
#
|
|
# src_configure() {
|
|
# lto-guarantee-fat
|
|
# econf
|
|
# }
|
|
#
|
|
# src_install() {
|
|
# default
|
|
# strip-lto-bytecode
|
|
# }
|
|
case ${EAPI} in
|
|
8) ;;
|
|
*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
|
|
esac
|
|
|
|
if [[ -z ${_DOT_A_ECLASS} ]] ; then
|
|
_DOT_A_ECLASS=1
|
|
|
|
inherit flag-o-matic toolchain-funcs
|
|
|
|
# @VARIABLE: _DOT_A_IS_LTO
|
|
# @INTERNAL
|
|
# @DESCRIPTION:
|
|
# Records the state of tc-is-lto across eclass function calls.
|
|
_DOT_A_IS_LTO=0
|
|
|
|
# TODO: QA check
|
|
|
|
# @FUNCTION: lto-guarantee-fat
|
|
# @DESCRIPTION:
|
|
# If LTO is enabled, appends -ffat-lto-objects or any other flags needed
|
|
# to provide fat LTO objects.
|
|
lto-guarantee-fat() {
|
|
tc-is-lto || return
|
|
|
|
_DOT_A_IS_LTO=1
|
|
# We add this for all languages as LTO obviously can't be done
|
|
# if different compilers are used for e.g. C vs C++ anyway.
|
|
append-flags $(test-flags-CC -ffat-lto-objects)
|
|
}
|
|
|
|
# @FUNCTION: strip-lto-bytecode
|
|
# @USAGE: [library|directory] [...]
|
|
# @DESCRIPTION:
|
|
# Strips LTO bytecode from libraries (static archives) passed as arguments.
|
|
# Defaults to operating on ${ED} as a whole if no arguments are passed.
|
|
#
|
|
# As an optimisation, if USE=static-libs exists for a package and is disabled,
|
|
# the default-searching behaviour with no arguments is suppressed.
|
|
strip-lto-bytecode() {
|
|
if [[ ${_DOT_A_IS_LTO} != 1 ]] && ! tc-is-lto; then
|
|
return
|
|
fi
|
|
|
|
local files=()
|
|
|
|
if [[ ${#} -eq 0 ]]; then
|
|
if ! in_iuse static-libs || use static-libs ; then
|
|
# maybe we are USE=static-libs. Alternatively, maybe the ebuild doesn't
|
|
# offer such a choice. In both cases, the user specified the function,
|
|
# so we expect to be called on *something*, but nothing was explicitly
|
|
# passed. Try scanning ${ED} automatically.
|
|
set -- "${ED}"
|
|
else
|
|
return
|
|
fi
|
|
fi
|
|
|
|
mapfile -t -d '' files < <(find -H "${@}" -type f \( -name '*.a' -or -name '*.o' \) -print0)
|
|
|
|
local toolchain_type=
|
|
tc-is-gcc && toolchain_type=gnu
|
|
tc-is-clang && toolchain_type=llvm
|
|
|
|
local file
|
|
for file in "${files[@]}" ; do
|
|
case ${toolchain_type} in
|
|
gnu)
|
|
$(tc-getSTRIP) \
|
|
-R .gnu.lto_* \
|
|
-R .gnu.debuglto_* \
|
|
-N __gnu_lto_v1 \
|
|
"${file}" || die "Stripping bytecode in ${file} failed"
|
|
;;
|
|
llvm)
|
|
llvm-bitcode-strip \
|
|
-r "${file}" \
|
|
-o "${file}" || die "Stripping bytecode in ${file} failed"
|
|
;;
|
|
*)
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
fi
|