From 0bb42730e8fc9c8e571f12e3189c6c6f8d532c24 Mon Sep 17 00:00:00 2001 From: V3n3RiX Date: Sat, 10 Feb 2024 17:34:25 +0000 Subject: gentoo auto-resync : 10:02:2024 - 17:34:25 --- eclass/Manifest.gz | Bin 39123 -> 39761 bytes eclass/dotnet-pkg-base.eclass | 124 +++++++++++++-------- eclass/dotnet-pkg.eclass | 69 +++++++++++- eclass/llvm-r1.eclass | 250 ++++++++++++++++++++++++++++++++++++++++++ eclass/llvm-utils.eclass | 153 ++++++++++++++++++++++++++ eclass/llvm.eclass | 117 +------------------- eclass/nuget.eclass | 47 +++++++- eclass/tests/llvm-r1.sh | 151 +++++++++++++++++++++++++ eclass/tests/llvm-utils.sh | 118 ++++++++++++++++++++ 9 files changed, 869 insertions(+), 160 deletions(-) create mode 100644 eclass/llvm-r1.eclass create mode 100644 eclass/llvm-utils.eclass create mode 100755 eclass/tests/llvm-r1.sh create mode 100755 eclass/tests/llvm-utils.sh (limited to 'eclass') diff --git a/eclass/Manifest.gz b/eclass/Manifest.gz index 33e99f13acc7..cb928087604c 100644 Binary files a/eclass/Manifest.gz and b/eclass/Manifest.gz differ diff --git a/eclass/dotnet-pkg-base.eclass b/eclass/dotnet-pkg-base.eclass index 1a9d311208e2..a2d95f15a2fb 100644 --- a/eclass/dotnet-pkg-base.eclass +++ b/eclass/dotnet-pkg-base.eclass @@ -1,4 +1,4 @@ -# Copyright 1999-2023 Gentoo Authors +# Copyright 1999-2024 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: dotnet-pkg-base.eclass @@ -68,13 +68,19 @@ if [[ ${CATEGORY}/${PN} != dev-dotnet/dotnet-runtime-nugets ]] ; then die "${ECLASS}: DOTNET_PKG_COMPAT not set" fi - DOTNET_PKG_RDEPS+=" virtual/dotnet-sdk:${DOTNET_PKG_COMPAT} " - DOTNET_PKG_BDEPS+=" ${DOTNET_PKG_RDEPS} " + DOTNET_PKG_RDEPS+=" + virtual/dotnet-sdk:${DOTNET_PKG_COMPAT} + " + DOTNET_PKG_BDEPS+=" + ${DOTNET_PKG_RDEPS} + " # Special package "dev-dotnet/csharp-gentoodotnetinfo" used for information # gathering, example for usage see the "dotnet-pkg-base_info" function. if [[ ${CATEGORY}/${PN} != dev-dotnet/csharp-gentoodotnetinfo ]] ; then - DOTNET_PKG_BDEPS+=" dev-dotnet/csharp-gentoodotnetinfo " + DOTNET_PKG_BDEPS+=" + dev-dotnet/csharp-gentoodotnetinfo + " fi IUSE+=" debug " @@ -222,28 +228,27 @@ dotnet-pkg-base_get-runtime() { # # Used by "dotnet-pkg_pkg_setup" from the "dotnet-pkg" eclass. dotnet-pkg-base_setup() { - local dotnet_compat_impl - local dotnet_compat_impl_path - for dotnet_compat_impl in dotnet{,-bin}-${DOTNET_PKG_COMPAT} ; do - dotnet_compat_impl_path="$(type -P "${dotnet_compat_impl}")" + local -a impl_dirs=( + "${EPREFIX}/usr/$(get_libdir)/dotnet-sdk-${DOTNET_PKG_COMPAT}" + "${EPREFIX}/opt/dotnet-sdk-bin-${DOTNET_PKG_COMPAT}" + ) + local impl_exe + + local impl_dir + for impl_dir in "${impl_dirs[@]}" ; do + impl_exe="${impl_dir}/dotnet" + + if [[ -d "${impl_dir}" ]] && [[ -x "${impl_exe}" ]] ; then + DOTNET_PKG_EXECUTABLE="${impl_exe}" + DOTNET_ROOT="${impl_dir}" - if [[ -n ${dotnet_compat_impl_path} ]] ; then - DOTNET_PKG_EXECUTABLE="${dotnet_compat_impl}" break fi done - # Link "DOTNET_PKG_EXECUTABLE" to "dotnet" only for the package build. - local dotnet_spoof_path="${T}/dotnet_spoof/${DOTNET_PKG_COMPAT}" - mkdir -p "${dotnet_spoof_path}" || die - ln -s "${dotnet_compat_impl_path}" "${dotnet_spoof_path}/dotnet" || die - export PATH="${dotnet_spoof_path}:${PATH}" - - einfo "Using dotnet SDK \"${DOTNET_PKG_EXECUTABLE}\" from \"${dotnet_compat_impl_path}\"." - - # The picked "DOTNET_PKG_EXECUTABLE" should set "DOTNET_ROOT" internally - # and not rely upon this environment variable. - unset DOTNET_ROOT + einfo "Setting .NET SDK \"DOTNET_ROOT\" to \"${DOTNET_ROOT}\"" + export DOTNET_ROOT + export PATH="${DOTNET_ROOT}:${PATH}" DOTNET_PKG_RUNTIME="$(dotnet-pkg-base_get-runtime)" DOTNET_PKG_CONFIGURATION="$(dotnet-pkg-base_get-configuration)" @@ -304,6 +309,21 @@ dotnet-pkg-base_info() { fi } +# @FUNCTION: dotnet-pkg-base_sln-remove +# @USAGE: +# @DESCRIPTION: +# Remove a project from a given solution file. +# +# Used by "dotnet-pkg_remove-bad" from the "dotnet-pkg" eclass. +dotnet-pkg-base_sln-remove() { + debug-print-function "${FUNCNAME[0]}" "${@}" + + [[ -z ${1} ]] && die "${FUNCNAME[0]}: no solution file specified" + [[ -z ${2} ]] && die "${FUNCNAME[0]}: no project file specified" + + edotnet sln "${1}" remove "${2}" +} + # @FUNCTION: dotnet-pkg-base_foreach-solution # @USAGE: ... # @DESCRIPTION: @@ -354,7 +374,7 @@ dotnet-pkg-base_restore() { edotnet restore "${restore_args[@]}" } -# @FUNCTION: dotnet-pkg-base_restore_tools +# @FUNCTION: dotnet-pkg-base_restore-tools # @USAGE: [config-file] [args] ... # @DESCRIPTION: # Restore dotnet tools for a project in the current directory. @@ -364,7 +384,7 @@ dotnet-pkg-base_restore() { # # Additionally any number of "args" maybe be given, they are appended to # the "dotnet" command invocation. -dotnet-pkg-base_restore_tools() { +dotnet-pkg-base_restore-tools() { debug-print-function "${FUNCNAME[0]}" "${@}" local -a tool_restore_args=( @@ -381,6 +401,14 @@ dotnet-pkg-base_restore_tools() { edotnet tool restore "${tool_restore_args[@]}" } +# @FUNCTION: dotnet-pkg-base_restore_tools +# @USAGE: [config-file] [args] ... +# @DESCRIPTION: +# DEPRECATED, use "dotnet-pkg-base_restore-tools" instead. +dotnet-pkg-base_restore_tools() { + dotnet-pkg-base_restore-tools "${@}" +} + # @FUNCTION: dotnet-pkg-base_build # @USAGE: [args] ... # @DESCRIPTION: @@ -388,8 +416,8 @@ dotnet-pkg-base_restore_tools() { # Build is performed in current directory unless a different directory is # passed via "args". # -# Additionally any number of "args" maybe be given, they are appended to -# the "dotnet" command invocation. +# Any number of "args" maybe be given, they are appended to the "dotnet" +# command invocation. # # Used by "dotnet-pkg_src_compile" from the "dotnet-pkg" eclass. dotnet-pkg-base_build() { @@ -420,27 +448,19 @@ dotnet-pkg-base_build() { } # @FUNCTION: dotnet-pkg-base_test -# @USAGE: [directory] [args] ... +# @USAGE: [args] ... # @DESCRIPTION: # Test the package using "dotnet test" in a specified directory. +# Test is performed in current directory unless a different directory is +# passed via "args". # -# Optional "directory" argument defaults to the current directory path. -# -# Additionally any number of "args" maybe be given, they are appended to -# the "dotnet" command invocation. +# Any number of "args" maybe be given, they are appended to the "dotnet" +# command invocation. # # Used by "dotnet-pkg_src_test" from the "dotnet-pkg" eclass. dotnet-pkg-base_test() { debug-print-function "${FUNCNAME[0]}" "${@}" - local directory - if [[ -n "${1}" ]] ; then - directory="${1}" - shift - else - directory="$(pwd)" - fi - local -a test_args=( --configuration "${DOTNET_PKG_CONFIGURATION}" --no-restore @@ -448,7 +468,7 @@ dotnet-pkg-base_test() { "${@}" ) - edotnet test "${test_args[@]}" "${directory}" + edotnet test "${test_args[@]}" } # @FUNCTION: dotnet-pkg-base_install @@ -482,7 +502,7 @@ dotnet-pkg-base_launcherinto() { _DOTNET_PKG_LAUNCHERDEST="${1}" } -# @FUNCTION: dotnet-pkg-base_append_launchervar +# @FUNCTION: dotnet-pkg-base_append-launchervar # @USAGE: # @DESCRIPTION: # Appends a given variable setting to the "_DOTNET_PKG_LAUNCHERVARS". @@ -498,7 +518,7 @@ dotnet-pkg-base_launcherinto() { # @CODE # # For more info see the "_DOTNET_PKG_LAUNCHERVARS" variable. -dotnet-pkg-base_append_launchervar() { +dotnet-pkg-base_append-launchervar() { debug-print-function "${FUNCNAME[0]}" "${@}" [[ -z ${1} ]] && die "${FUNCNAME[0]}: no variable setting specified" @@ -506,6 +526,14 @@ dotnet-pkg-base_append_launchervar() { _DOTNET_PKG_LAUNCHERVARS+=( "${1}" ) } +# @FUNCTION: dotnet-pkg-base_append_launchervar +# @USAGE: +# @DESCRIPTION: +# DEPRECATED, use "dotnet-pkg-base_append-launchervar" instead. +dotnet-pkg-base_append_launchervar() { + dotnet-pkg-base_append-launchervar "${@}" +} + # @FUNCTION: dotnet-pkg-base_dolauncher # @USAGE: [filename] # @DESCRIPTION: @@ -573,7 +601,7 @@ dotnet-pkg-base_dolauncher() { doexe "${executable_target}" } -# @FUNCTION: dotnet-pkg-base_dolauncher_portable +# @FUNCTION: dotnet-pkg-base_dolauncher-portable # @USAGE: # @DESCRIPTION: # Make a wrapper script to launch a .NET DLL file built from a .NET package. @@ -584,12 +612,12 @@ dotnet-pkg-base_dolauncher() { # # Example: # @CODE -# dotnet-pkg-base_dolauncher_portable \ +# dotnet-pkg-base_dolauncher-portable \ # /usr/share/${P}/GentooDotnetInfo.dll gentoo-dotnet-info # @CODE # # The path is prepended by "EPREFIX". -dotnet-pkg-base_dolauncher_portable() { +dotnet-pkg-base_dolauncher-portable() { debug-print-function "${FUNCNAME[0]}" "${@}" local dll_path="${1}" @@ -615,4 +643,12 @@ dotnet-pkg-base_dolauncher_portable() { doexe "${executable_target}" } +# @FUNCTION: dotnet-pkg-base_dolauncher_portable +# @USAGE: +# @DESCRIPTION: +# DEPRECATED, use "dotnet-pkg-base_dolauncher-portable" instead. +dotnet-pkg-base_dolauncher_portable() { + dotnet-pkg-base_dolauncher-portable "${@}" +} + fi diff --git a/eclass/dotnet-pkg.eclass b/eclass/dotnet-pkg.eclass index 9d78f463be77..59a8ae799f86 100644 --- a/eclass/dotnet-pkg.eclass +++ b/eclass/dotnet-pkg.eclass @@ -1,4 +1,4 @@ -# Copyright 1999-2023 Gentoo Authors +# Copyright 1999-2024 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: dotnet-pkg.eclass @@ -48,6 +48,24 @@ inherit dotnet-pkg-base RDEPEND+=" ${DOTNET_PKG_RDEPS} " BDEPEND+=" ${DOTNET_PKG_BDEPS} " +# @ECLASS_VARIABLE: DOTNET_PKG_BAD_PROJECTS +# @DESCRIPTION: +# List of projects to remove from all found solution (".sln") files. +# The projects are removed in the "dotnet-pkg_src_prepare" function. +# +# This variable should be set after inheriting "dotnet-pkg.eclass". +# +# Default value is an empty array. +# +# Example: +# @CODE +# DOTNET_PKG_BAD_PROJECTS=( "${S}/BrokenTests" ) +# DOTNET_PKG_PROJECTS=( "${S}/DotnetProject" ) +# @CODE +# +# For more info see: "dotnet-pkg_remove-bad" function. +DOTNET_PKG_BAD_PROJECTS=() + # @ECLASS_VARIABLE: DOTNET_PKG_PROJECTS # @DEFAULT_UNSET # @DESCRIPTION: @@ -138,6 +156,29 @@ DOTNET_PKG_BUILD_EXTRA_ARGS=() # For more info see the "DOTNET_PROJECT" variable and "dotnet-pkg_src_test". DOTNET_PKG_TEST_EXTRA_ARGS=() +# @FUNCTION: dotnet-pkg_force-compat +# @DESCRIPTION: +# This function appends special options to all "DOTNET_PKG_*_EXTRA_ARGS" +# variables in an attempt to force compatibility to the picked +# "DOTNET_PKG_COMPAT" .NET SDK version. +# +# Call this function post-inherit. +dotnet-pkg_force-compat() { + if [[ -z ${DOTNET_PKG_COMPAT} ]] ; then + die "DOTNET_PKG_COMPAT is not set" + fi + + local -a force_extra_args=( + -p:RollForward=Major + -p:TargetFramework="net${DOTNET_PKG_COMPAT}" + -p:TargetFrameworks="net${DOTNET_PKG_COMPAT}" + ) + + DOTNET_PKG_RESTORE_EXTRA_ARGS+=( "${force_extra_args[@]}" ) + DOTNET_PKG_BUILD_EXTRA_ARGS+=( "${force_extra_args[@]}" ) + DOTNET_PKG_TEST_EXTRA_ARGS+=( "${force_extra_args[@]}" ) +} + # @FUNCTION: dotnet-pkg_pkg_setup # @DESCRIPTION: # Default "pkg_setup" for the "dotnet-pkg" eclass. @@ -161,14 +202,38 @@ dotnet-pkg_src_unpack() { nuget_unpack-non-nuget-archives } +# @FUNCTION: dotnet-pkg_remove-bad +# @USAGE: +# @DESCRIPTION: +# Remove all projects specified by "DOTNET_PKG_BAD_PROJECTS" from a given +# solution file. +# +# Used by "dotnet-pkg_src_prepare". +dotnet-pkg_remove-bad() { + debug-print-function "${FUNCNAME[0]}" "${@}" + + [[ -z ${1} ]] && die "${FUNCNAME[0]}: no solution file specified" + + local bad_project + for bad_project in "${DOTNET_PKG_BAD_PROJECTS[@]}" ; do + nonfatal dotnet-pkg-base_sln-remove "${1}" "${bad_project}" + done +} + # @FUNCTION: dotnet-pkg_src_prepare # @DESCRIPTION: # Default "src_prepare" for the "dotnet-pkg" eclass. # Prepare the package sources. # -# Run "dotnet-pkg-base_remove-global-json". +# Run "dotnet-pkg-base_remove-global-json", "dotnet-pkg-base_remove-bad" +# for each found solution file and prepare for using Nuget. dotnet-pkg_src_prepare() { dotnet-pkg-base_remove-global-json + dotnet-pkg-base_foreach-solution "$(pwd)" dotnet-pkg_remove-bad + + find "$(pwd)" -maxdepth 1 -iname "nuget.config" -delete || + die "${FUNCNAME[0]}: failed to remove unwanted \"NuGet.config\" config files" + nuget_writeconfig "$(pwd)/" default } diff --git a/eclass/llvm-r1.eclass b/eclass/llvm-r1.eclass new file mode 100644 index 000000000000..658946a1ecbd --- /dev/null +++ b/eclass/llvm-r1.eclass @@ -0,0 +1,250 @@ +# Copyright 2024 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: llvm-r1.eclass +# @MAINTAINER: +# Michał Górny +# @AUTHOR: +# Michał Górny +# @SUPPORTED_EAPIS: 8 +# @PROVIDES: llvm-utils +# @BLURB: Provide LLVM_SLOT to build against slotted LLVM +# @DESCRIPTION: +# An eclass to reliably depend on a set of LLVM-related packages +# in a matching slot. To use the eclass: +# +# 1. Set LLVM_COMPAT to the list of supported LLVM slots. +# 2. Use llvm_gen_dep and/or LLVM_USEDEP to add appropriate +# dependencies. +# 3. Use llvm-r1_pkg_setup, get_llvm_prefix or LLVM_SLOT. +# +# The eclass sets IUSE and REQUIRED_USE. The flag corresponding +# to the newest supported stable LLVM slot (or the newest testing, +# if no stable slots are supported) is enabled by default. +# +# Example: +# @CODE +# LLVM_COMPAT=( {16..18} ) +# +# inherit llvm-r1 +# +# DEPEND=" +# dev-libs/libfoo[${LLVM_USEDEP}] +# $(llvm_gen_dep ' +# sys-devel/clang:${LLVM_SLOT} +# sys-devel/llvm:${LLVM_SLOT} +# ') +# " +# @CODE + +case ${EAPI} in + 8) ;; + *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; +esac + +if [[ ! ${_LLVM_R1_ECLASS} ]]; then +_LLVM_R1_ECLASS=1 + +inherit llvm-utils + +# == internal control knobs == + +# @ECLASS_VARIABLE: _LLVM_OLDEST_SLOT +# @INTERNAL +# @DESCRIPTION: +# Oldest supported LLVM slot. This is used to automatically filter out +# unsupported LLVM_COMPAT values. +_LLVM_OLDEST_SLOT=15 + +# @ECLASS_VARIABLE: _LLVM_NEWEST_STABLE +# @INTERNAL +# @DESCRIPTION: +# The newest stable LLVM version. Versions newer than that won't +# be automatically enabled via USE defaults. +_LLVM_NEWEST_STABLE=17 + +# == control variables == + +# @ECLASS_VARIABLE: LLVM_COMPAT +# @PRE_INHERIT +# @REQUIRED +# @DESCRIPTION: +# A list of LLVM slots supported by the package, oldest to newest. +# +# Example: +# @CODE +# LLVM_COMPAT=( {15..17} ) +# @CODE + +# @ECLASS_VARIABLE: LLVM_OPTIONAL +# @PRE_INHERIT +# @DEFAULT_UNSET +# @DESCRIPTION: +# If set to a non-empty value, disables setting REQUIRED_USE +# and exporting pkg_setup. You have to add LLVM_REQUIRED_USE and call +# pkg_setup manually, with appropriate USE conditions. + +# == global metadata == + +# @ECLASS_VARIABLE: LLVM_REQUIRED_USE +# @OUTPUT_VARIABLE +# @DESCRIPTION: +# An eclass-generated REQUIRED_USE string that enforces selecting +# exactly one slot. It LLVM_OPTIONAL is set, it needs to be copied +# into REQUIRED_USE, under appropriate USE conditions. Otherwise, +# it is added automatically. + +# @ECLASS_VARIABLE: LLVM_USEDEP +# @OUTPUT_VARIABLE +# @DESCRIPTION: +# An eclass-generated USE dependency string that can be applied to other +# packages using the same eclass, to enforce a LLVM slot match. + +_llvm_set_globals() { + debug-print-function ${FUNCNAME} "${@}" + + if [[ ${LLVM_COMPAT@a} != *a* ]]; then + die "LLVM_COMPAT must be set to an array before inheriting ${ECLASS}" + fi + + local stable=() unstable=() + local x + for x in "${LLVM_COMPAT[@]}"; do + if [[ ${x} -gt ${_LLVM_NEWEST_STABLE} ]]; then + unstable+=( "${x}" ) + elif [[ ${x} -ge ${_LLVM_OLDEST_SLOT} ]]; then + stable+=( "${x}" ) + fi + done + + _LLVM_SLOTS=( "${stable[@]}" "${unstable[@]}" ) + if [[ ! ${_LLVM_SLOTS[@]} ]]; then + die "LLVM_COMPAT does not contain any valid versions (all older than ${_LLVM_OLDEST_SLOT}?)" + fi + + if [[ ${stable[@]} ]]; then + IUSE="+llvm_slot_${stable[-1]}" + unset 'stable[-1]' + else + IUSE="+llvm_slot_${unstable[-1]}" + unset 'unstable[-1]' + fi + local nondefault=( "${stable[@]}" "${unstable[@]}" ) + IUSE+=" ${nondefault[*]/#/llvm_slot_}" + + local flags=( "${_LLVM_SLOTS[@]/#/llvm_slot_}" ) + LLVM_REQUIRED_USE="^^ ( ${flags[*]} )" + local usedep_flags=${flags[*]/%/(-)?} + LLVM_USEDEP=${usedep_flags// /,} + readonly LLVM_REQUIRED_USE LLVM_USEDEP + + if [[ ! ${LLVM_OPTIONAL} ]]; then + REQUIRED_USE=${LLVM_REQUIRED_USE} + fi +} +_llvm_set_globals +unset -f _llvm_set_globals + +# == metadata helpers == + +# @FUNCTION: llvm_gen_dep +# @USAGE: +# @DESCRIPTION: +# Output a dependency block, repeating "" conditionally +# to all llvm_slot_* USE flags. Any occurences of '${LLVM_SLOT}' +# within the block will be substituted for the respective slot. +# +# Example: +# @CODE +# DEPEND=" +# $(llvm_gen_dep ' +# sys-devel/clang:${LLVM_SLOT} +# sys-devel/llvm:${LLVM_SLOT} +# ') +# " +# @CODE +llvm_gen_dep() { + debug-print-function ${FUNCNAME} "${@}" + + [[ ${#} -ne 1 ]] && die "Usage: ${FUNCNAME} " + + local dep=${1} + + local slot + for slot in "${_LLVM_SLOTS[@]}"; do + echo "llvm_slot_${slot}? ( ${dep//\$\{LLVM_SLOT\}/${slot}} )" + done +} + +# == ebuild helpers == + +# @FUNCTION: get_llvm_prefix +# @USAGE: [-b|-d] +# @DESCRIPTION: +# Output the path to the selected LLVM slot. +# +# With no option or "-d", the path is prefixed by ESYSROOT. LLVM +# dependencies should be in DEPEND then. +# +# With "-b" option, the path is prefixed by BROOT. LLVM dependencies +# should be in BDEPEND then. +get_llvm_prefix() { + debug-print-function ${FUNCNAME} "${@}" + + [[ ${#} -gt 1 ]] && die "Usage: ${FUNCNAME} [-b|-d]" + + local prefix + case ${1--d} in + -d) + prefix=${ESYSROOT} + ;; + -b) + prefix=${BROOT} + ;; + *) + die "${FUNCNAME}: invalid option: ${1}" + ;; + esac + + echo "${prefix}/usr/lib/llvm/${LLVM_SLOT}" +} + +# @FUNCTION: llvm-r1_pkg_setup +# @DESCRIPTION: +# Prepend the appropriate executable directory for the selected LLVM +# slot to PATH. +# +# The PATH manipulation is only done for source builds. The function +# is a no-op when installing a binary package. +# +# If any other behavior is desired, the contents of the function +# should be inlined into the ebuild and modified as necessary. +# +# Note that this function is not exported if LLVM_OPTIONAL is set. +# In that case, it needs to be called manually. +llvm-r1_pkg_setup() { + debug-print-function ${FUNCNAME} "${@}" + + if [[ ${MERGE_TYPE} != binary ]]; then + [[ -z ${LLVM_SLOT} ]] && die "LLVM_SLOT unset (broken USE_EXPAND?)" + + llvm_fix_clang_version CC CPP CXX + # keep in sync with profiles/features/llvm/make.defaults! + llvm_fix_tool_path ADDR2LINE AR AS LD NM OBJCOPY OBJDUMP RANLIB + llvm_fix_tool_path READELF STRINGS STRIP + + # Set LLVM_CONFIG to help Meson (bug #907965) but only do it + # for empty ESYSROOT (as a proxy for "are we cross-compiling?"). + if [[ -z ${ESYSROOT} ]] ; then + llvm_fix_tool_path LLVM_CONFIG + fi + + llvm_prepend_path "${LLVM_SLOT}" + fi +} + +fi + +if [[ ! ${LLVM_OPTIONAL} ]]; then + EXPORT_FUNCTIONS pkg_setup +fi diff --git a/eclass/llvm-utils.eclass b/eclass/llvm-utils.eclass new file mode 100644 index 000000000000..532e609679b8 --- /dev/null +++ b/eclass/llvm-utils.eclass @@ -0,0 +1,153 @@ +# Copyright 2024 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: llvm-utils.eclass +# @MAINTAINER: +# Michał Górny +# @AUTHOR: +# Michał Górny +# @SUPPORTED_EAPIS: 7 8 +# @BLURB: Common utility functions for building against installed LLVM +# @DESCRIPTION: +# The utility eclass providing shared functions reused between +# llvm.eclass and llvm-r1.eclass. It may also be used directly +# in ebuilds. + +case ${EAPI} in + 7|8) ;; + *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; +esac + +if [[ ! ${_LLVM_UTILS_ECLASS} ]]; then +_LLVM_UTILS_ECLASS=1 + +# @FUNCTION: llvm_tuple_to_target +# @USAGE: [] +# @DESCRIPTION: +# Translate a tuple into a target suitable for LLVM_TARGETS. +# Defaults to ${CHOST} if not specified. +llvm_tuple_to_target() { + debug-print-function ${FUNCNAME} "${@}" + + [[ ${#} -gt 1 ]] && die "Usage: ${FUNCNAME} []" + + case ${1:-${CHOST}} in + aarch64*) echo "AArch64";; + amdgcn*) echo "AMDGPU";; + arc*) echo "ARC";; + arm*) echo "ARM";; + avr*) echo "AVR";; + bpf*) echo "BPF";; + csky*) echo "CSKY";; + loong*) echo "LoongArch";; + m68k*) echo "M68k";; + mips*) echo "Mips";; + msp430*) echo "MSP430";; + nvptx*) echo "NVPTX";; + powerpc*) echo "PowerPC";; + riscv*) echo "RISCV";; + sparc*) echo "Sparc";; + s390*) echo "SystemZ";; + x86_64*|i?86*) echo "X86";; + xtensa*) echo "Xtensa";; + *) die "Unknown LLVM target for tuple ${1:-${CHOST}}" + esac +} + +# @FUNCTION: llvm_fix_clang_version +# @USAGE: ... +# @DESCRIPTION: +# Fix the clang compiler name in specified variables to include +# the major version, to prevent PATH alterations from forcing an older +# clang version being used. +llvm_fix_clang_version() { + debug-print-function ${FUNCNAME} "${@}" + + local shopt_save=$(shopt -p -o noglob) + set -f + local var + for var; do + local split=( ${!var} ) + case ${split[0]} in + *clang|*clang++|*clang-cpp) + local version=() + read -r -a version < <("${split[0]}" --version) + local major=${version[-1]%%.*} + if [[ -n ${major//[0-9]} ]]; then + die "${var}=${!var} produced invalid --version: ${version[*]}" + fi + + split[0]+=-${major} + if ! type -P "${split[0]}" &>/dev/null; then + die "${split[0]} does not seem to exist" + fi + declare -g "${var}=${split[*]}" + ;; + esac + done + ${shopt_save} +} + +# @FUNCTION: llvm_fix_tool_path +# @USAGE: ... +# @DESCRIPTION: +# Fix the LLVM tools referenced in the specified variables to their +# current location, to prevent PATH alterations from forcing older +# versions being used. +llvm_fix_tool_path() { + debug-print-function ${FUNCNAME} "${@}" + + local shopt_save=$(shopt -p -o noglob) + set -f + local var + for var; do + local split=( ${!var} ) + local path=$(type -P ${split[0]} 2>/dev/null) + # if it resides in one of the LLVM prefixes, it's an LLVM tool! + if [[ ${path} == "${BROOT}/usr/lib/llvm"* ]]; then + split[0]=${path} + declare -g "${var}=${split[*]}" + fi + done + ${shopt_save} +} + +# @FUNCTION: llvm_prepend_path +# @USAGE: +# @DESCRIPTION: +# Prepend the path to the specified LLVM slot to PATH variable, +# and reexport it. +llvm_prepend_path() { + debug-print-function ${FUNCNAME} "${@}" + + [[ ${#} -ne 1 ]] && die "Usage: ${FUNCNAME} " + local slot=${1} + + local llvm_path=${ESYSROOT}/usr/lib/llvm/${slot}/bin + local IFS=: + local split_path=( ${PATH} ) + local new_path=() + local x added= + + for x in "${split_path[@]}"; do + if [[ ${x} == */usr/lib/llvm/*/bin ]]; then + # prepend new path in front of the first LLVM version found + if [[ ! ${added} ]]; then + new_path+=( "${llvm_path}" ) + added=1 + fi + # remove duplicate copies of the same path + if [[ ${x} == ${llvm_path} ]]; then + # deduplicate + continue + fi + fi + new_path+=( "${x}" ) + done + # ...or to the end of PATH + [[ ${added} ]] || new_path+=( "${llvm_path}" ) + + export PATH=${new_path[*]} +} + +fi diff --git a/eclass/llvm.eclass b/eclass/llvm.eclass index 91cc68d966fe..e297fe992c9f 100644 --- a/eclass/llvm.eclass +++ b/eclass/llvm.eclass @@ -7,6 +7,7 @@ # @AUTHOR: # Michał Górny # @SUPPORTED_EAPIS: 7 8 +# @PROVIDES: llvm-utils # @BLURB: Utility functions to build against slotted LLVM # @DESCRIPTION: # The llvm.eclass provides utility functions that can be used to build @@ -64,6 +65,8 @@ esac if [[ ! ${_LLVM_ECLASS} ]]; then _LLVM_ECLASS=1 +inherit llvm-utils + # make sure that the versions installing straight into /usr/bin # are uninstalled DEPEND="!!sys-devel/llvm:0" @@ -174,95 +177,6 @@ get_llvm_prefix() { echo "${prefix}/usr/lib/llvm/$(get_llvm_slot "${@}")" } -# @FUNCTION: llvm_tuple_to_target -# @USAGE: [] -# @DESCRIPTION: -# Translate a tuple into a target suitable for LLVM_TARGETS. -# Defaults to ${CHOST} if not specified. -llvm_tuple_to_target() { - debug-print-function ${FUNCNAME} "${@}" - - case ${1:-${CHOST}} in - aarch64*) echo "AArch64";; - amdgcn*) echo "AMDGPU";; - arc*) echo "ARC";; - arm*) echo "ARM";; - avr*) echo "AVR";; - bpf*) echo "BPF";; - csky*) echo "CSKY";; - loong*) echo "LoongArch";; - m68k*) echo "M68k";; - mips*) echo "Mips";; - msp430*) echo "MSP430";; - nvptx*) echo "NVPTX";; - powerpc*) echo "PowerPC";; - riscv*) echo "RISCV";; - sparc*) echo "Sparc";; - s390*) echo "SystemZ";; - x86_64*|i?86*) echo "X86";; - xtensa*) echo "Xtensa";; - *) die "Unknown LLVM target for tuple ${1:-${CHOST}}" - esac -} - -# @FUNCTION: llvm_fix_clang_version -# @USAGE: ... -# @DESCRIPTION: -# Fix the clang compiler name in specified variables to include -# the major version, to prevent PATH alterations from forcing an older -# clang version being used. -llvm_fix_clang_version() { - debug-print-function ${FUNCNAME} "${@}" - - local shopt_save=$(shopt -p -o noglob) - set -f - local var - for var; do - local split=( ${!var} ) - case ${split[0]} in - *clang|*clang++|*clang-cpp) - local version=() - read -r -a version < <("${split[0]}" --version) - local major=${version[-1]%%.*} - if [[ -n ${major//[0-9]} ]]; then - die "${var}=${!var} produced invalid --version: ${version[*]}" - fi - - split[0]+=-${major} - if ! type -P "${split[0]}" &>/dev/null; then - die "${split[0]} does not seem to exist" - fi - declare -g "${var}=${split[*]}" - ;; - esac - done - ${shopt_save} -} - -# @FUNCTION: llvm_fix_tool_path -# @USAGE: ... -# @DESCRIPTION: -# Fix the LLVM tools referenced in the specified variables to their -# current location, to prevent PATH alterations from forcing older -# versions being used. -llvm_fix_tool_path() { - debug-print-function ${FUNCNAME} "${@}" - - local shopt_save=$(shopt -p -o noglob) - set -f - local var - for var; do - local split=( ${!var} ) - local path=$(type -P ${split[0]} 2>/dev/null) - # if it resides in one of the LLVM prefixes, it's an LLVM tool! - if [[ ${path} == "${BROOT}/usr/lib/llvm"* ]]; then - split[0]=${path} - declare -g "${var}=${split[*]}" - fi - done - ${shopt_save} -} - # @FUNCTION: llvm_pkg_setup # @DESCRIPTION: # Prepend the appropriate executable directory for the newest @@ -298,30 +212,7 @@ llvm_pkg_setup() { llvm_fix_tool_path LLVM_CONFIG fi - local prefix=${ESYSROOT} - local llvm_path=${prefix}/usr/lib/llvm/${LLVM_SLOT}/bin - local IFS=: - local split_path=( ${PATH} ) - local new_path=() - local x added= - - # prepend new path before first LLVM version found - for x in "${split_path[@]}"; do - if [[ ${x} == */usr/lib/llvm/*/bin ]]; then - if [[ ${x} != ${llvm_path} ]]; then - new_path+=( "${llvm_path}" ) - elif [[ ${added} && ${x} == ${llvm_path} ]]; then - # deduplicate - continue - fi - added=1 - fi - new_path+=( "${x}" ) - done - # ...or to the end of PATH - [[ ${added} ]] || new_path+=( "${llvm_path}" ) - - export PATH=${new_path[*]} + llvm_prepend_path "${LLVM_SLOT}" fi } diff --git a/eclass/nuget.eclass b/eclass/nuget.eclass index 669e21300ef2..ac8629848eca 100644 --- a/eclass/nuget.eclass +++ b/eclass/nuget.eclass @@ -1,4 +1,4 @@ -# Copyright 1999-2023 Gentoo Authors +# Copyright 1999-2024 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: nuget.eclass @@ -226,6 +226,51 @@ nuget_unpack-non-nuget-archives() { done } +# @FUNCTION: nuget_writeconfig +# @USAGE: +# @DESCRIPTION: +# Create a "NuGet.config" config file that can be used to overwrite any other +# Nuget configuration file in order to prevent Nuget executable from accessing +# the network or undesired NuPkg package sources. +# +# If given path ends with a slash, a file name "NuGet.config" is assumed, +# otherwise contents are written to specified file path exactly. +# +# Created configuration file clears all other NuPkg sources and inserts +# "NUGET_PACKAGES" as the only one source. +# +# This function is used inside "dotnet-pkg_src_prepare" +# from the "dotnet-pkg" eclass. +# +# This function is used inside "dotnet-pkg_src_prepare" +# from the "dotnet-pkg" eclass. +nuget_writeconfig() { + debug-print-function "${FUNCNAME[0]}" "${@}" + + case "${1}" in + "" ) die "${FUNCNAME[0]}: no directory/file path specified" ;; + */ ) mkdir -p "${1}" || die ;; + esac + + local nuget_config_path + + if [[ -d "${1}" ]] ; then + nuget_config_path="${1}/NuGet.config" + else + nuget_config_path="${1}" + fi + + cat <<-EOF > "${nuget_config_path}" || die + + + + + + + + EOF +} + # @FUNCTION: nuget_donuget # @USAGE: ... # @DESCRIPTION: diff --git a/eclass/tests/llvm-r1.sh b/eclass/tests/llvm-r1.sh new file mode 100755 index 000000000000..9958f5bba420 --- /dev/null +++ b/eclass/tests/llvm-r1.sh @@ -0,0 +1,151 @@ +#!/bin/bash +# Copyright 2024 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +source tests-common.sh || exit + +EAPI=8 + +test_globals() { + local compat=${1} + local expected_iuse=${2} + local expected_required_use=${3} + local expected_usedep=${4} + local x + + tbegin "LLVM_COMPAT=( ${compat} )" + + ( + local fail=0 + local LLVM_COMPAT=( ${compat} ) + + inherit llvm-r1 + + if [[ ${IUSE%% } != ${expected_iuse} ]]; then + eerror " IUSE: ${IUSE%% }" + eerror "does not match: ${expected_iuse}" + fail=1 + fi + + if [[ ${REQUIRED_USE} != ${expected_required_use} ]]; then + eerror " REQUIRED_USE: ${REQUIRED_USE}" + eerror "does not match: ${expected_required_use}" + fail=1 + fi + + if [[ ${LLVM_USEDEP} != ${expected_usedep} ]]; then + eerror " LLVM_USEDEP: ${LLVM_USEDEP}" + eerror "does not match: ${expected_usedep}" + fail=1 + fi + + exit "${fail}" + ) + + tend "${?}" +} + +test_gen_dep() { + local arg=${1} + local expected + read -r -d '' expected + + tbegin "llvm_gen_dep ${arg}" + local value=$(llvm_gen_dep "${arg}") + + if [[ ${value} != ${expected} ]]; then + eerror "python_get_usedep ${arg}" + eerror "gave:" + eerror " ${value}" + eerror "expected:" + eerror " ${expected}" + fi + tend ${?} +} + +test_fix_clang_version() { + local var=${1} + local tool=${2} + local version=${3} + local expected=${4} + + eval "${tool}() { + cat <<-EOF + clang version ${version} + Target: x86_64-pc-linux-gnu + Thread model: posix + InstalledDir: /usr/lib/llvm/17/bin + Configuration file: /etc/clang/x86_64-pc-linux-gnu-clang.cfg + EOF + }" + + declare -g ${var}=${tool} + tbegin "llvm_fix_clang_version ${var}=${tool} for ${version}" + llvm_fix_clang_version "${var}" + if [[ ${!var} != ${expected} ]]; then + eerror "llvm_fix_clang_version ${var}" + eerror " gave: ${!var}" + eerror "expected: ${expected}" + fi + tend ${?} +} + +test_fix_tool_path() { + local var=${1} + local tool=${2} + local expected_subst=${3} + local expected=${tool} + + tbegin "llvm_fix_tool_path ${1}=${2} (from llvm? ${expected_subst})" + + local matches=( "${BROOT}"/usr/lib/llvm/*/bin/"${tool}" ) + if [[ ${expected_subst} == 1 ]]; then + if [[ ! -x ${matches[0]} ]]; then + ewarn "- skipping, test requires ${tool}" + return + fi + + expected=${matches[0]} + local -x PATH=${matches[0]%/*} + else + local -x PATH= + fi + + declare -g ${var}=${tool} + llvm_fix_tool_path "${var}" + if [[ ${!var} != ${expected} ]]; then + eerror "llvm_fix_tool_path ${var}" + eerror " gave: ${!var}" + eerror "expected: ${expected}" + fi + tend ${?} +} + +test_globals '14 15 16 17 18' \ + "+llvm_slot_17 llvm_slot_15 llvm_slot_16 llvm_slot_18" \ + "^^ ( llvm_slot_15 llvm_slot_16 llvm_slot_17 llvm_slot_18 )" \ + "llvm_slot_15(-)?,llvm_slot_16(-)?,llvm_slot_17(-)?,llvm_slot_18(-)?" +test_globals '14 15 16' \ + "+llvm_slot_16 llvm_slot_15" \ + "^^ ( llvm_slot_15 llvm_slot_16 )" \ + "llvm_slot_15(-)?,llvm_slot_16(-)?" +test_globals '15 18' \ + "+llvm_slot_15 llvm_slot_18" \ + "^^ ( llvm_slot_15 llvm_slot_18 )" \ + "llvm_slot_15(-)?,llvm_slot_18(-)?" +test_globals '18' \ + "+llvm_slot_18" \ + "^^ ( llvm_slot_18 )" \ + "llvm_slot_18(-)?" + +LLVM_COMPAT=( {14..18} ) +inherit llvm-r1 + +test_gen_dep 'sys-devel/llvm:${LLVM_SLOT} sys-devel/clang:${LLVM_SLOT}' <<-EOF + llvm_slot_15? ( sys-devel/llvm:15 sys-devel/clang:15 ) + llvm_slot_16? ( sys-devel/llvm:16 sys-devel/clang:16 ) + llvm_slot_17? ( sys-devel/llvm:17 sys-devel/clang:17 ) + llvm_slot_18? ( sys-devel/llvm:18 sys-devel/clang:18 ) +EOF + +texit diff --git a/eclass/tests/llvm-utils.sh b/eclass/tests/llvm-utils.sh new file mode 100755 index 000000000000..6fe3da3eda13 --- /dev/null +++ b/eclass/tests/llvm-utils.sh @@ -0,0 +1,118 @@ +#!/bin/bash +# Copyright 2024 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +source tests-common.sh || exit + +EAPI=8 + +inherit llvm-utils + +test_fix_clang_version() { + local var=${1} + local tool=${2} + local version=${3} + local expected=${4} + + eval "${tool}() { + cat <<-EOF + clang version ${version} + Target: x86_64-pc-linux-gnu + Thread model: posix + InstalledDir: /usr/lib/llvm/17/bin + Configuration file: /etc/clang/x86_64-pc-linux-gnu-clang.cfg + EOF + }" + + declare -g ${var}=${tool} + tbegin "llvm_fix_clang_version ${var}=${tool} for ${version}" + llvm_fix_clang_version "${var}" + if [[ ${!var} != ${expected} ]]; then + eerror "llvm_fix_clang_version ${var}" + eerror " gave: ${!var}" + eerror "expected: ${expected}" + fi + tend ${?} +} + +test_fix_tool_path() { + local var=${1} + local tool=${2} + local expected_subst=${3} + local expected=${tool} + + tbegin "llvm_fix_tool_path ${1}=${2} (from llvm? ${expected_subst})" + + local matches=( "${BROOT}"/usr/lib/llvm/*/bin/"${tool}" ) + if [[ ${expected_subst} == 1 ]]; then + if [[ ! -x ${matches[0]} ]]; then + ewarn "- skipping, test requires ${tool}" + return + fi + + expected=${matches[0]} + local -x PATH=${matches[0]%/*} + else + local -x PATH= + fi + + declare -g ${var}=${tool} + llvm_fix_tool_path "${var}" + if [[ ${!var} != ${expected} ]]; then + eerror "llvm_fix_tool_path ${var}" + eerror " gave: ${!var}" + eerror "expected: ${expected}" + fi + tend ${?} +} + +test_prepend_path() { + local slot=${1} + local -x PATH=${2} + local expected=${3} + + tbegin "llvm_prepend_path ${slot} to PATH=${PATH}" + llvm_prepend_path "${slot}" + if [[ ${PATH} != ${expected} ]]; then + eerror "llvm_prepend_path ${var}" + eerror " gave: ${PATH}" + eerror "expected: ${expected}" + fi + tend ${?} +} + +test_fix_clang_version CC clang 19.0.0git78b4e7c5 clang-19 +test_fix_clang_version CC clang 17.0.6 clang-17 +test_fix_clang_version CXX clang++ 17.0.6 clang++-17 +test_fix_clang_version CC x86_64-pc-linux-gnu-clang 17.0.6 \ + x86_64-pc-linux-gnu-clang-17 +test_fix_clang_version CC clang-17 n/a clang-17 +test_fix_clang_version CC gcc n/a gcc + +test_fix_tool_path AR llvm-ar 1 +test_fix_tool_path RANLIB llvm-ranlib 1 +test_fix_tool_path AR ar 1 +test_fix_tool_path AR ar 0 + +ESYSROOT= +test_prepend_path 17 /usr/bin /usr/bin:/usr/lib/llvm/17/bin +test_prepend_path 17 /usr/lib/llvm/17/bin:/usr/bin /usr/lib/llvm/17/bin:/usr/bin +test_prepend_path 17 /usr/bin:/usr/lib/llvm/17/bin /usr/bin:/usr/lib/llvm/17/bin +test_prepend_path 17 /usr/lib/llvm/17/bin:/usr/bin:/usr/lib/llvm/17/bin \ + /usr/lib/llvm/17/bin:/usr/bin +test_prepend_path 17 /usr/lib/llvm/17/bin:/usr/lib/llvm/17/bin:/usr/bin \ + /usr/lib/llvm/17/bin:/usr/bin +test_prepend_path 17 /usr/bin:/usr/lib/llvm/17/bin:/usr/lib/llvm/17/bin \ + /usr/bin:/usr/lib/llvm/17/bin +test_prepend_path 18 /usr/lib/llvm/17/bin:/usr/bin \ + /usr/lib/llvm/18/bin:/usr/lib/llvm/17/bin:/usr/bin +test_prepend_path 18 /usr/bin:/usr/lib/llvm/17/bin \ + /usr/bin:/usr/lib/llvm/18/bin:/usr/lib/llvm/17/bin +test_prepend_path 18 /usr/lib/llvm/17/bin:/usr/lib/llvm/16/bin:/usr/bin \ + /usr/lib/llvm/18/bin:/usr/lib/llvm/17/bin:/usr/lib/llvm/16/bin:/usr/bin +test_prepend_path 18 /usr/bin:/usr/lib/llvm/17/bin:/usr/lib/llvm/16/bin \ + /usr/bin:/usr/lib/llvm/18/bin:/usr/lib/llvm/17/bin:/usr/lib/llvm/16/bin +test_prepend_path 18 /usr/lib/llvm/17/bin:/usr/bin:/usr/lib/llvm/16/bin \ + /usr/lib/llvm/18/bin:/usr/lib/llvm/17/bin:/usr/bin:/usr/lib/llvm/16/bin + +texit -- cgit v1.2.3