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