summaryrefslogtreecommitdiff
blob: d587000e70f7fb3347e8af11b879f78107af1bd1 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# Copyright 1999-2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=8

inherit bash-completion-r1 llvm.org multilib

DESCRIPTION="Common files shared between multiple slots of clang"
HOMEPAGE="https://llvm.org/"

LICENSE="Apache-2.0-with-LLVM-exceptions UoI-NCSA"
SLOT="0"
KEYWORDS="~amd64 ~arm ~arm64 ~loong ~mips ~ppc ~ppc64 ~riscv ~sparc ~x86 ~amd64-linux ~arm64-macos ~ppc-macos ~x64-macos"
IUSE="
	default-compiler-rt default-libcxx default-lld
	bootstrap-prefix cet hardened llvm-libunwind
"

PDEPEND="
	default-compiler-rt? (
		sys-devel/clang-runtime:${LLVM_MAJOR}[compiler-rt]
		llvm-libunwind? ( sys-libs/llvm-libunwind[static-libs] )
		!llvm-libunwind? ( sys-libs/libunwind[static-libs] )
	)
	!default-compiler-rt? ( sys-devel/gcc )
	default-libcxx? ( >=sys-libs/libcxx-${PV}[static-libs] )
	!default-libcxx? ( sys-devel/gcc )
	default-lld? ( >=sys-devel/lld-${PV} )
	!default-lld? ( sys-devel/binutils )
"
IDEPEND="
	!default-compiler-rt? ( sys-devel/gcc-config )
	!default-libcxx? ( sys-devel/gcc-config )
"

LLVM_COMPONENTS=( clang/utils )
llvm.org_set_globals

pkg_pretend() {
	[[ ${CLANG_IGNORE_DEFAULT_RUNTIMES} ]] && return

	local flag missing_flags=()
	for flag in default-{compiler-rt,libcxx,lld}; do
		if ! use "${flag}" && has_version "sys-devel/clang[${flag}]"; then
			missing_flags+=( "${flag}" )
		fi
	done

	if [[ ${missing_flags[@]} ]]; then
		eerror "It seems that you have the following flags set on sys-devel/clang:"
		eerror
		eerror "  ${missing_flags[*]}"
		eerror
		eerror "The default runtimes are now set via flags on sys-devel/clang-common."
		eerror "The build is being aborted to prevent breakage.  Please either set"
		eerror "the respective flags on this ebuild, e.g.:"
		eerror
		eerror "  sys-devel/clang-common ${missing_flags[*]}"
		eerror
		eerror "or build with CLANG_IGNORE_DEFAULT_RUNTIMES=1."
		die "Mismatched defaults detected between sys-devel/clang and sys-devel/clang-common"
	fi
}

_doclang_cfg() {
	local triple="${1}"

	local tool
	for tool in ${triple}-clang{,++}; do
		newins - "${tool}.cfg" <<-EOF
			# This configuration file is used by ${tool} driver.
			@gentoo-common.cfg
			@gentoo-common-ld.cfg
		EOF
		if [[ ${triple} == x86_64* ]]; then
			cat >> "${ED}/etc/clang/${tool}.cfg" <<-EOF || die
				@gentoo-cet.cfg
			EOF
		fi
	done

	if use kernel_Darwin; then
		cat >> "${ED}/etc/clang/${triple}-clang++.cfg" <<-EOF || die
			-lc++abi
		EOF
	fi

	newins - "${triple}-clang-cpp.cfg" <<-EOF
		# This configuration file is used by the ${triple}-clang-cpp driver.
		@gentoo-common.cfg
	EOF
	if [[ ${triple} == x86_64* ]]; then
		cat >> "${ED}/etc/clang/${triple}-clang-cpp.cfg" <<-EOF || die
			@gentoo-cet.cfg
		EOF
	fi

	# Install symlinks for triples with other vendor strings since some
	# programs insist on mangling the triple.
	local vendor
	for vendor in gentoo pc unknown; do
		local vendor_triple="${triple%%-*}-${vendor}-${triple#*-*-}"
		for tool in clang{,++,-cpp}; do
			if [[ ! -f "${ED}/etc/clang/${vendor_triple}-${tool}.cfg" ]]; then
				dosym "${triple}-${tool}.cfg" "/etc/clang/${vendor_triple}-${tool}.cfg"
			fi
		done
	done
}

doclang_cfg() {
	local triple="${1}"

	_doclang_cfg ${triple}

	# LLVM may have different arch names in some cases. For example in x86
	# profiles the triple uses i686, but llvm will prefer i386 if invoked
	# with "clang" on x86 or "clang -m32" on x86_64. The gentoo triple will
	# be used if invoked through ${CHOST}-clang{,++,-cpp} though.
	#
	# To make sure the correct triples are installed,
	# see Triple::getArchTypeName() in llvm/lib/TargetParser/Triple.cpp
	# and compare with CHOST values in profiles.

	local abi=${triple%%-*}
	case ${abi} in
		armv4l|armv4t|armv5tel|armv6j|armv7a)
			_doclang_cfg ${triple/${abi}/arm}
			;;
		i686)
			_doclang_cfg ${triple/${abi}/i386}
			;;
		sparc)
			_doclang_cfg ${triple/${abi}/sparcel}
			;;
		sparc64)
			_doclang_cfg ${triple/${abi}/sparcv9}
			;;
	esac
}

src_install() {
	newbashcomp bash-autocomplete.sh clang

	insinto /etc/clang
	newins - gentoo-runtimes.cfg <<-EOF
		# This file is initially generated by sys-devel/clang-runtime.
		# It is used to control the default runtimes using by clang.

		--rtlib=$(usex default-compiler-rt compiler-rt libgcc)
		--unwindlib=$(usex default-compiler-rt libunwind libgcc)
		--stdlib=$(usex default-libcxx libc++ libstdc++)
		-fuse-ld=$(usex default-lld lld bfd)
	EOF

	newins - gentoo-gcc-install.cfg <<-EOF
		# This file is maintained by gcc-config.
		# It is used to specify the selected GCC installation.
	EOF

	newins - gentoo-common.cfg <<-EOF
		# This file contains flags common to clang, clang++ and clang-cpp.
		@gentoo-runtimes.cfg
		@gentoo-gcc-install.cfg
		@gentoo-hardened.cfg
		# bug #870001
		-include "${EPREFIX}/usr/include/gentoo/maybe-stddefs.h"
	EOF

	# clang-cpp does not like link args being passed to it when directly
	# invoked, so use a separate configuration file.
	newins - gentoo-common-ld.cfg <<-EOF
		# This file contains flags common to clang and clang++
		@gentoo-hardened-ld.cfg
	EOF

	# Baseline hardening (bug #851111)
	newins - gentoo-hardened.cfg <<-EOF
		# Some of these options are added unconditionally, regardless of
		# USE=hardened, for parity with sys-devel/gcc.
		-Xarch_host -fstack-clash-protection
		-Xarch_host -fstack-protector-strong
		-fPIE
		-include "${EPREFIX}/usr/include/gentoo/fortify.h"
	EOF

	newins - gentoo-cet.cfg <<-EOF
		-Xarch_host -fcf-protection=$(usex cet full none)
	EOF

	if use kernel_Darwin; then
		newins - gentoo-hardened-ld.cfg <<-EOF
			# There was -Wl,-z,relro here, but it's not supported on Mac
			# TODO: investigate whether -bind_at_load or -read_only_stubs will do the job
		EOF
	else
		newins - gentoo-hardened-ld.cfg <<-EOF
			# Some of these options are added unconditionally, regardless of
			# USE=hardened, for parity with sys-devel/gcc.
			-Wl,-z,relro
			-Wl,-z,now
		EOF
	fi

	dodir /usr/include/gentoo

	cat >> "${ED}/usr/include/gentoo/maybe-stddefs.h" <<-EOF || die
	/* __has_include is an extension, but it's fine, because this is only
	for Clang anyway. */
	#if defined __has_include && __has_include (<stdc-predef.h>) && !defined(__GLIBC__)
	# include <stdc-predef.h>
	#endif
	EOF

	local fortify_level=$(usex hardened 3 2)
	# We have to do this because glibc's headers warn if F_S is set
	# without optimization and that would at the very least be very noisy
	# during builds and at worst trigger many -Werror builds.
	cat >> "${ED}/usr/include/gentoo/fortify.h" <<- EOF || die
	#ifdef __clang__
	# pragma clang system_header
	#endif
	#ifndef _FORTIFY_SOURCE
	# if defined(__has_feature)
	#  define __GENTOO_HAS_FEATURE(x) __has_feature(x)
	# else
	#  define __GENTOO_HAS_FEATURE(x) 0
	# endif
	#
	# if defined(__STDC_HOSTED__) && __STDC_HOSTED__ == 1
	#  define __GENTOO_NOT_FREESTANDING 1
	# else
	#  define __GENTOO_NOT_FREESTANDING 0
	# endif
	#
	# if defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 && __GENTOO_NOT_FREESTANDING > 0
	#  if !defined(__SANITIZE_ADDRESS__) && !__GENTOO_HAS_FEATURE(address_sanitizer) && !__GENTOO_HAS_FEATURE(memory_sanitizer)
	#   define _FORTIFY_SOURCE ${fortify_level}
	#  endif
	# endif
	# undef __GENTOO_HAS_FEATURE
	# undef __GENTOO_NOT_FREESTANDING
	#endif
	EOF

	# TODO: Maybe -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST for
	# non-hardened?
	if use hardened ; then
		cat >> "${ED}/etc/clang/gentoo-hardened.cfg" <<-EOF || die
			# Options below are conditional on USE=hardened.
			-Xarch_host -D_GLIBCXX_ASSERTIONS

			# Analogue to GLIBCXX_ASSERTIONS
			# https://libcxx.llvm.org/UsingLibcxx.html#assertions-mode
			# https://libcxx.llvm.org/Hardening.html#using-hardened-mode
			-Xarch_host -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE
		EOF

		cat >> "${ED}/etc/clang/gentoo-hardened-ld.cfg" <<-EOF || die
			# Options below are conditional on USE=hardened.
		EOF
	fi

	# We only install config files for supported ABIs because unprefixed tools
	# might be used for crosscompilation where e.g. PIE may not be supported.
	# See bug #912237 and bug #901247. Just ${CHOST} won't do due to bug #912685.
	local abi
	for abi in $(get_all_abis); do
		local abi_chost=$(get_abi_CHOST "${abi}")
		doclang_cfg "${abi_chost}"
	done

	if use kernel_Darwin; then
		cat >> "${ED}/etc/clang/gentoo-common.cfg" <<-EOF || die
			# Gentoo Prefix on Darwin
			-Wl,-search_paths_first
		EOF
		if use bootstrap-prefix ; then
			# bootstrap-prefix is only set during stage2 of bootstrapping
			# Prefix, where EPREFIX is set to EPREFIX/tmp.
			# Here we need to point it at the future lib dir of the stage3's
			# EPREFIX.
			cat >> "${ED}/etc/clang/gentoo-common.cfg" <<-EOF || die
				-Wl,-rpath,${EPREFIX}/../usr/lib
				-Wl,-L,${EPREFIX}/../usr/lib
				-isystem ${EPREFIX}/../usr/include
			EOF
		fi
		# Using -Wl,-L instead of -L to trick compiler driver to put it
		# after -isysroot's internal -L
		cat >> "${ED}/etc/clang/gentoo-common.cfg" <<-EOF || die
			-Wl,-rpath,${EPREFIX}/usr/lib
			-Wl,-L,${EPREFIX}/usr/lib
			-isystem ${EPREFIX}/usr/include
			-isysroot ${EPREFIX}/MacOSX.sdk
		EOF
	fi
}

pkg_preinst() {
	if has_version -b sys-devel/gcc-config && has_version sys-devel/gcc
	then
		local gcc_path=$(gcc-config --get-lib-path 2>/dev/null)
		if [[ -n ${gcc_path} ]]; then
			cat >> "${ED}/etc/clang/gentoo-gcc-install.cfg" <<-EOF
				--gcc-install-dir="${gcc_path%%:*}"
			EOF
		fi
	fi
}