summaryrefslogtreecommitdiff
path: root/eclass/dot-a.eclass
blob: f82e5da5be897c1d1383932aeafd309780730d6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# 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

# 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

	# 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() {
	tc-is-lto || return

	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)

	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