libshit

Just some random shit
git clone https://git.neptards.moe/neptards/libshit.git
Log | Files | Refs | Submodules | README | LICENSE

llvm.eclass (8277B)


      1 # Copyright 1999-2022 Gentoo Authors
      2 # Distributed under the terms of the GNU General Public License v2
      3 
      4 # @ECLASS: llvm.eclass
      5 # @MAINTAINER:
      6 # Michał Górny <mgorny@gentoo.org>
      7 # @AUTHOR:
      8 # Michał Górny <mgorny@gentoo.org>
      9 # @SUPPORTED_EAPIS: 6 7 8
     10 # @BLURB: Utility functions to build against slotted LLVM
     11 # @DESCRIPTION:
     12 # The llvm.eclass provides utility functions that can be used to build
     13 # against specific version of slotted LLVM (with fallback to :0 for old
     14 # versions).
     15 #
     16 # This eclass does not generate dependency strings. You need to write
     17 # a proper dependency string yourself to guarantee that appropriate
     18 # version of LLVM is installed.
     19 #
     20 # Example use for a package supporting LLVM 9 to 11:
     21 # @CODE
     22 # inherit cmake llvm
     23 #
     24 # RDEPEND="
     25 #	<sys-devel/llvm-11:=
     26 #	|| (
     27 #		sys-devel/llvm:9
     28 #		sys-devel/llvm:10
     29 #		sys-devel/llvm:11
     30 #	)
     31 # "
     32 # DEPEND=${RDEPEND}
     33 #
     34 # LLVM_MAX_SLOT=11
     35 #
     36 # # only if you need to define one explicitly
     37 # pkg_setup() {
     38 #	llvm_pkg_setup
     39 #	do-something-else
     40 # }
     41 # @CODE
     42 #
     43 # Example for a package needing LLVM+clang w/ a specific target:
     44 # @CODE
     45 # inherit cmake llvm
     46 #
     47 # # note: do not use := on both clang and llvm, it can match different
     48 # # slots then. clang pulls llvm in, so we can skip the latter.
     49 # RDEPEND="
     50 #	>=sys-devel/clang-9:=[llvm_targets_AMDGPU(+)]
     51 # "
     52 # DEPEND=${RDEPEND}
     53 #
     54 # llvm_check_deps() {
     55 #	has_version -d "sys-devel/clang:${LLVM_SLOT}[llvm_targets_AMDGPU(+)]"
     56 # }
     57 # @CODE
     58 
     59 case "${EAPI:-0}" in
     60 	0|1|2|3|4|5)
     61 		die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
     62 		;;
     63 	6|7|8)
     64 		;;
     65 	*)
     66 		die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
     67 		;;
     68 esac
     69 
     70 EXPORT_FUNCTIONS pkg_setup
     71 
     72 if [[ ! ${_LLVM_ECLASS} ]]; then
     73 
     74 # make sure that the versions installing straight into /usr/bin
     75 # are uninstalled
     76 DEPEND="!!sys-devel/llvm:0"
     77 
     78 # @ECLASS_VARIABLE: LLVM_MAX_SLOT
     79 # @DEFAULT_UNSET
     80 # @DESCRIPTION:
     81 # Highest LLVM slot supported by the package. Needs to be set before
     82 # llvm_pkg_setup is called. If unset, no upper bound is assumed.
     83 
     84 # @ECLASS_VARIABLE: _LLVM_KNOWN_SLOTS
     85 # @INTERNAL
     86 # @DESCRIPTION:
     87 # Correct values of LLVM slots, newest first.
     88 declare -g -r _LLVM_KNOWN_SLOTS=( {16..8} )
     89 
     90 # @FUNCTION: get_llvm_slot
     91 # @USAGE: [-b|-d] [<max_slot>]
     92 # @DESCRIPTION:
     93 # Find the newest LLVM install that is acceptable for the package,
     94 # and print its major version number (i.e. slot).
     95 #
     96 # If -b is specified, the checks are performed relative to BROOT,
     97 # and BROOT-path is returned.  This is appropriate when your package
     98 # calls llvm-config executable.  -b is supported since EAPI 7.
     99 #
    100 # If -d is specified, the checks are performed relative to ESYSROOT,
    101 # and ESYSROOT-path is returned.  This is appropriate when your package
    102 # uses CMake find_package(LLVM).  -d is the default.
    103 #
    104 # If <max_slot> is specified, then only LLVM versions that are not newer
    105 # than <max_slot> will be considered. Otherwise, all LLVM versions would
    106 # be considered acceptable. The function does not support specifying
    107 # minimal supported version -- the developer must ensure that a version
    108 # new enough is installed via providing appropriate dependencies.
    109 #
    110 # If llvm_check_deps() function is defined within the ebuild, it will
    111 # be called to verify whether a particular slot is accepable. Within
    112 # the function scope, LLVM_SLOT will be defined to the SLOT value
    113 # (0, 4, 5...). The function should return a true status if the slot
    114 # is acceptable, false otherwise. If llvm_check_deps() is not defined,
    115 # the function defaults to checking whether sys-devel/llvm:${LLVM_SLOT}
    116 # is installed.
    117 get_llvm_slot() {
    118 	debug-print-function ${FUNCNAME} "${@}"
    119 
    120 	local hv_switch=-d
    121 	while [[ ${1} == -* ]]; do
    122 		case ${1} in
    123 			-b|-d) hv_switch=${1};;
    124 			*) break;;
    125 		esac
    126 		shift
    127 	done
    128 
    129 	if [[ ${EAPI} == 6 ]]; then
    130 		case ${hv_switch} in
    131 			-b)
    132 				die "${FUNCNAME} -b is not supported in EAPI ${EAPI}"
    133 				;;
    134 			-d)
    135 				hv_switch=
    136 				;;
    137 		esac
    138 	fi
    139 
    140 	local max_slot=${1}
    141 	local slot
    142 	for slot in "${_LLVM_KNOWN_SLOTS[@]}"; do
    143 		# skip higher slots
    144 		if [[ -n ${max_slot} ]]; then
    145 			if [[ ${max_slot} == ${slot} ]]; then
    146 				max_slot=
    147 			else
    148 				continue
    149 			fi
    150 		fi
    151 
    152 		if declare -f llvm_check_deps >/dev/null; then
    153 			local LLVM_SLOT=${slot}
    154 			llvm_check_deps || continue
    155 		else
    156 			# check if LLVM package is installed
    157 			has_version ${hv_switch} "sys-devel/llvm:${slot}" || continue
    158 		fi
    159 
    160 		echo "${slot}"
    161 		return
    162 	done
    163 
    164 	# max_slot should have been unset in the iteration
    165 	if [[ -n ${max_slot} ]]; then
    166 		die "${FUNCNAME}: invalid max_slot=${max_slot}"
    167 	fi
    168 
    169 	die "No LLVM slot${1:+ <= ${1}} satisfying the package's dependencies found installed!"
    170 }
    171 
    172 # @FUNCTION: get_llvm_prefix
    173 # @USAGE: [-b|-d] [<max_slot>]
    174 # @DESCRIPTION:
    175 # Find the newest LLVM install that is acceptable for the package,
    176 # and print an absolute path to it.
    177 #
    178 # The options and behavior is the same as for get_llvm_slot.
    179 get_llvm_prefix() {
    180 	debug-print-function ${FUNCNAME} "${@}"
    181 
    182 	local prefix=${EPREFIX}
    183 	if [[ ${EAPI} != 6 ]]; then
    184 		case ${1} in
    185 			-b)
    186 				prefix=${BROOT}
    187 				;;
    188 			*)
    189 				prefix=${ESYSROOT}
    190 				;;
    191 		esac
    192 	fi
    193 
    194 	echo "${prefix}/usr/lib/llvm/$(get_llvm_slot "${@}")"
    195 }
    196 
    197 # @FUNCTION: llvm_fix_clang_version
    198 # @USAGE: <variable-name>...
    199 # @DESCRIPTION:
    200 # Fix the clang compiler name in specified variables to include
    201 # the major version, to prevent PATH alterations from forcing an older
    202 # clang version being used.
    203 llvm_fix_clang_version() {
    204 	debug-print-function ${FUNCNAME} "${@}"
    205 
    206 	local shopt_save=$(shopt -p -o noglob)
    207 	set -f
    208 	local var
    209 	for var; do
    210 		local split=( ${!var} )
    211 		case ${split[0]} in
    212 			*clang|*clang++|*clang-cpp)
    213 				local version=()
    214 				read -r -a version < <("${split[0]}" --version)
    215 				local major=${version[-1]%%.*}
    216 				if [[ -n ${major//[0-9]} ]]; then
    217 					die "${var}=${!var} produced invalid --version: ${version[*]}"
    218 				fi
    219 
    220 				split[0]+=-${major}
    221 				if ! type -P "${split[0]}" &>/dev/null; then
    222 					die "${split[0]} does not seem to exist"
    223 				fi
    224 				declare -g "${var}=${split[*]}"
    225 				;;
    226 		esac
    227 	done
    228 	${shopt_save}
    229 }
    230 
    231 # @FUNCTION: llvm_fix_tool_path
    232 # @USAGE: <variable-name>...
    233 # @DESCRIPTION:
    234 # Fix the LLVM tools referenced in the specified variables to their
    235 # current location, to prevent PATH alterations from forcing older
    236 # versions being used.
    237 llvm_fix_tool_path() {
    238 	debug-print-function ${FUNCNAME} "${@}"
    239 
    240 	local shopt_save=$(shopt -p -o noglob)
    241 	set -f
    242 	local var
    243 	for var; do
    244 		local split=( ${!var} )
    245 		local path=$(type -P ${split[0]} 2>/dev/null)
    246 		# if it resides in one of the LLVM prefixes, it's an LLVM tool!
    247 		if [[ ${path} == "${BROOT}/usr/lib/llvm"* ]]; then
    248 			split[0]=${path}
    249 			declare -g "${var}=${split[*]}"
    250 		fi
    251 	done
    252 	${shopt_save}
    253 }
    254 
    255 # @FUNCTION: llvm_pkg_setup
    256 # @DESCRIPTION:
    257 # Prepend the appropriate executable directory for the newest
    258 # acceptable LLVM slot to the PATH. For path determination logic,
    259 # please see the get_llvm_prefix documentation.
    260 #
    261 # The highest acceptable LLVM slot can be set in LLVM_MAX_SLOT variable.
    262 # If it is unset or empty, any slot is acceptable.
    263 #
    264 # The PATH manipulation is only done for source builds. The function
    265 # is a no-op when installing a binary package.
    266 #
    267 # If any other behavior is desired, the contents of the function
    268 # should be inlined into the ebuild and modified as necessary.
    269 llvm_pkg_setup() {
    270 	debug-print-function ${FUNCNAME} "${@}"
    271 
    272 	if [[ ${MERGE_TYPE} != binary ]]; then
    273 		LLVM_SLOT=$(get_llvm_slot "${LLVM_MAX_SLOT}")
    274 
    275 		llvm_fix_clang_version CC CPP CXX
    276 		# keep in sync with profiles/features/llvm/make.defaults!
    277 		llvm_fix_tool_path ADDR2LINE AR AS LD NM OBJCOPY OBJDUMP RANLIB
    278 		llvm_fix_tool_path READELF STRINGS STRIP
    279 
    280 		local prefix=${EPREFIX}
    281 		[[ ${EAPI} != 6 ]] && prefix=${ESYSROOT}
    282 		local llvm_path=${prefix}/usr/lib/llvm/${LLVM_SLOT}/bin
    283 		local IFS=:
    284 		local split_path=( ${PATH} )
    285 		local new_path=()
    286 		local x added=
    287 
    288 		# prepend new path before first LLVM version found
    289 		for x in "${split_path[@]}"; do
    290 			if [[ ${x} == */usr/lib/llvm/*/bin ]]; then
    291 				if [[ ${x} != ${llvm_path} ]]; then
    292 					new_path+=( "${llvm_path}" )
    293 				elif [[ ${added} && ${x} == ${llvm_path} ]]; then
    294 					# deduplicate
    295 					continue
    296 				fi
    297 				added=1
    298 			fi
    299 			new_path+=( "${x}" )
    300 		done
    301 		# ...or to the end of PATH
    302 		[[ ${added} ]] || new_path+=( "${llvm_path}" )
    303 
    304 		export PATH=${new_path[*]}
    305 	fi
    306 }
    307 
    308 _LLVM_ECLASS=1
    309 fi