diff options
Diffstat (limited to 'eclass')
39 files changed, 2917 insertions, 391 deletions
diff --git a/eclass/ada.eclass b/eclass/ada.eclass index 9206bfcc42ca..3d22dd5d2a61 100644 --- a/eclass/ada.eclass +++ b/eclass/ada.eclass @@ -282,7 +282,7 @@ ada_export() { debug-print "${FUNCNAME}: GNATBIND = ${GNATBIND}" ;; GNATMAKE) - export GNATMAKE=${EPREFIX}/usr/bin/gnatmake-${gcc_pv} + export GNATMAKE=${EPREFIX}/usr/bin/${CHOST}-gnatmake-${gcc_pv} debug-print "${FUNCNAME}: GNATMAKE = ${GNATMAKE}" ;; GNATLS) diff --git a/eclass/dist-kernel-utils.eclass b/eclass/dist-kernel-utils.eclass index 210c586c8c29..3d7315e9e94e 100644 --- a/eclass/dist-kernel-utils.eclass +++ b/eclass/dist-kernel-utils.eclass @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Gentoo Authors +# Copyright 2020-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: dist-kernel-utils.eclass @@ -82,12 +82,33 @@ dist-kernel_install_kernel() { local success= # not an actual loop but allows error handling with 'break' while true; do + if [[ -n ${ROOT} ]] && in_iuse initramfs && use initramfs; then + if ! in_iuse generic-uki || ! use generic-uki; then + eerror + eerror "ROOT is set, and (re-)generation of an initramfs is requested" + eerror "via the USE=initramfs flag. However, this is currently not" + eerror "supported via the sys-kernel/installkernel mechanism." + eerror + if in_iuse generic-uki && ! use generic-uki; then + eerror "Generation and installation of a generic initramfs and/or" + eerror "Unified Kernel Image is possible via portage by enabling the" + eerror "USE=generic-uki flag. Please enable the generic-uki flag, or" + eerror "chroot into: ROOT=${ROOT}" + else + eerror "Please chroot into: ROOT=${ROOT}" + fi + break + fi + fi + nonfatal mount-boot_check_status || break + mkdir -p "${EROOT}/boot" || break ebegin "Installing the kernel via installkernel" # note: .config is taken relatively to System.map; # initrd relatively to bzImage - ARCH=$(tc-arch-kernel) installkernel "${version}" "${image}" "${map}" || break + ARCH=$(tc-arch-kernel) installkernel "${version}" "${image}" "${map}" \ + "${EROOT}/boot" || break eend ${?} || die -n "Installing the kernel failed" success=1 diff --git a/eclass/ecm.eclass b/eclass/ecm.eclass index fbe1a23cf205..e433952903e8 100644 --- a/eclass/ecm.eclass +++ b/eclass/ecm.eclass @@ -29,7 +29,7 @@ esac if [[ -z ${_ECM_ECLASS} ]]; then _ECM_ECLASS=1 -inherit cmake flag-o-matic toolchain-funcs +inherit cmake flag-o-matic if [[ ${EAPI} == 8 ]]; then # @ECLASS_VARIABLE: VIRTUALX_REQUIRED @@ -39,23 +39,18 @@ if [[ ${EAPI} == 8 ]]; then # for tests you should proceed with setting VIRTUALX_REQUIRED=test. : "${VIRTUALX_REQUIRED:=manual}" -inherit virtualx +inherit toolchain-funcs virtualx fi # @ECLASS_VARIABLE: ECM_NONGUI -# @DEFAULT_UNSET # @DESCRIPTION: # By default, for all CATEGORIES except kde-frameworks, assume we are building # a GUI application. Add dependency on kde-frameworks/breeze-icons or -# kde-frameworks/oxygen-icons and run the xdg.eclass routines for pkg_preinst, -# pkg_postinst and pkg_postrm. If set to "true", do nothing. -if [[ ${CATEGORY} = kde-frameworks ]] ; then - : "${ECM_NONGUI:=true}" -fi +# kde-frameworks/oxygen-icons. With KFMIN lower than 6.9.0, inherit xdg.eclass, +# run pkg_preinst, pkg_postinst and pkg_postrm. If set to "true", do nothing. : "${ECM_NONGUI:=false}" - -if [[ ${ECM_NONGUI} = false ]] ; then - inherit xdg +if [[ ${CATEGORY} == kde-frameworks ]]; then + ECM_NONGUI=true fi # @ECLASS_VARIABLE: ECM_KDEINSTALLDIRS @@ -104,11 +99,25 @@ fi : "${ECM_HANDBOOK_DIR:=doc}" # @ECLASS_VARIABLE: ECM_PO_DIRS +# @PRE_INHERIT # @DESCRIPTION: # Specifies directories of l10n files relative to ${S} to be processed by # KF${_KFSLOT}I18n (ki18n_install). If IUSE nls exists and is disabled then # disable build of these directories in CMakeLists.txt. -: "${ECM_PO_DIRS:="po poqm"}" +if [[ ${ECM_PO_DIRS} ]]; then + [[ ${ECM_PO_DIRS@a} == *a* ]] || + die "ECM_PO_DIRS must be an array" +else + ECM_PO_DIRS=( po poqm ) +fi + +# @ECLASS_VARIABLE: ECM_PYTHON_BINDINGS +# @DESCRIPTION: +# Default value is "false", which means do nothing. +# If set to "off", pass -DBUILD_PYTHON_BINDINGS=OFF to mycmakeargs, and also +# disable cmake finding Python3, PySide6 and Shiboken6 to make it quiet. +# No other value is implemented as python bindings are not supported in Gentoo. +: "${ECM_PYTHON_BINDINGS:=false}" # @ECLASS_VARIABLE: ECM_QTHELP # @DEFAULT_UNSET @@ -155,16 +164,21 @@ fi : "${ECM_TEST:=false}" # @ECLASS_VARIABLE: KFMIN +# @PRE_INHERIT # @DEFAULT_UNSET # @DESCRIPTION: # Minimum version of Frameworks to require. Default value for kde-frameworks -# is ${PV} and 5.106.0 baseline for everything else. +# is ${PV} and 5.116.0 baseline for everything else. # If set to >=5.240, KF6/Qt6 is assumed thus SLOT=6 dependencies added and # -DQT_MAJOR_VERSION=6 added to cmake args. if [[ ${CATEGORY} = kde-frameworks ]]; then : "${KFMIN:=$(ver_cut 1-2)}" fi -: "${KFMIN:=5.106.0}" +: "${KFMIN:=5.116.0}" + +if ver_test ${KFMIN} -lt 6.9 && [[ ${ECM_NONGUI} == false ]]; then + inherit xdg +fi # @ECLASS_VARIABLE: _KFSLOT # @INTERNAL @@ -175,15 +189,21 @@ fi # prefixed cmake args. : "${_KFSLOT:=5}" if [[ ${CATEGORY} == kde-frameworks ]]; then - if [[ ${PV} != 5.9999 ]] && $(ver_test ${KFMIN} -ge 5.240); then - _KFSLOT=6 - fi + ver_test ${KFMIN} -ge 5.240 && _KFSLOT=6 else if [[ ${KFMIN/.*} == 6 ]] || $(ver_test ${KFMIN} -ge 5.240); then _KFSLOT=6 fi fi +# @ECLASS_VARIABLE: KDE_GCC_MINIMAL +# @DEFAULT_UNSET +# @DESCRIPTION: +# Minimum version of active GCC to require. This is checked in +# ecm_pkg_pretend and ecm_pkg_setup. +[[ ${KDE_GCC_MINIMAL} ]] && ver_test ${KFMIN} -ge 6.9 && + die "KDE_GCC_MINIMAL has been banned with KFMIN >=6.9.0." + case ${ECM_NONGUI} in true) ;; false) @@ -249,6 +269,15 @@ case ${ECM_HANDBOOK} in ;; esac +case ${ECM_PYTHON_BINDINGS} in + off|false) ;; + true) ;& # TODO if you really really want + *) + eerror "Unknown value for \${ECM_PYTHON_BINDINGS}" + die "Value ${ECM_PYTHON_BINDINGS} is not supported" + ;; +esac + case ${ECM_QTHELP} in true) IUSE+=" doc" @@ -305,30 +334,6 @@ DEPEND+=" ${COMMONDEPEND}" RDEPEND+=" ${COMMONDEPEND}" unset COMMONDEPEND -# @ECLASS_VARIABLE: KDE_GCC_MINIMAL -# @DEFAULT_UNSET -# @DESCRIPTION: -# Minimum version of active GCC to require. This is checked in -# ecm_pkg_pretend and ecm_pkg_setup. - -# @FUNCTION: _ecm_check_gcc_version -# @INTERNAL -# @DESCRIPTION: -# Determine if the current GCC version is acceptable, otherwise die. -_ecm_check_gcc_version() { - if [[ ${MERGE_TYPE} != binary && -v KDE_GCC_MINIMAL ]] && tc-is-gcc; then - - local version=$(gcc-version) - - debug-print "GCC version check activated" - debug-print "Version detected: ${version}" - debug-print "Version required: ${KDE_GCC_MINIMAL}" - - ver_test ${version} -lt ${KDE_GCC_MINIMAL} && - die "Sorry, but gcc-${KDE_GCC_MINIMAL} or later is required for this package (found ${version})." - fi -} - # @FUNCTION: _ecm_strip_handbook_translations # @INTERNAL # @DESCRIPTION: @@ -339,7 +344,7 @@ _ecm_strip_handbook_translations() { fi local lang po - for po in ${ECM_PO_DIRS}; do + for po in ${ECM_PO_DIRS[*]}; do if [[ -d ${po} ]] ; then pushd ${po} > /dev/null || die for lang in *; do @@ -474,22 +479,49 @@ ecm_punt_po_install() { -i CMakeLists.txt || die } +if [[ ${EAPI} == 8 ]]; then +# @FUNCTION: _ecm_deprecated_check_gcc_version +# @INTERNAL +# @DESCRIPTION: +# Determine if the current GCC version is acceptable, otherwise die. +_ecm_deprecated_check_gcc_version() { + if ver_test ${KFMIN} -ge 6.9; then + eqawarn "QA notice: ecm_pkg_${1} has become a no-op." + eqawarn "It is no longer being exported with KFMIN >=6.9.0." + return + fi + if [[ ${MERGE_TYPE} != binary && -v KDE_GCC_MINIMAL ]] && tc-is-gcc; then + + local version=$(gcc-version) + + debug-print "GCC version check activated" + debug-print "Version detected: ${version}" + debug-print "Version required: ${KDE_GCC_MINIMAL}" + + ver_test ${version} -lt ${KDE_GCC_MINIMAL} && + die "Sorry, but gcc-${KDE_GCC_MINIMAL} or later is required for this package (found ${version})." + fi +} + # @FUNCTION: ecm_pkg_pretend # @DESCRIPTION: # Checks if the active compiler meets the minimum version requirements. -# phase function is only exported if KDE_GCC_MINIMAL is defined. +# Phase function is only exported if KFMIN is <6.9.0 and KDE_GCC_MINIMAL +# is defined. ecm_pkg_pretend() { debug-print-function ${FUNCNAME} "$@" - _ecm_check_gcc_version + _ecm_deprecated_check_gcc_version pretend } # @FUNCTION: ecm_pkg_setup # @DESCRIPTION: # Checks if the active compiler meets the minimum version requirements. +# Phase function is only exported if KFMIN is <6.9.0. ecm_pkg_setup() { debug-print-function ${FUNCNAME} "$@" - _ecm_check_gcc_version + _ecm_deprecated_check_gcc_version setup } +fi # @FUNCTION: ecm_src_prepare # @DESCRIPTION: @@ -540,7 +572,7 @@ ecm_src_prepare() { if [[ ${ECM_TEST} = forceoptional ]] ; then [[ ${_KFSLOT} = 5 ]] && ecm_punt_qt_module Test # if forceoptional, also cover non-kde categories - cmake_comment_add_subdirectory autotests test tests + cmake_comment_add_subdirectory appiumtests autotests test tests elif [[ ${ECM_TEST} = forceoptional-recursive ]] ; then [[ ${_KFSLOT} = 5 ]] && ecm_punt_qt_module Test local f pf="${T}/${P}"-tests-optional.patch @@ -557,17 +589,17 @@ ecm_src_prepare() { diff -Naur ${f}.old ${f} 1>>${pf} rm ${f}.old || die "Failed to clean up" done - eqawarn "Build system was modified by ECM_TEST=forceoptional-recursive." + eqawarn "QA notice: Build system modified by ECM_TEST=forceoptional-recursive." eqawarn "Unified diff file ready for pickup in:" eqawarn " ${pf}" eqawarn "Push it upstream to make this message go away." - elif [[ ${CATEGORY} = kde-frameworks || ${CATEGORY} = kde-plasma || ${CATEGORY} = kde-apps ]] ; then - cmake_comment_add_subdirectory autotests test tests + elif [[ -n ${_KDE_ORG_ECLASS} ]] ; then + cmake_comment_add_subdirectory appiumtests autotests test tests fi fi # in frameworks, tests = manual tests so never build them - if [[ ${CATEGORY} = kde-frameworks ]] && [[ ${PN} != extra-cmake-modules ]]; then + if [[ -n ${_FRAMEWORKS_KDE_ORG_ECLASS} ]] && [[ ${PN} != extra-cmake-modules ]]; then cmake_comment_add_subdirectory tests fi } @@ -605,6 +637,13 @@ ecm_src_configure() { cmakeargs+=( -DBUILD_DESIGNERPLUGIN=$(usex designer) ) fi + if [[ ${ECM_PYTHON_BINDINGS} == off ]]; then + cmakeargs+=( + -DBUILD_PYTHON_BINDINGS=OFF + -DCMAKE_DISABLE_FIND_PACKAGE_{Python3,PySide6,Shiboken6}=ON + ) + fi + if [[ ${ECM_QTHELP} = true ]]; then cmakeargs+=( -DBUILD_QCH=$(usex doc) ) fi @@ -731,52 +770,58 @@ ecm_src_install() { done } +if [[ ${EAPI} == 8 ]]; then +# @FUNCTION: _ecm_nongui_deprecated +# @INTERNAL +# @DESCRIPTION: +# Carryall for ecm_pkg_preinst, ecm_pkg_postinst and ecm_pkg_postrm. +_ecm_nongui_deprecated() { + if ver_test ${KFMIN} -ge 6.9; then + eqawarn "QA notice: ecm_pkg_${1} has become a no-op." + eqawarn "It is no longer being exported with KFMIN >=6.9.0." + else + case ${ECM_NONGUI} in + false) xdg_pkg_${1} ;; + *) ;; + esac + fi +} + # @FUNCTION: ecm_pkg_preinst # @DESCRIPTION: # Sets up environment variables required in ecm_pkg_postinst. +# Phase function is only exported if KFMIN is <6.9.0. ecm_pkg_preinst() { debug-print-function ${FUNCNAME} "$@" - - case ${ECM_NONGUI} in - false) xdg_pkg_preinst ;; - *) ;; - esac + _ecm_nongui_deprecated preinst } # @FUNCTION: ecm_pkg_postinst # @DESCRIPTION: # Updates the various XDG caches (icon, desktop, mime) if necessary. +# Phase function is only exported if KFMIN is <6.9.0. ecm_pkg_postinst() { debug-print-function ${FUNCNAME} "$@" - - case ${ECM_NONGUI} in - false) xdg_pkg_postinst ;; - *) ;; - esac - - if [[ -n ${_KDE_ORG_ECLASS} ]] && [[ -z ${I_KNOW_WHAT_I_AM_DOING} ]] && [[ ${KDE_BUILD_TYPE} = live ]]; then - einfo "WARNING! This is an experimental live ebuild of ${CATEGORY}/${PN}" - einfo "Use it at your own risk." - einfo "Do _NOT_ file bugs at bugs.gentoo.org because of this ebuild!" - fi + _ecm_nongui_deprecated postinst } # @FUNCTION: ecm_pkg_postrm # @DESCRIPTION: # Updates the various XDG caches (icon, desktop, mime) if necessary. +# Phase function is only exported if KFMIN is <6.9.0. ecm_pkg_postrm() { debug-print-function ${FUNCNAME} "$@" - - case ${ECM_NONGUI} in - false) xdg_pkg_postrm ;; - *) ;; - esac + _ecm_nongui_deprecated postrm } +fi fi -if [[ -v ${KDE_GCC_MINIMAL} ]]; then - EXPORT_FUNCTIONS pkg_pretend +if ver_test ${KFMIN} -lt 6.9; then + EXPORT_FUNCTIONS pkg_setup pkg_preinst pkg_postinst pkg_postrm + if [[ -v ${KDE_GCC_MINIMAL} ]]; then + EXPORT_FUNCTIONS pkg_pretend + fi fi -EXPORT_FUNCTIONS pkg_setup src_prepare src_configure src_test src_install pkg_preinst pkg_postinst pkg_postrm +EXPORT_FUNCTIONS src_prepare src_configure src_test src_install diff --git a/eclass/elisp-common.eclass b/eclass/elisp-common.eclass index ad9d3c7e60c6..117544e94b35 100644 --- a/eclass/elisp-common.eclass +++ b/eclass/elisp-common.eclass @@ -25,7 +25,7 @@ # When relying on the emacs USE flag, you need to add # # @CODE -# emacs? ( >=app-editors/emacs-25.3:* ) +# emacs? ( >=app-editors/emacs-25.3:* ) # @CODE # # to your DEPEND/RDEPEND line and use the functions provided here to @@ -39,7 +39,7 @@ # NEED_EMACS with the Emacs version, as in the following example: # # @CODE -# NEED_EMACS=26.1 +# NEED_EMACS=26.1 # @CODE # # Please note that this should be done only for packages that are known @@ -54,7 +54,7 @@ # are loadable. # # @CODE -# elisp-compile *.el +# elisp-compile *.el # @CODE # # Function elisp-make-autoload-file() can be used to generate a file @@ -75,7 +75,7 @@ # (see below) the change, as it defaults to ${PN}. # # @CODE -# elisp-install ${PN} *.el *.elc +# elisp-install ${PN} *.el *.elc # @CODE # # To let the Emacs support be activated by Emacs on startup, you need @@ -84,9 +84,9 @@ # Normally this would look like this: # # @CODE -# (add-to-list 'load-path "@SITELISP@") -# (add-to-list 'auto-mode-alist '("\\.csv\\'" . csv-mode)) -# (autoload 'csv-mode "csv-mode" "Major mode for csv files." t) +# (add-to-list 'load-path "@SITELISP@") +# (add-to-list 'auto-mode-alist '("\\.csv\\'" . csv-mode)) +# (autoload 'csv-mode "csv-mode" "Major mode for csv files." t) # @CODE # # If your Emacs support files are installed in a subdirectory of @@ -117,13 +117,13 @@ # your ebuild (e.g., right after S or RDEPEND): # # @CODE -# SITEFILE="50${PN}-gentoo.el" +# SITEFILE="50${PN}-gentoo.el" # @CODE # # Which is then installed by # # @CODE -# elisp-site-file-install "${FILESDIR}/${SITEFILE}" +# elisp-site-file-install "${FILESDIR}/${SITEFILE}" # @CODE # # in src_install(). Any characters after the "-gentoo" part and before @@ -137,7 +137,7 @@ # and install a site-init file that does just that: # # @CODE -# elisp-make-site-file "${SITEFILE}" +# elisp-make-site-file "${SITEFILE}" # @CODE # # Again, this must be called in src_install(). See the function's @@ -153,7 +153,7 @@ # version. In this case, you can add an explicit check in pkg_setup: # # @CODE -# elisp-check-emacs-version +# elisp-check-emacs-version # @CODE # # When having optional Emacs support, you should prepend "use emacs &&" @@ -165,13 +165,13 @@ # emerging and unmerging by using # # @CODE -# pkg_postinst() { -# elisp-site-regen -# } +# pkg_postinst() { +# elisp-site-regen +# } # -# pkg_postrm() { -# elisp-site-regen -# } +# pkg_postrm() { +# elisp-site-regen +# } # @CODE # # Again, with optional Emacs support, you should prepend "use emacs &&" @@ -260,7 +260,6 @@ elisp-emacs-version() { } # @FUNCTION: elisp-check-emacs-version -# @USAGE: [version] # @DESCRIPTION: # Test if the eselected Emacs version is at least the version of # GNU Emacs specified in the NEED_EMACS variable, or die otherwise. @@ -356,8 +355,8 @@ elisp-make-autoload-file() { # # Example: # @CODE -# elisp-org-export-to texinfo README.org -# mv README.texi ${PN}.texi || die +# elisp-org-export-to texinfo README.org +# mv README.texi ${PN}.texi || die # @CODE elisp-org-export-to() { @@ -512,16 +511,16 @@ elisp-test-ert() { # # Example: # @CODE -# inherit elisp-common +# inherit elisp-common # -# ... +# ... # -# elisp-enable-tests --optional ert-runner "${S}"/elisp -t "!org" +# elisp-enable-tests --optional ert-runner "${S}"/elisp -t "!org" # -# src_test() { -# emake -C tests test -# elisp-test -# } +# src_test() { +# emake -C tests test +# elisp-test +# } # @CODE elisp-enable-tests() { @@ -662,7 +661,7 @@ elisp-site-file-install() { # this will add the package's SITELISP subdirectory to Emacs' load-path: # # @CODE -# (add-to-list 'load-path "@SITELISP@") +# (add-to-list 'load-path "@SITELISP@") # @CODE # # Additional arguments are appended as lines to the destination file. diff --git a/eclass/elisp.eclass b/eclass/elisp.eclass index 1fa8aab29753..e2f629edf132 100644 --- a/eclass/elisp.eclass +++ b/eclass/elisp.eclass @@ -139,7 +139,7 @@ elisp_src_configure() { :; } elisp_src_compile() { elisp-compile *.el if [[ -n ${ELISP_TEXINFO} ]]; then - makeinfo ${ELISP_TEXINFO} || die + makeinfo --no-split ${ELISP_TEXINFO} || die fi } diff --git a/eclass/frameworks.kde.org.eclass b/eclass/frameworks.kde.org.eclass index 53811e339976..522211a23ab2 100644 --- a/eclass/frameworks.kde.org.eclass +++ b/eclass/frameworks.kde.org.eclass @@ -25,6 +25,13 @@ esac if [[ -z ${_FRAMEWORKS_KDE_ORG_ECLASS} ]]; then _FRAMEWORKS_KDE_ORG_ECLASS=1 +# @ECLASS_VARIABLE: KDE_CATV +# @DESCRIPTION: +# Holds main Frameworks release number (major.minor) for use on same-category +# dependencies. +KDE_CATV=$(ver_cut 1-2) +readonly KDE_CATV + # @ECLASS_VARIABLE: KDE_PV_UNRELEASED # @INTERNAL # @DESCRIPTION: @@ -39,15 +46,14 @@ SLOT=6 if ver_test ${PV} -lt 5.240; then SLOT=5 fi -if [[ ${PN} == extra-cmake-modules ]]; then - SLOT=0 -else - if [[ ${KDE_BUILD_TYPE} == release ]]; then - SLOT=${SLOT}/$(ver_cut 1-2) - else - SLOT=${SLOT}/9999 - fi -fi +case ${PN} in + extra-cmake-modules|kapidox) + SLOT=0 + ;; + *) + SLOT=${SLOT}/${KDE_CATV} + ;; +esac # @ECLASS_VARIABLE: KDE_ORG_SCHEDULE_URI # @INTERNAL @@ -61,32 +67,24 @@ KDE_ORG_SCHEDULE_URI+="/Frameworks" # Helper variable to construct release group specific SRC_URI. _KDE_SRC_URI="mirror://kde/" -case ${KDE_BUILD_TYPE} in - live) - if [[ ${PV} == 5.239.9999 ]]; then - EGIT_BRANCH="kf5" - fi - ;; - *) - if [[ -z ${KDE_ORG_COMMIT} ]]; then - _KDE_SRC_URI+="stable/frameworks/$(ver_cut 1-2)/" - case ${KDE_ORG_NAME} in - kdelibs4support | \ - kdesignerplugin | \ - kdewebkit | \ - khtml | \ - kjs | \ - kjsembed | \ - kmediaplayer | \ - kross | \ - kxmlrpcclient) - _KDE_SRC_URI+="portingAids/" - ;; - esac +# TODO: Remove after last KF5 PortingAid treecleaned; bug 755956 +if [[ ${KDE_BUILD_TYPE} != live && -z ${KDE_ORG_COMMIT} ]]; then + _KDE_SRC_URI+="stable/frameworks/${KDE_CATV}/" + case ${KDE_ORG_NAME} in + kdelibs4support | \ + kdesignerplugin | \ + kdewebkit | \ + khtml | \ + kjs | \ + kjsembed | \ + kmediaplayer | \ + kross | \ + kxmlrpcclient) + _KDE_SRC_URI+="portingAids/" + ;; + esac - SRC_URI="${_KDE_SRC_URI}${KDE_ORG_TAR_PN}-${PV}.tar.xz" - fi - ;; -esac + SRC_URI="${_KDE_SRC_URI}${KDE_ORG_TAR_PN}-${PV}.tar.xz" +fi fi diff --git a/eclass/gear.kde.org.eclass b/eclass/gear.kde.org.eclass index 8089cbb53bf7..2ae40dfbc708 100644 --- a/eclass/gear.kde.org.eclass +++ b/eclass/gear.kde.org.eclass @@ -285,4 +285,19 @@ if $(ver_test -gt 24.07.75); then esac fi +# list of applications ported to KF6 post-24.08 in SLOT=6 having to block SLOT=5 +if $(ver_test -gt 24.11.75); then + case ${PN} in + cantor | \ + kalzium | \ + kmix | \ + kwave | \ + marble | \ + minuet | \ + step) + RDEPEND+=" !${CATEGORY}/${PN}:5" ;; + *) ;; + esac +fi + fi diff --git a/eclass/gstreamer-meson.eclass b/eclass/gstreamer-meson.eclass index 937c86a0f15b..15b0a6390a42 100644 --- a/eclass/gstreamer-meson.eclass +++ b/eclass/gstreamer-meson.eclass @@ -1,4 +1,4 @@ -# Copyright 1999-2024 Gentoo Authors +# Copyright 1999-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: gstreamer-meson.eclass @@ -38,11 +38,6 @@ esac PYTHON_COMPAT=( python3_{10..12} ) [[ ${EAPI} == 8 ]] && inherit python-any-r1 -# TODO: Remove after all older versions are gone from tree -if ver_test ${PV} -lt 1.22.10 ; then - inherit virtualx -fi - # multilib-minimal goes last inherit meson multilib toolchain-funcs xdg-utils multilib-minimal @@ -133,10 +128,7 @@ gstreamer_system_package() { pc=${tuple#*:}-${SLOT} sed -e "1i${dependency} = dependency('${pc}', required : true)" \ -i "${pdir}"/meson.build || die - # TODO: Remove conditional applying once older versions are all gone - if ver_test ${PV} -gt 1.22.5 ; then - sed -e "/meson\.override_dependency[(]pkg_name, ${dependency}[)]/d" -i "${S}"/gst-libs/gst/*/meson.build || die - fi + sed -e "/meson\.override_dependency[(]pkg_name, ${dependency}[)]/d" -i "${S}"/gst-libs/gst/*/meson.build || die done done } @@ -207,8 +199,14 @@ S="${WORKDIR}/${GST_ORG_MODULE}-${PV}" LICENSE="GPL-2" SLOT="1.0" +if ver_test ${GST_ORG_PVP} -ge 1.24 ; then + GLIB_VERSION=2.64.0 +else + GLIB_VERSION=2.62.0 +fi + RDEPEND=" - >=dev-libs/glib-2.40.0:2[${MULTILIB_USEDEP}] + >=dev-libs/glib-${GLIB_VERSION}:2[${MULTILIB_USEDEP}] " BDEPEND=" virtual/pkgconfig diff --git a/eclass/guile-utils.eclass b/eclass/guile-utils.eclass index b0660dcfd1ce..d066013486ed 100644 --- a/eclass/guile-utils.eclass +++ b/eclass/guile-utils.eclass @@ -84,10 +84,14 @@ guile_check_compat # @FUNCTION: guile_set_common_vars # @DESCRIPTION: # Sets common variables that apply to all Guile packages, namely, -# QA_PREBUILT. +# GUILE_AUTO_COMPILE and QA_PREBUILT. guile_set_common_vars() { debug-print-function ${FUNCNAME} "$@" + # We don't want Guile making decisions based on the system cache + # files. Always recompile so we're deterministic. + export GUILE_AUTO_COMPILE=fresh + # These aren't strictly speaking prebuilt. but they do generated a # nonstandard ELF object. if [[ -z ${QA_PREBUILT} ]]; then diff --git a/eclass/java-pkg-2.eclass b/eclass/java-pkg-2.eclass index eebdec584ccc..0b35490e0365 100644 --- a/eclass/java-pkg-2.eclass +++ b/eclass/java-pkg-2.eclass @@ -1,4 +1,4 @@ -# Copyright 2004-2024 Gentoo Authors +# Copyright 2004-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: java-pkg-2.eclass @@ -6,7 +6,7 @@ # java@gentoo.org # @AUTHOR: # Thomas Matthijs <axxo@gentoo.org> -# @SUPPORTED_EAPIS: 7 8 +# @SUPPORTED_EAPIS: 8 # @PROVIDES: java-utils-2 # @BLURB: Eclass for Java Packages # @DESCRIPTION: @@ -17,7 +17,7 @@ if [[ -z ${_JAVA_PKG_2_ECLASS} ]] ; then _JAVA_PKG_2_ECLASS=1 case ${EAPI} in - 7|8) ;; + 8) ;; *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; esac diff --git a/eclass/java-pkg-simple.eclass b/eclass/java-pkg-simple.eclass index 5ed7e3e5b78e..ce4a62f048da 100644 --- a/eclass/java-pkg-simple.eclass +++ b/eclass/java-pkg-simple.eclass @@ -6,7 +6,7 @@ # java@gentoo.org # @AUTHOR: # Java maintainers <java@gentoo.org> -# @SUPPORTED_EAPIS: 7 8 +# @SUPPORTED_EAPIS: 8 # @BLURB: Eclass for packaging Java software with ease. # @DESCRIPTION: # This class is intended to build pure Java packages from Java sources @@ -17,7 +17,7 @@ # directory before calling the src_compile function of this eclass. case ${EAPI} in - 7|8) ;; + 8) ;; *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; esac diff --git a/eclass/kde.org.eclass b/eclass/kde.org.eclass index 9be501ce9e3f..47a52ef0234c 100644 --- a/eclass/kde.org.eclass +++ b/eclass/kde.org.eclass @@ -235,6 +235,14 @@ kde.org_src_unpack() { esac } +kde.org_pkg_info() { + if [[ ${KDE_BUILD_TYPE} = live ]]; then + echo "WARNING! This is an experimental live ebuild of ${CATEGORY}/${PN}" + echo "Use it at your own risk." + echo "Only file bugs at bugs.gentoo.org if convinced that ebuild needs an update!" + fi +} + fi -EXPORT_FUNCTIONS pkg_nofetch src_unpack +EXPORT_FUNCTIONS pkg_nofetch src_unpack pkg_info diff --git a/eclass/kernel-build.eclass b/eclass/kernel-build.eclass index 831027216321..65433d9fc9c0 100644 --- a/eclass/kernel-build.eclass +++ b/eclass/kernel-build.eclass @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Gentoo Authors +# Copyright 2020-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: kernel-build.eclass @@ -108,10 +108,14 @@ IUSE="+strip" # @ECLASS_VARIABLE: KERNEL_GENERIC_UKI_CMDLINE # @USER_VARIABLE # @DESCRIPTION: -# If KERNEL_IUSE_GENERIC_UKI is set, this variable allows setting the -# built-in kernel command line for the UKI. If unset, the default is -# root=/dev/gpt-auto-root ro -: "${KERNEL_GENERIC_UKI_CMDLINE:="root=/dev/gpt-auto-root ro"}" +# If KERNEL_IUSE_GENERIC_UKI is set, and this variable is not +# empty, then the contents are used as the first kernel cmdline +# option of the multi-profile generic UKI. Supplementing the four +# standard options of: +# - root=/dev/gpt-auto-root ro +# - root=/dev/gpt-auto-root ro quiet splash +# - root=/dev/gpt-auto-root ro lockdown=integrity +# - root=/dev/gpt-auto-root ro quiet splash lockdown=integrity if [[ ${KERNEL_IUSE_MODULES_SIGN} ]]; then IUSE+=" modules-sign" @@ -133,6 +137,9 @@ fi kernel-build_pkg_setup() { python-any-r1_pkg_setup if [[ ${KERNEL_IUSE_MODULES_SIGN} && ${MERGE_TYPE} != binary ]]; then + # inherits linux-info to check config values for keys + # ensure KV_FULL will not be set globally, that breaks configure + local KV_FULL secureboot_pkg_setup if use modules-sign && [[ -n ${MODULES_SIGN_KEY} ]]; then @@ -440,6 +447,11 @@ kernel-build_src_install() { # Copy built key/certificate files cp -p build/certs/* "${ED}${kernel_dir}/certs/" || die + # If a key was generated, exclude it from the binpkg + local generated_key=${ED}${kernel_dir}/certs/signing_key.pem + if [[ -r ${generated_key} ]]; then + mv "${generated_key}" "${T}/signing_key.pem" || die + fi # building modules fails with 'vmlinux has no symtab?' if stripped use ppc64 && dostrip -x "${kernel_dir}/${image_path}" @@ -497,10 +509,10 @@ kernel-build_src_install() { local dracut_modules=( base bash btrfs cifs crypt crypt-gpg crypt-loop dbus dbus-daemon - dm dmraid dracut-systemd fido2 i18n fs-lib kernel-modules + dm dmraid dracut-systemd drm fido2 i18n fs-lib kernel-modules kernel-network-modules kernel-modules-extra lunmask lvm nbd mdraid modsign network network-manager nfs nvdimm nvmf pcsc - pkcs11 qemu qemu-net resume rngd rootfs-block shutdown + pkcs11 plymouth qemu qemu-net resume rngd rootfs-block shutdown systemd systemd-ac-power systemd-ask-password systemd-initrd systemd-integritysetup systemd-pcrphase systemd-sysusers systemd-udevd systemd-veritysetup terminfo tpm2-tss udev-rules @@ -526,7 +538,7 @@ kernel-build_src_install() { --ro-mnt --modules "${dracut_modules[*]}" # Pulls in huge firmware files - --omit-drivers "nfp" + --omit-drivers "amdgpu i915 nfp nouveau nvidia xe" ) # Tries to update ld cache @@ -534,29 +546,81 @@ kernel-build_src_install() { dracut "${dracut_args[@]}" "${image%/*}/initrd" || die "Failed to generate initramfs" + # Note, we cannot use an associative array here because those are + # not ordered. + local profiles=() + local cmdlines=() + + # If defined, make the user entry the first and default + if [[ -n ${KERNEL_GENERIC_UKI_CMDLINE} ]]; then + profiles+=( + $'TITLE=User specified at build time\nID=user' + ) + cmdlines+=( "${KERNEL_GENERIC_UKI_CMDLINE}" ) + fi + + profiles+=( + $'TITLE=Default\nID=default' + $'TITLE=Default with splash\nID=splash' + $'TITLE=Default with lockdown\nID=lockdown' + $'TITLE=Default with splash and lockdown\nID=splash-lockdown' + ) + + cmdlines+=( + "root=/dev/gpt-auto-root ro" + "root=/dev/gpt-auto-root ro quiet splash" + "root=/dev/gpt-auto-root ro lockdown=integrity" + "root=/dev/gpt-auto-root ro quiet splash lockdown=integrity" + ) + local ukify_args=( --linux="${image}" --initrd="${image%/*}/initrd" - --cmdline="${KERNEL_GENERIC_UKI_CMDLINE}" --uname="${KV_FULL}" --output="${image%/*}/uki.efi" - ) + --profile="${profiles[0]}" + --cmdline="${cmdlines[0]}" + ) # 0th profile is default + + # Additional profiles have to be added with --join-profile + local i + for (( i=1; i<"${#profiles[@]}"; i++ )); do + ukify build \ + --profile="${profiles[i]}" \ + --cmdline="${cmdlines[i]}" \ + --output="${T}/profile${i}.efi" || + die "Failed to create profile ${i}" + + ukify_args+=( --join-profile="${T}/profile${i}.efi" ) + done if [[ ${KERNEL_IUSE_MODULES_SIGN} ]] && use secureboot; then + # --pcrpkey is appended as is. If the certificate and key + # are in the same file, we could accidentally leak the key + # into the UKI. Pass the certificate through openssl to ensure + # that it truly contains *only* the certificate. + openssl x509 \ + -in "${SECUREBOOT_SIGN_CERT}" -inform PEM \ + -out "${T}/pcrpkey.pem" -outform PEM || + die "Failed to extract certificate" ukify_args+=( - --signtool=sbsign --secureboot-private-key="${SECUREBOOT_SIGN_KEY}" --secureboot-certificate="${SECUREBOOT_SIGN_CERT}" + --pcrpkey="${T}/pcrpkey.pem" + --measure ) if [[ ${SECUREBOOT_SIGN_KEY} == pkcs11:* ]]; then ukify_args+=( --signing-engine="pkcs11" + --pcr-private-key="${SECUREBOOT_SIGN_KEY}" + --pcr-public-key="${SECUREBOOT_SIGN_CERT}" + --phases="enter-initrd" + --pcr-private-key="${SECUREBOOT_SIGN_KEY}" + --pcr-public-key="${SECUREBOOT_SIGN_CERT}" + --phases="enter-initrd:leave-initrd enter-initrd:leave-initrd:sysinit enter-initrd:leave-initrd:sysinit:ready" ) else - # Sytemd-measure does not currently support pkcs11 ukify_args+=( - --measure - --pcrpkey="${ED}${kernel_dir}/certs/signing_key.x509" --pcr-private-key="${SECUREBOOT_SIGN_KEY}" --phases="enter-initrd" --pcr-private-key="${SECUREBOOT_SIGN_KEY}" @@ -565,9 +629,7 @@ kernel-build_src_install() { fi fi - # systemd<255 does not install ukify in /usr/bin - PATH="${PATH}:${BROOT}/usr/lib/systemd:${BROOT}/lib/systemd" \ - ukify build "${ukify_args[@]}" || die "Failed to generate UKI" + ukify build "${ukify_args[@]}" || die "Failed to generate UKI" # Overwrite unnecessary image types to save space > "${image}" || die @@ -597,7 +659,6 @@ kernel-build_pkg_postinst() { ewarn "MODULES_SIGN_KEY was not set, this means the kernel build system" ewarn "automatically generated the signing key. This key was installed" ewarn "in ${EROOT}/usr/src/linux-${KV_FULL}/certs" - ewarn "and will also be included in any binary packages." ewarn "Please take appropriate action to protect the key!" ewarn ewarn "Recompiling this package causes a new key to be generated. As" diff --git a/eclass/kernel-install.eclass b/eclass/kernel-install.eclass index a341dd9426ff..cf34007844a8 100644 --- a/eclass/kernel-install.eclass +++ b/eclass/kernel-install.eclass @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Gentoo Authors +# Copyright 2020-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: kernel-install.eclass @@ -162,9 +162,10 @@ if [[ ${KERNEL_IUSE_GENERIC_UKI} ]]; then ["sys-apps/rng-tools"]="GPL-2" ["sys-apps/sed"]="GPL-3+" ["sys-apps/shadow"]="BSD GPL-2" - ["sys-apps/systemd[boot(-),cryptsetup,pkcs11,policykit,tpm,ukify(-)]"]="GPL-2 LGPL-2.1 MIT public-domain" + [">=sys-apps/systemd-257[boot(-),cryptsetup,pkcs11,policykit,tpm,ukify(-)]"]="GPL-2 LGPL-2.1 MIT public-domain" ["sys-apps/util-linux"]="GPL-2 GPL-3 LGPL-2.1 BSD-4 MIT public-domain" ["sys-auth/polkit"]="LGPL-2" + ["sys-boot/plymouth[drm,systemd(+),udev]"]="GPL-2+" ["sys-block/nbd"]="GPL-2" ["sys-devel/gcc"]="GPL-3+ LGPL-3+ || ( GPL-3+ libgcc libstdc++ gcc-runtime-library-exception-3.1 ) FDL-1.3+" ["sys-fs/btrfs-progs"]="GPL-2" @@ -190,6 +191,7 @@ if [[ ${KERNEL_IUSE_GENERIC_UKI} ]]; then ["sys-libs/readline"]="GPL-3+" ["sys-libs/zlib"]="ZLIB" ["sys-process/procps"]="GPL-2+ LGPL-2+ LGPL-2.1+" + ["x11-libs/libdrm"]="MIT" ["amd64? ( sys-firmware/intel-microcode )"]="amd64? ( intel-ucode )" ["x86? ( sys-firmware/intel-microcode )"]="x86? ( intel-ucode )" ) @@ -202,6 +204,7 @@ if [[ ${KERNEL_IUSE_GENERIC_UKI} ]]; then " IDEPEND=" generic-uki? ( + app-crypt/sbsigntools >=sys-kernel/installkernel-14[-dracut(-),-ugrd(-),-ukify(-)] ) !generic-uki? ( @@ -605,6 +608,15 @@ kernel-install_pkg_preinst() { [[ ! -d ${kernel_dir} ]] && die "Kernel directory ${kernel_dir} not installed!" + # We moved this in order to omit it from the binpkg, move it back + if [[ -r "${T}/signing_key.pem" ]]; then + # cp instead of mv to set owner to root in one go + ( + umask 066 && + cp "${T}/signing_key.pem" "${kernel_dir}/certs/signing_key.pem" + ) || die + fi + # perform the version check for release ebuilds only if [[ ${PV} != *9999 ]]; then local expected_ver=$(dist-kernel_PV_to_KV "${PV}") @@ -649,13 +661,65 @@ kernel-install_extract_from_uki() { local extract_type=${1} local uki=${2} local out=${3} + local out_temp=${T}/${extract_type}-section-dumped # objcopy overwrites input if there is no output, dump the output in T. # We unfortunately cannot use /dev/null here $(tc-getOBJCOPY) "${uki}" "${T}/dump.efi" \ - --dump-section ".${extract_type}=${out}" || - die "Failed to extract ${extract_type}" - chmod 644 "${out}" || die + --dump-section ".${extract_type}=${out_temp}" || + die "Failed to extract ${extract_type}" + + # Sanity checks for kernel images + if [[ ${extract_type} == linux ]] && + { ! in_iuse secureboot || use secureboot ;} + then + # Extract the used SECUREBOOT_SIGN_CERT to verify the kernel image + local cert=${T}/pcrpkey + kernel-install_extract_from_uki pcrpkey "${uki}" "${cert}" + if [[ $(head -n1 "${cert}") != "-----BEGIN CERTIFICATE-----" ]]; then + # This is a DER format certificate, convert it to PEM + openssl x509 \ + -inform DER -in "${cert}" \ + -outform PEM -out "${cert}" || + die "Failed to convert pcrpkey to PEM format" + fi + + # Check if the signature on the UKI is valid + sbverify --cert "${cert}" "${uki}" || + die "ERROR: UKI signature is invalid" + + # Check if the signature on the kernel image is valid + local sbverify_err=$( + sbverify --cert "${cert}" "${out_temp}" 2>&1 >/dev/null + ) + + # Check if there was a padding warning + if [[ ${sbverify_err} == "warning: data remaining"*": gaps between PE/COFF sections?"* ]] + then + # https://github.com/systemd/systemd/issues/35851 + local proper_size=${sbverify_err#"warning: data remaining["} + proper_size=${proper_size%" vs"*} + # Strip the padding + head "${out_temp}" --bytes "${proper_size}" \ + >"${out_temp}_trimmed" || die + # Check if the signature verifies now + sbverify_err=$( + sbverify --cert "${cert}" "${out_temp}_trimmed" 2>&1 >/dev/null + ) + [[ -z ${sbverify_err} ]] && out_temp=${out_temp}_trimmed + fi + + # Something has gone wrong, stop here to prevent installing a kernel + # with an invalid signature or a completely broken kernel image. + if [[ -n ${sbverify_err} ]]; then + eerror "${sbverify_err}" + die "ERROR: Kernel image signature is invalid" + else + einfo "Signature verification OK" + fi + fi + + install -m 644 "${out_temp}" "${out}" || die } # @FUNCTION: kernel-install_install_all @@ -714,9 +778,7 @@ kernel-install_pkg_postinst() { dist-kernel_compressed_module_cleanup \ "${EROOT}/lib/modules/${KV_FULL}" - if [[ -z ${ROOT} ]]; then - kernel-install_install_all "${KV_FULL}" - fi + kernel-install_install_all "${KV_FULL}" if [[ ${KERNEL_IUSE_GENERIC_UKI} ]] && use generic-uki; then ewarn "The prebuilt initramfs and unified kernel image are highly experimental!" @@ -738,9 +800,9 @@ kernel-install_pkg_postinst() { kernel-install_pkg_postrm() { debug-print-function ${FUNCNAME} "$@" - if [[ -z ${ROOT} && ! ${KERNEL_IUSE_GENERIC_UKI} ]]; then - local kernel_dir=${EROOT}/usr/src/linux-${KV_FULL} - local image_path=$(dist-kernel_get_image_path) + local kernel_dir=${EROOT}/usr/src/linux-${KV_FULL} + local image_path=$(dist-kernel_get_image_path) + if [[ ! ${KERNEL_IUSE_GENERIC_UKI} && -d ${kernel_dir} ]]; then ebegin "Removing initramfs" rm -f "${kernel_dir}/${image_path%/*}"/{initrd,uki.efi} && find "${kernel_dir}" -depth -type d -empty -delete @@ -752,8 +814,6 @@ kernel-install_pkg_postrm() { # @DESCRIPTION: # Rebuild the initramfs and reinstall the kernel. kernel-install_pkg_config() { - [[ -z ${ROOT} ]] || die "ROOT!=/ not supported currently" - if [[ -z ${KV_FULL} ]]; then KV_FULL=${PV}${KV_LOCALVERSION} fi diff --git a/eclass/latex-package.eclass b/eclass/latex-package.eclass index 4082e161b843..dfef7fc2836f 100644 --- a/eclass/latex-package.eclass +++ b/eclass/latex-package.eclass @@ -137,11 +137,16 @@ latex-package_src_doinstall() { continue einfo "Making documentation: ${i}" + local mypdflatex=( + pdflatex + ${LATEX_DOC_ARGUMENTS} + --halt-on-error + --interaction=nonstopmode + "${i}" + ) # some macros need compiler called twice, do it here. - set -- pdflatex ${LATEX_DOC_ARGUMENTS} \ - --halt-on-error --interaction=nonstopmode "${i}" - if "${@}"; then - "${@}" + if "${mypdflatex[@]}"; then + "${mypdflatex[@]}" else einfo "pdflatex failed, trying texi2dvi" texi2dvi -q -c --language=latex "${i}" || die @@ -195,6 +200,9 @@ latex-package_src_doinstall() { "all") latex-package_src_doinstall styles fonts bin doc ;; + *) + die "Unknown module: ${1}" + ;; esac shift done diff --git a/eclass/linux-mod-r1.eclass b/eclass/linux-mod-r1.eclass index 4e5b17548b04..16c280219ef8 100644 --- a/eclass/linux-mod-r1.eclass +++ b/eclass/linux-mod-r1.eclass @@ -1,4 +1,4 @@ -# Copyright 2023-2024 Gentoo Authors +# Copyright 2023-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: linux-mod-r1.eclass @@ -333,7 +333,7 @@ linux-mod-r1_pkg_setup() { _MODULES_GLOBAL[ran:pkg_setup]=1 _modules_check_function ${#} 0 0 || return 0 - if [[ -z ${ROOT} && ${MODULES_INITRAMFS_IUSE} ]] && + if [[ ${MODULES_INITRAMFS_IUSE} ]] && use dist-kernel && use ${MODULES_INITRAMFS_IUSE#+} then # Check, but don't die because we can fix the problem and then @@ -508,7 +508,7 @@ linux-mod-r1_pkg_postinst() { dist-kernel_compressed_module_cleanup "${EROOT}/lib/modules/${KV_FULL}" _modules_update_depmod - if [[ -z ${ROOT} && ${MODULES_INITRAMFS_IUSE} ]] && + if [[ ${MODULES_INITRAMFS_IUSE} ]] && use dist-kernel && use ${MODULES_INITRAMFS_IUSE#+} then dist-kernel_reinstall_initramfs "${KV_DIR}" "${KV_FULL}" diff --git a/eclass/llvm-r1.eclass b/eclass/llvm-r1.eclass index 7326e3a6b271..e59bd9c317b9 100644 --- a/eclass/llvm-r1.eclass +++ b/eclass/llvm-r1.eclass @@ -14,8 +14,10 @@ # 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 diff --git a/eclass/llvm-r2.eclass b/eclass/llvm-r2.eclass new file mode 100644 index 000000000000..4dda9aedc7c6 --- /dev/null +++ b/eclass/llvm-r2.eclass @@ -0,0 +1,476 @@ +# Copyright 2024 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: llvm-r2.eclass +# @MAINTAINER: +# Michał Górny <mgorny@gentoo.org> +# @AUTHOR: +# Michał Górny <mgorny@gentoo.org> +# @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-r2_pkg_setup, llvm_chost_setup, llvm_cbuild_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. +# +# Note that the eclass aims for a best-effort support of CHOST builds +# (i.e. compiling/linking against LLVM) and CBUILD use (i.e. calling +# LLVM tools at build time). You need to determine what the package +# in question needs, and put the appropriate packages in DEPEND and/or +# BDEPEND appropriately. +# +# Example: +# @CODE +# LLVM_COMPAT=( {16..18} ) +# +# inherit llvm-r2 +# +# DEPEND=" +# dev-libs/libfoo[${LLVM_USEDEP}] +# $(llvm_gen_dep ' +# llvm-core/clang:${LLVM_SLOT}= +# llvm-core/llvm:${LLVM_SLOT}= +# ') +# " +# @CODE + +case ${EAPI} in + 8) ;; + *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; +esac + +if [[ -z ${_LLVM_R2_ECLASS} ]]; then +_LLVM_R2_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=19 + +# == 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 + # If there is at least one stable slot supported, then enable + # the newest stable slot by default. + IUSE="+llvm_slot_${stable[-1]}" + unset 'stable[-1]' + else + # Otherwise, enable the "oldest" ~arch slot. We really only + # expect a single ~arch version, so this primarily prevents + # defaulting to non-keyworded slots. + IUSE="+llvm_slot_${unstable[0]}" + unset 'unstable[0]' + 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: <dependency> +# @DESCRIPTION: +# Output a dependency block, repeating "<dependency>" 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 ' +# llvm-core/clang:${LLVM_SLOT}= +# llvm-core/llvm:${LLVM_SLOT}= +# ') +# " +# @CODE +llvm_gen_dep() { + debug-print-function ${FUNCNAME} "$@" + + [[ ${#} -ne 1 ]] && die "Usage: ${FUNCNAME} <dependency>" + + 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: generate_llvm_config +# @DESCRIPTION: +# Output a llvm-config compatible script that yields paths specific +# to the requested LLVM version. +generate_llvm_config() { + debug-print-function ${FUNCNAME} "$@" + + local bindir=$(get_llvm_prefix -b)/bin + [[ ! -d ${bindir} ]] && bindir= + + local prefix=$(get_llvm_prefix -d) + local includedir=${prefix}/include + local libdir=${prefix}/$(get_libdir) + local cmake_conf=${libdir}/cmake/llvm/LLVMConfig.cmake + if [[ ! -f ${cmake_conf} ]]; then + cat <<-EOF + #!/usr/bin/env sh + echo "LLVM ${LLVM_SLOT} not installed for ABI=${ABI}" >&2 + exit 127 + EOF + return + fi + + local version=$( + sed -ne 's:set(LLVM_PACKAGE_VERSION \(.*\)):\1:p' "${cmake_conf}" || die + ) + [[ -n ${version} ]] || die + local cppdefs=$( + sed -ne 's:set(LLVM_DEFINITIONS "\(.*\)"):\1:p' "${cmake_conf}" || die + ) + [[ -n ${cppdefs} ]] || die + local targets=$( + sed -ne 's:set(LLVM_TARGETS_TO_BUILD \(.*\)):\1:p' "${cmake_conf}" || die + ) + [[ -n ${targets} ]] || die + local libs=$( + sed -ne 's:set(LLVM_AVAILABLE_LIBS \(.*\)):\1:p' "${cmake_conf}" || die + ) + [[ -n ${libs} ]] || die + local target_triple=$( + sed -ne 's:set(LLVM_TARGET_TRIPLE "\(.*\)"):\1:p' "${cmake_conf}" || die + ) + [[ -n ${target_triple} ]] || die + + readarray -d';' -t targets <<<"${targets}" + readarray -d';' -t libs <<<"${libs}" + # easier than parsing CMake booleans + local assertions=OFF + [[ ${cppdefs} == *-D_DEBUG* ]] && assertions=ON + # major + suffix + local shlib_name=LLVM-${version%%.*} + [[ ${version} == *git* ]] && shlib_name+="git${version##*git}" + + local components=( + "${libs[@]#LLVM}" "${targets[@]}" + # special component groups (grep for add_llvm_component_group) + all all-targets engine native nativecodegen + ) + + cat <<-EOF + #!/usr/bin/env sh + + echo "\${0} \${*}" >> "${T}/llvm-config-calls.txt" + + do_echo() { + echo " \${*}" >> "${T}/llvm-config-calls.txt" + echo "\${@}" + } + + for arg; do + case \${arg} in + --assertion-mode) + do_echo "${assertions}" + ;; + --bindir) + if [ -n "${bindir}" ]; then + do_echo "${bindir}" + else + do_echo "CBUILD LLVM not available" >&2 + exit 1 + fi + ;; + --build-mode) + do_echo RelWithDebInfo + ;; + --build-system) + do_echo cmake + ;; + --cflags|--cppflags) + do_echo "-I${includedir} ${cppdefs[*]}" + ;; + --cmakedir) + do_echo "${libdir}/cmake/llvm" + ;; + --components) + do_echo "${components[*],,}" + ;; + --cxxflags) + do_echo "-I${includedir} -std=c++17 ${cppdefs[*]}" + ;; + --has-rtti) + do_echo YES + ;; + --host-target) + do_echo "${target_triple}" + ;; + --ignore-libllvm) + # ignored + ;; + --includedir) + do_echo "${includedir}" + ;; + --ldflags) + do_echo "-L${libdir}" + ;; + --libdir) + do_echo "${libdir}" + ;; + --libfiles) + do_echo "${libdir}/lib${shlib_name}.so" + ;; + --libnames) + do_echo lib${shlib_name}.so + ;; + --libs) + do_echo "-l${shlib_name}" + ;; + --link-shared|--link-static) + # ignored + ;; + --obj-root|--prefix) + do_echo "${prefix}" + ;; + --shared-mode) + do_echo shared + ;; + --system-libs) + do_echo + ;; + --targets-built) + do_echo "${targets[*]}" + ;; + --version) + do_echo "${version}" + ;; + -*) + do_echo "Unsupported option: \${arg}" >&2 + exit 1 + ;; + *) + # ignore components, we always return the dylib + ;; + esac + done + EOF +} +# @FUNCTION: llvm_cbuild_setup +# @DESCRIPTION: +# Prepend the PATH for selected LLVM version in CBUILD. +# +# This function is meant to be used when the package in question uses +# LLVM tools at build time. It is called automatically +# by llvm-r2_pkg_setup if LLVM is found installed in BROOT. +# +# Note that llvm-config from this path must not be used to build against +# LLVM, as that will break cross-compilation. +llvm_cbuild_setup() { + debug-print-function ${FUNCNAME} "$@" + + local broot_prefix=$(get_llvm_prefix -b) + einfo "Using ${broot_prefix} for CBUILD LLVM ${LLVM_SLOT}" + [[ -d ${broot_prefix}/bin ]] || + die "LLVM ${LLVM_SLOT} not found installed in BROOT (expected: ${broot_prefix}/bin)" + + 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 + llvm_prepend_path -b "${LLVM_SLOT}" +} + +# @FUNCTION: llvm_chost_setup +# @DESCRIPTION: +# Set the environment for finding selected LLVM slot installed +# for CHOST. Create llvm-config wrappers to satisfy legacy lookups. +# +# This function is meant to be used when the package in question uses +# LLVM compiles against and links to LLVM. It is called automatically +# by llvm-r2_pkg_setup if LLVM is found installed in ESYSROOT. +# +# Note that the generated llvm-config may refer to CBUILD installation +# of LLVM via --bindir, if it is found available. +llvm_chost_setup() { + debug-print-function ${FUNCNAME} "$@" + + local esysroot_prefix=$(get_llvm_prefix -d) + einfo "Using ${esysroot_prefix} for CHOST LLVM ${LLVM_SLOT}" + [[ -d ${esysroot_prefix} ]] || + die "LLVM ${LLVM_SLOT} not found installed in ESYSROOT (expected: ${esysroot_prefix})" + + # satisfies find_package() in CMake + export LLVM_ROOT="${esysroot_prefix}" + export Clang_ROOT="${esysroot_prefix}" + export LLD_ROOT="${esysroot_prefix}" + export MLIR_ROOT="${esysroot_prefix}" + export Polly_ROOT="${esysroot_prefix}" + + # satisfies llvm-config calls, e.g. from meson + export PATH="${T}/llvm-bin:${PATH}" + mkdir "${T}"/llvm-bin || die + # we need to generate it per-ABI, since libdir changes + local ABI + for ABI in $(get_all_abis); do + local path="${T}/llvm-bin/$(get_abi_CHOST)-llvm-config" + generate_llvm_config > "${path}" || die + chmod +x "${path}" || die + done + ln -s "$(get_abi_CHOST)-llvm-config" "${T}/llvm-bin/llvm-config" || die +} + +# @FUNCTION: llvm-r2_pkg_setup +# @DESCRIPTION: +# Handle all supported setup actions automatically. If LLVM is found +# installed for CBUILD, call llvm_cbuild_setup. If it is found +# installed for CHOST, call llvm_chost_setup. +# +# This function is a no-op when installing a binary package. +# +# Note that this function is not exported if LLVM_OPTIONAL is set. +# In that case, it needs to be called manually. +llvm-r2_pkg_setup() { + debug-print-function ${FUNCNAME} "$@" + + if [[ ${MERGE_TYPE} != binary ]]; then + [[ -z ${LLVM_SLOT} ]] && die "LLVM_SLOT unset (broken USE_EXPAND?)" + + if [[ -d $(get_llvm_prefix -b)/bin ]]; then + llvm_cbuild_setup + fi + + if [[ -d $(get_llvm_prefix -d) ]]; then + llvm_chost_setup + fi + fi +} + +fi + +if [[ ! ${LLVM_OPTIONAL} ]]; then + EXPORT_FUNCTIONS pkg_setup +fi diff --git a/eclass/llvm-utils.eclass b/eclass/llvm-utils.eclass index 1ae3295484c8..b105e169fbc4 100644 --- a/eclass/llvm-utils.eclass +++ b/eclass/llvm-utils.eclass @@ -113,17 +113,38 @@ llvm_fix_tool_path() { } # @FUNCTION: llvm_prepend_path -# @USAGE: <slot> +# @USAGE: [-b|-d] <slot> # @DESCRIPTION: # Prepend the path to the specified LLVM slot to PATH variable, # and reexport it. +# +# 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. llvm_prepend_path() { debug-print-function ${FUNCNAME} "$@" - [[ ${#} -ne 1 ]] && die "Usage: ${FUNCNAME} <slot>" + local prefix + case ${1--d} in + -d) + prefix=${ESYSROOT} + shift + ;; + -b) + prefix=${BROOT} + shift + ;; + -*) + die "${FUNCNAME}: invalid option: ${1}" + ;; + esac + + [[ ${#} -ne 1 ]] && die "Usage: ${FUNCNAME} [-b|-d] <slot>" local slot=${1} - local llvm_path=${ESYSROOT}/usr/lib/llvm/${slot}/bin + local llvm_path=${prefix}/usr/lib/llvm/${slot}/bin local IFS=: local split_path=( ${PATH} ) local new_path=() diff --git a/eclass/llvm.org.eclass b/eclass/llvm.org.eclass index a7685a38575b..a810027f74f5 100644 --- a/eclass/llvm.org.eclass +++ b/eclass/llvm.org.eclass @@ -1,4 +1,4 @@ -# Copyright 2019-2024 Gentoo Authors +# Copyright 2019-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: llvm.org.eclass @@ -72,11 +72,14 @@ if [[ -z ${_LLVM_SOURCE_TYPE+1} ]]; then _LLVM_SOURCE_TYPE=snapshot case ${PV} in - 20.0.0_pre20241207) - EGIT_COMMIT=32f7f0010bca99ee4bd917f57272733fb2bf3bd9 + 20.0.0_pre20250111) + EGIT_COMMIT=8af4d206e0f979f68925a08f9dffd60a98ce97e2 ;; - 20.0.0_pre20241130) - EGIT_COMMIT=a348f223cab54b21a7b1c38dec7bc6aa2f81c949 + 20.0.0_pre20250104) + EGIT_COMMIT=2529a8df53af9bc6cecfd6c83404ffa5e89e3370 + ;; + 20.0.0_pre20241227) + EGIT_COMMIT=ccfe0de0e1e37ed369c9bf89dd0188ba0afb2e9a ;; *) die "Unknown snapshot: ${PV}" diff --git a/eclass/mono-env.eclass b/eclass/mono-env.eclass index 5415a7043fed..2e19c0b744ee 100644 --- a/eclass/mono-env.eclass +++ b/eclass/mono-env.eclass @@ -4,7 +4,7 @@ # @ECLASS: mono-env.eclass # @MAINTAINER: # maintainer-needed@gentoo.org -# @SUPPORTED_EAPIS: 7 +# @SUPPORTED_EAPIS: 7 8 # @BLURB: Set environment variables commonly used by dotnet packages. # @DESCRIPTION: # Set environment variables commonly used by dotnet packages. diff --git a/eclass/mount-boot-utils.eclass b/eclass/mount-boot-utils.eclass index e24b4e0c0826..72b4c9ccd14a 100644 --- a/eclass/mount-boot-utils.eclass +++ b/eclass/mount-boot-utils.eclass @@ -1,4 +1,4 @@ -# Copyright 1999-2024 Gentoo Authors +# Copyright 1999-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: mount-boot-utils.eclass @@ -16,6 +16,18 @@ # This eclass provides the functions used by mount-boot.eclass in an "inherit- # safe" way. This allows these functions to be used in other eclasses cleanly. +# @ECLASS_VARIABLE: DONT_MOUNT_BOOT +# @USER_VARIABLE +# @DESCRIPTION: +# May be set by the user or an ebuild to completely disable mount checking +# of the /boot partition and the EFI System Partition. + +# @ECLASS_VARIABLE: DONT_MOUNT_ESP +# @USER_VARIABLE +# @DESCRIPTION: +# May be set by the user or an ebuild to disable mount checking of the +# EFI System Partition only. + case ${EAPI} in 7|8) ;; *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; @@ -62,7 +74,7 @@ mount-boot_check_status() { local candidates=( /boot ) # If system is booted with UEFI, check for ESP as well - if [[ -d /sys/firmware/efi ]]; then + if [[ -d /sys/firmware/efi && -z ${DONT_MOUNT_ESP} ]]; then # Use same candidates for ESP as installkernel and eclean-kernel candidates+=( /efi /boot/efi /boot/EFI ) fi diff --git a/eclass/office-ext-r1.eclass b/eclass/office-ext-r1.eclass index 7e4d894483fe..9ee4561f0c11 100644 --- a/eclass/office-ext-r1.eclass +++ b/eclass/office-ext-r1.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: office-ext-r1.eclass @@ -6,13 +6,13 @@ # The office team <office@gentoo.org> # @AUTHOR: # Tomáš Chvátal <scarabeus@gentoo.org> -# @SUPPORTED_EAPIS: 7 +# @SUPPORTED_EAPIS: 7 8 # @BLURB: Eclass for installing libreoffice extensions # @DESCRIPTION: # Eclass for easing maintenance of libreoffice extensions. case ${EAPI} in - 7) ;; + 7|8) ;; *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; esac @@ -70,11 +70,13 @@ fi # @CODE : "${OFFICE_EXTENSIONS_LOCATION:=${DISTDIR}}" -IUSE="" -RDEPEND="" +# Most projects actually do not provide any relevant sourcedir as they are oxt. +S="${WORKDIR}" + +IUSE="$(printf 'office_implementation_%s ' ${OFFICE_IMPLEMENTATIONS[@]})" +REQUIRED_USE="|| ( $(printf 'office_implementation_%s ' ${OFFICE_IMPLEMENTATIONS[@]}) )" for i in ${OFFICE_IMPLEMENTATIONS[@]}; do - IUSE+=" office_implementation_${i}" if [[ ${i} == "libreoffice" ]]; then RDEPEND+=" office_implementation_${i}? ( @@ -86,19 +88,7 @@ for i in ${OFFICE_IMPLEMENTATIONS[@]}; do " fi done - -REQUIRED_USE="|| ( " -for i in ${OFFICE_IMPLEMENTATIONS[@]}; do - REQUIRED_USE+=" office_implementation_${i} " -done -REQUIRED_USE+=" )" - -DEPEND="${RDEPEND} - app-arch/unzip -" - -# Most projects actually do not provide any relevant sourcedir as they are oxt. -S="${WORKDIR}" +BDEPEND="app-arch/unzip" # @FUNCTION: office-ext-r1_src_unpack # @DESCRIPTION: diff --git a/eclass/plasma.kde.org.eclass b/eclass/plasma.kde.org.eclass index 1a626de37bfb..6612028e298b 100644 --- a/eclass/plasma.kde.org.eclass +++ b/eclass/plasma.kde.org.eclass @@ -25,6 +25,13 @@ esac if [[ -z ${_PLASMA_KDE_ORG_ECLASS} ]]; then _PLASMA_KDE_ORG_ECLASS=1 +# @ECLASS_VARIABLE: KDE_CATV +# @DESCRIPTION: +# Holds main Plasma release number (major.minor.micro) for use on same-category +# dependencies. +KDE_CATV=$(ver_cut 1-3) +readonly KDE_CATV + # @ECLASS_VARIABLE: KDE_PV_UNRELEASED # @INTERNAL # @DESCRIPTION: @@ -64,10 +71,10 @@ if [[ ${KDE_BUILD_TYPE} == live ]]; then elif [[ -z ${KDE_ORG_COMMIT} ]]; then case ${PV} in 5.??.[6-9][05]* | 6.?.[6-9][05]* ) - _KDE_SRC_URI+="unstable/plasma/$(ver_cut 1-3)/" + _KDE_SRC_URI+="unstable/plasma/${KDE_CATV}/" RESTRICT+=" mirror" ;; - *) _KDE_SRC_URI+="stable/plasma/$(ver_cut 1-3)/" ;; + *) _KDE_SRC_URI+="stable/plasma/${KDE_CATV}/" ;; esac SRC_URI="${_KDE_SRC_URI}${KDE_ORG_TAR_PN}-${PV}.tar.xz" diff --git a/eclass/qt6-build.eclass b/eclass/qt6-build.eclass index f8161447074a..ca6c63081053 100644 --- a/eclass/qt6-build.eclass +++ b/eclass/qt6-build.eclass @@ -1,4 +1,4 @@ -# Copyright 2021-2024 Gentoo Authors +# Copyright 2021-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: qt6-build.eclass @@ -296,7 +296,7 @@ _qt6-build_sanitize_cpu_flags() { # extras only needed by chromium in qtwebengine # (see also chromium's ebuild wrt bug #530248,#544702,#546984,#853646) [[ ${PN} == qtwebengine ]] && cpuflags+=( - mmx xop + avx512vnni mmx xop # unclear if these two are really needed given (current) chromium # does not pass these flags, albeit it may side-disable something diff --git a/eclass/ruby-fakegem.eclass b/eclass/ruby-fakegem.eclass index eb6257a50cf9..c358015902bb 100644 --- a/eclass/ruby-fakegem.eclass +++ b/eclass/ruby-fakegem.eclass @@ -23,6 +23,8 @@ case ${EAPI} in *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; esac +# flag-o-matic is only required for ruby31 support. +inherit flag-o-matic inherit ruby-ng # @ECLASS_VARIABLE: RUBY_FAKEGEM_NAME @@ -424,6 +426,16 @@ EOF each_fakegem_configure() { debug-print-function ${FUNCNAME} "$@" + # Ruby 3.1 has a varargs implementation that is not compatible with + # gnu23. Ruby 3.1 is EOL in March 2025 and will be removed shortly + # after that. + case ${RUBY} in + *ruby31) + append-flags -std=gnu17 + filter-flags -std=gnu23 + ;; + esac + tc-export PKG_CONFIG for extension in "${RUBY_FAKEGEM_EXTENSIONS[@]}" ; do CC=$(tc-getCC) ${RUBY} --disable=did_you_mean -C ${extension%/*} ${extension##*/} --with-cflags="${CFLAGS}" --with-ldflags="${LDFLAGS}" ${RUBY_FAKEGEM_EXTENSION_OPTIONS} || die @@ -612,7 +624,7 @@ each_fakegem_install() { ruby_fakegem_install_gemspec local _gemlibdirs="${RUBY_FAKEGEM_EXTRAINSTALL}" - for directory in "${RUBY_FAKEGEM_BINDIR}" lib; do + for directory in "${RUBY_FAKEGEM_BINDIR}" lib sig; do [[ -d ${directory} ]] && _gemlibdirs="${_gemlibdirs} ${directory}" done diff --git a/eclass/ruby-utils.eclass b/eclass/ruby-utils.eclass index 29b9ab396b87..4bd3e6ba1292 100644 --- a/eclass/ruby-utils.eclass +++ b/eclass/ruby-utils.eclass @@ -36,14 +36,14 @@ esac RUBY_TARGETS_PREFERENCE="ruby32 ruby31 " # All other active ruby targets -RUBY_TARGETS_PREFERENCE+="ruby33" +RUBY_TARGETS_PREFERENCE+="ruby33 ruby34" _ruby_implementation_depend() { local rubypn= local rubyslot= case $1 in - ruby1[89]|ruby2[0-7]|ruby3[0-3]) + ruby1[89]|ruby2[0-7]|ruby3[0-4]) rubypn="dev-lang/ruby" rubyslot=":${1:4:1}.${1:5}" ;; diff --git a/eclass/rust.eclass b/eclass/rust.eclass index eb14ca2329b5..0630d5973854 100644 --- a/eclass/rust.eclass +++ b/eclass/rust.eclass @@ -1,4 +1,4 @@ -# Copyright 2024 Gentoo Authors +# Copyright 2024-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: rust.eclass @@ -67,6 +67,7 @@ fi # @DESCRIPTION: # Definitive list of Rust slots and the associated LLVM slot, newest first. declare -A -g -r _RUST_LLVM_MAP=( + ["1.84.0"]=19 ["1.83.0"]=19 ["1.82.0"]=19 ["1.81.0"]=18 @@ -88,6 +89,7 @@ declare -A -g -r _RUST_LLVM_MAP=( # While _RUST_LLVM_MAP stores useful info about the relationship between Rust and LLVM slots, # this array is used to store the Rust slots in a more convenient order for iteration. declare -a -g -r _RUST_SLOTS_ORDERED=( + "1.84.0" "1.83.0" "1.82.0" "1.81.0" @@ -286,7 +288,8 @@ unset -f _rust_set_globals # @USAGE: [-b|-d] # @DESCRIPTION: # Find the newest Rust install that is acceptable for the package, -# and print its version number (i.e. SLOT) and type (source or bin[ary]). +# and export its version (i.e. SLOT) and type (source or bin[ary]) +# as RUST_SLOT and RUST_TYPE. # # If -b is specified, the checks are performed relative to BROOT, # and BROOT-path is returned. -b is the default. @@ -363,10 +366,13 @@ _get_rust_slot() { # If we're in LLVM mode we can skip any slots that don't match the selected USE if [[ -n "${RUST_NEEDS_LLVM}" ]]; then if [[ "${llvm_slot}" != "${llvm_r1_slot}" ]]; then + einfo "Skipping Rust ${slot} as it does not match llvm_slot_${llvm_r1_slot}" continue fi fi + einfo "Checking whether Rust ${slot} is suitable ..." + if declare -f rust_check_deps >/dev/null; then local RUST_SLOT="${slot}" local LLVM_SLOT="${_RUST_LLVM_MAP[${slot}]}" @@ -396,11 +402,13 @@ _get_rust_slot() { esac local _pkg for _pkg in "${rust_pkgs[@]}"; do + einfo " Checking for ${_pkg} ..." if has_version "${hv_switch}" "${_pkg}"; then + export RUST_SLOT="${slot}" if [[ "${_pkg}" == "dev-lang/rust:${slot}${usedep}" ]]; then - echo "${slot} source" + export RUST_TYPE="source" else - echo "${slot} binary" + export RUST_TYPE="binary" fi return fi @@ -418,7 +426,12 @@ _get_rust_slot() { die "${FUNCNAME}: invalid max_slot=${max_slot}" fi - die "No Rust slot${1:+ <= ${1}} satisfying the package's dependencies found installed!" + local requirement_msg="" + [[ -n "${RUST_MAX_VER}" ]] && requirement_msg+="<= ${RUST_MAX_VER} " + [[ -n "${RUST_MIN_VER}" ]] && requirement_msg+=">= ${RUST_MIN_VER} " + [[ -n "${RUST_REQ_USE}" ]] && requirement_msg+="with USE=${RUST_REQ_USE}" + requirement_msg="${requirement_msg% }" + die "No Rust matching requirements${requirement_msg:+ (${requirement_msg})} found installed!" } # @FUNCTION: get_rust_path @@ -460,9 +473,8 @@ get_rust_prefix() { local prefix=${BROOT} [[ ${1} == -d ]] && prefix=${ESYSROOT} - local slot rust_type - read -r slot rust_type <<< $(_get_rust_slot "$@") - get_rust_path "${prefix}" "${slot}" "${rust_type}" + _get_rust_slot "$@" + get_rust_path "${prefix}" "${RUST_SLOT}" "${RUST_TYPE}" } # @FUNCTION: rust_prepend_path @@ -500,7 +512,7 @@ rust_pkg_setup() { debug-print-function ${FUNCNAME} "$@" if [[ ${MERGE_TYPE} != binary ]]; then - read -r RUST_SLOT RUST_TYPE <<< $(_get_rust_slot -b) + _get_rust_slot -b rust_prepend_path "${RUST_SLOT}" "${RUST_TYPE}" local prefix=$(get_rust_path "${BROOT}" "${RUST_SLOT}" "${RUST_TYPE}") CARGO="${prefix}bin/cargo" diff --git a/eclass/secureboot.eclass b/eclass/secureboot.eclass index a854061719a9..7361465ee2d3 100644 --- a/eclass/secureboot.eclass +++ b/eclass/secureboot.eclass @@ -1,4 +1,4 @@ -# Copyright 1999-2024 Gentoo Authors +# Copyright 1999-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: secureboot.eclass @@ -57,6 +57,13 @@ BDEPEND=" # @DESCRIPTION: # Used with USE=secureboot. Should be set to the path of the private # key in PEM format to use, or a PKCS#11 URI. +# If unspecified the following locations are tried in order: +# - /etc/portage/secureboot.pem +# - /var/lib/sbctl/keys/db/db.{key,pem} (from app-crypt/sbctl) +# - the MODULES_SIGN_KEY (and MODULES_SIGN_CERT if set) +# - the contents of CONFIG_MODULE_SIG_KEY in the current kernel +# If none of these exist, a new key will be generated at +# /etc/portage/secureboot.pem. # @ECLASS_VARIABLE: SECUREBOOT_SIGN_CERT # @USER_VARIABLE @@ -64,36 +71,13 @@ BDEPEND=" # @DESCRIPTION: # Used with USE=secureboot. Should be set to the path of the public # key certificate in PEM format to use. +# If unspecified the SECUREBOOT_SIGN_KEY is assumed to also contain the +# certificate belonging to it. if [[ -z ${_SECUREBOOT_ECLASS} ]]; then _SECUREBOOT_ECLASS=1 -# @FUNCTION: _secureboot_die_if_unset -# @INTERNAL -# @DESCRIPTION: -# If USE=secureboot is enabled die if the required user variables are unset -# and die if the keys can't be found. -_secureboot_die_if_unset() { - debug-print-function ${FUNCNAME} "$@" - use secureboot || return - - if [[ -z ${SECUREBOOT_SIGN_KEY} || -z ${SECUREBOOT_SIGN_CERT} ]]; then - die "USE=secureboot enabled but SECUREBOOT_SIGN_KEY and/or SECUREBOOT_SIGN_CERT not set." - fi - - # Sanity check: fail early if key/cert in DER format or does not exist - local openssl_args=( - -inform PEM -in "${SECUREBOOT_SIGN_CERT}" - -noout -nocert - ) - if [[ ${SECUREBOOT_SIGN_KEY} == pkcs11:* ]]; then - openssl_args+=( -engine pkcs11 -keyform ENGINE -key "${SECUREBOOT_SIGN_KEY}" ) - else - openssl_args+=( -keyform PEM -key "${SECUREBOOT_SIGN_KEY}" ) - fi - openssl x509 "${openssl_args[@]}" || - die "Secure Boot signing certificate or key not found or not PEM format." -} +inherit linux-info # @FUNCTION: secureboot_pkg_setup # @DESCRIPTION: @@ -105,7 +89,114 @@ secureboot_pkg_setup() { # If we are merging a binary then the files in this binary # are already signed, no need to check the variables. if [[ ${MERGE_TYPE} != binary ]]; then - _secureboot_die_if_unset + if [[ -z ${SECUREBOOT_SIGN_KEY} ]]; then + # No key specified, try some usual suspects + linux-info_pkg_setup + local module_sig_key= + if linux_config_exists MODULE_SIG_KEY; then + : "$(linux_chkconfig_string MODULE_SIG_KEY)" + module_sig_key=${_//\"} + # Convert to absolute path if required + if [[ ${module_sig_key} != pkcs11:* && + ${module_sig_key} != /* ]] + then + module_sig_key=${KV_OUT_DIR}/${module_sig_key} + fi + fi + + # Check both the SYSROOT and ROOT, like linux-info.eclass + ewarn "No Secure Boot signing key specified." + if [[ -r ${SYSROOT}/etc/portage/secureboot.pem ]]; then + ewarn "Using ${SYSROOT}/etc/portage/secureboot.pem as signing key" + export SECUREBOOT_SIGN_KEY=${SYSROOT}/etc/portage/secureboot.pem + export SECUREBOOT_SIGN_CERT=${SYSROOT}/etc/portage/secureboot.pem + elif [[ -r ${ROOT}/etc/portage/secureboot.pem ]]; then + ewarn "Using ${ROOT}/etc/portage/secureboot.pem as signing key" + export SECUREBOOT_SIGN_KEY=${ROOT}/etc/portage/secureboot.pem + export SECUREBOOT_SIGN_CERT=${ROOT}/etc/portage/secureboot.pem + elif [[ -r ${SYSROOT}/var/lib/sbctl/keys/db/db.key && + -r ${SYSROOT}/var/lib/sbctl/keys/db/db.pem ]] + then + ewarn "Using keys maintained by app-crypt/sbctl" + export SECUREBOOT_SIGN_KEY=${SYSROOT}/var/lib/sbctl/keys/db/db.key + export SECUREBOOT_SIGN_CERT=${SYSROOT}/var/lib/sbctl/keys/db/db.pem + elif [[ -r ${ROOT}/var/lib/sbctl/keys/db/db.key && + -r ${ROOT}/var/lib/sbctl/keys/db/db.pem ]] + then + ewarn "Using keys maintained by app-crypt/sbctl" + export SECUREBOOT_SIGN_KEY=${ROOT}/var/lib/sbctl/keys/db/db.key + export SECUREBOOT_SIGN_CERT=${ROOT}/var/lib/sbctl/keys/db/db.pem + elif [[ -r ${MODULES_SIGN_KEY} ]]; then + ewarn "Using the kernel module signing key" + export SECUREBOOT_SIGN_KEY=${MODULES_SIGN_KEY} + if [[ -r ${MODULES_SIGN_CERT} ]]; then + export SECUREBOOT_SIGN_CERT=${MODULES_SIGN_CERT} + else + export SECUREBOOT_SIGN_CERT=${MODULES_SIGN_KEY} + fi + elif [[ -r ${KV_OUT_DIR}/certs/signing_key.x509 ]] && + [[ -r ${module_sig_key} || ${module_sig_key} == pkcs11:* ]] + then + ewarn "Using keys maintained by the kernel" + openssl x509 \ + -in "${KV_OUT_DIR}/certs/signing_key.x509" -inform DER \ + -out "${T}/secureboot.pem" -outform PEM || + die "Failed to convert kernel certificate to PEM format" + export SECUREBOOT_SIGN_KEY=${module_sig_key} + export SECUREBOOT_SIGN_CERT=${T}/secureboot.pem + else + ewarn "No candidate keys found, generating a new key" + local openssl_gen_args=( + req -new -batch -nodes -utf8 -sha256 -days 36500 -x509 + -outform PEM -out "${SYSROOT}/etc/portage/secureboot.pem" + -keyform PEM -keyout "${SYSROOT}/etc/portage/secureboot.pem" + ) + if [[ -r ${KV_OUT_DIR}/certs/x509.genkey ]]; then + openssl_gen_args+=( + -config "${KV_OUT_DIR}/certs/x509.genkey" + ) + elif [[ -r ${KV_OUT_DIR}/certs/default_x509.genkey ]]; then + openssl_gen_args+=( + -config "${KV_OUT_DIR}/certs/default_x509.genkey" + ) + else + openssl_gen_args+=( + -subj '/CN=Build time autogenerated kernel key' + ) + fi + ( + umask 066 + openssl "${openssl_gen_args[@]}" || + die "Failed to generate new signing key" + # Generate DER format key as well for easy inclusion in + # either the UEFI dB or MOK list. + openssl x509 \ + -in "${SYSROOT}/etc/portage/secureboot.pem" -inform PEM \ + -out "${ROOT}/etc/portage/secureboot.x509" -outform DER || + die "Failed to convert signing certificate to DER format" + ) + export SECUREBOOT_SIGN_KEY=${SYSROOT}/etc/portage/secureboot.pem + export SECUREBOOT_SIGN_CERT=${SYSROOT}/etc/portage/secureboot.pem + fi + elif [[ -z ${SECUREBOOT_SIGN_CERT} ]]; then + ewarn "A SECUREBOOT_SIGN_KEY was specified but no SECUREBOOT_SIGN_CERT" + ewarn "was set. Assuming the certificate is in the same file as the key." + export SECUREBOOT_SIGN_CERT=${SECUREBOOT_SIGN_KEY} + fi + + # Sanity check: fail early if key/cert in DER format or does not exist + local openssl_args=( + -inform PEM -in "${SECUREBOOT_SIGN_CERT}" + -noout -nocert + ) + if [[ ${SECUREBOOT_SIGN_KEY} == pkcs11:* ]]; then + openssl_args+=( -engine pkcs11 -keyform ENGINE -key "${SECUREBOOT_SIGN_KEY}" ) + else + openssl_args+=( -keyform PEM -key "${SECUREBOOT_SIGN_KEY}" ) + fi + + openssl x509 "${openssl_args[@]}" || + die "Secure Boot signing certificate or key not found or not PEM format." fi } @@ -123,8 +214,6 @@ secureboot_sign_efi_file() { local input_file=${1} local output_file=${2:-${1}} - _secureboot_die_if_unset - ebegin "Signing ${input_file}" local return=1 if sbverify "${input_file}" --cert "${SECUREBOOT_SIGN_CERT}" &> /dev/null; then diff --git a/eclass/tests/llvm-r1.sh b/eclass/tests/llvm-r1.sh index 892b773a08c9..d4657815465d 100755 --- a/eclass/tests/llvm-r1.sh +++ b/eclass/tests/llvm-r1.sh @@ -54,7 +54,7 @@ test_gen_dep() { local value=$(llvm_gen_dep "${arg}") if [[ ${value} != ${expected} ]]; then - eerror "python_get_usedep ${arg}" + eerror "llvm_gen_dep ${arg}" eerror "gave:" eerror " ${value}" eerror "expected:" @@ -63,67 +63,9 @@ test_gen_dep() { 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 ${?} -} - # full range test_globals '14 15 16 17 18 19' \ - "+llvm_slot_18 llvm_slot_15 llvm_slot_16 llvm_slot_17 llvm_slot_19" \ + "+llvm_slot_19 llvm_slot_15 llvm_slot_16 llvm_slot_17 llvm_slot_18" \ "^^ ( llvm_slot_15 llvm_slot_16 llvm_slot_17 llvm_slot_18 llvm_slot_19 )" \ "llvm_slot_15(-)?,llvm_slot_16(-)?,llvm_slot_17(-)?,llvm_slot_18(-)?,llvm_slot_19(-)?" test_globals '14 15 16 17 18' \ @@ -136,10 +78,10 @@ test_globals '14 15 16' \ "^^ ( llvm_slot_15 llvm_slot_16 )" \ "llvm_slot_15(-)?,llvm_slot_16(-)?" # old + newer than current stable -test_globals '15 19' \ - "+llvm_slot_15 llvm_slot_19" \ - "^^ ( llvm_slot_15 llvm_slot_19 )" \ - "llvm_slot_15(-)?,llvm_slot_19(-)?" +test_globals '15 20' \ + "+llvm_slot_15 llvm_slot_20" \ + "^^ ( llvm_slot_15 llvm_slot_20 )" \ + "llvm_slot_15(-)?,llvm_slot_20(-)?" # newer than current stable test_globals '19' \ "+llvm_slot_19" \ diff --git a/eclass/tests/llvm-r2.sh b/eclass/tests/llvm-r2.sh new file mode 100755 index 000000000000..fde76d2d682e --- /dev/null +++ b/eclass/tests/llvm-r2.sh @@ -0,0 +1,188 @@ +#!/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-r2 + + 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 "llvm_gen_dep ${arg}" + eerror "gave:" + eerror " ${value}" + eerror "expected:" + eerror " ${expected}" + fi + tend ${?} +} + +LLVM_CONFIG_OPTIONS=( + --assertion-mode + --bindir + --build-mode + --build-system + --cflags + --cmakedir + --components + --cppflags + --cxxflags + --has-rtti + --host-target + --ignore-libllvm + --includedir + --ldflags + --libdir + --libfiles + --libnames + --libs + --link-shared + --link-static + --obj-root + --prefix + --shared-mode + --system-libs + --targets-built + --version +) + +normalize_list() { + "${@}" | + sed -e 's:\s\+:\n:g' | + sed -e '/^$/d' | + sort + local ps=${PIPESTATUS[*]} + [[ ${ps} == '0 0 0 0' ]] || die "normalize_list pipe failed: ${ps}" +} + +test_llvm_config() { + einfo "llvm-config for slot ${LLVM_SLOT}, libdir ${LLVM_LIBDIR}" + eindent + + generate_llvm_config > "${TMP}/llvm-config" || die + local triple=$(sh "${TMP}/llvm-config" --host-target || die) + local llvm_config=/usr/lib/llvm/${LLVM_SLOT}/bin/${triple}-llvm-config + + local option res + for option in "${LLVM_CONFIG_OPTIONS[@]}"; do + tbegin "${option}" + + normalize_list sh "${TMP}/llvm-config" "${option}" > "${TMP}/our" + normalize_list "${llvm_config}" "${option}" > "${TMP}/upstream" + case ${option} in + --components) + # our components are a superset of what llvm-config yields + res=$(comm -13 "${TMP}/our" "${TMP}/upstream") + ;; + *) + # expect all elements to match + res=$(comm -3 "${TMP}/our" "${TMP}/upstream") + ;; + esac + + if [[ -z ${res} ]]; then + tend 0 + else + eerror "$(diff -u "${TMP}/our" "${TMP}/upstream")" + tend 1 + fi + done + + eoutdent +} + +# full range +test_globals '14 15 16 17 18 19' \ + "+llvm_slot_19 llvm_slot_15 llvm_slot_16 llvm_slot_17 llvm_slot_18" \ + "^^ ( llvm_slot_15 llvm_slot_16 llvm_slot_17 llvm_slot_18 llvm_slot_19 )" \ + "llvm_slot_15(-)?,llvm_slot_16(-)?,llvm_slot_17(-)?,llvm_slot_18(-)?,llvm_slot_19(-)?" +test_globals '14 15 16 17 18' \ + "+llvm_slot_18 llvm_slot_15 llvm_slot_16 llvm_slot_17" \ + "^^ ( llvm_slot_15 llvm_slot_16 llvm_slot_17 llvm_slot_18 )" \ + "llvm_slot_15(-)?,llvm_slot_16(-)?,llvm_slot_17(-)?,llvm_slot_18(-)?" +# older than stable +test_globals '14 15 16' \ + "+llvm_slot_16 llvm_slot_15" \ + "^^ ( llvm_slot_15 llvm_slot_16 )" \ + "llvm_slot_15(-)?,llvm_slot_16(-)?" +# old + newer than current stable +test_globals '15 20' \ + "+llvm_slot_15 llvm_slot_20" \ + "^^ ( llvm_slot_15 llvm_slot_20 )" \ + "llvm_slot_15(-)?,llvm_slot_20(-)?" +# newer than current stable +test_globals '19' \ + "+llvm_slot_19" \ + "^^ ( llvm_slot_19 )" \ + "llvm_slot_19(-)?" + +LLVM_COMPAT=( {14..18} ) +inherit llvm-r2 + +test_gen_dep 'llvm-core/llvm:${LLVM_SLOT} llvm-core/clang:${LLVM_SLOT}' <<-EOF + llvm_slot_15? ( llvm-core/llvm:15 llvm-core/clang:15 ) + llvm_slot_16? ( llvm-core/llvm:16 llvm-core/clang:16 ) + llvm_slot_17? ( llvm-core/llvm:17 llvm-core/clang:17 ) + llvm_slot_18? ( llvm-core/llvm:18 llvm-core/clang:18 ) +EOF + +TMP=$(mktemp -d || die) +trap 'rm -rf \"${TMP}\"' EXIT +get_libdir() { echo "${LLVM_LIBDIR}"; } + +for installed_llvm_cmake in /usr/lib/llvm/*/lib*/cmake; do + installed_llvm_libdir=${installed_llvm_cmake%/*} + LLVM_LIBDIR=${installed_llvm_libdir##*/} + installed_llvm=${installed_llvm_libdir%/*} + LLVM_SLOT=${installed_llvm##*/} + + test_llvm_config +done + +texit diff --git a/eclass/tests/zig-utils.sh b/eclass/tests/zig-utils.sh new file mode 100755 index 000000000000..14af1d2105e3 --- /dev/null +++ b/eclass/tests/zig-utils.sh @@ -0,0 +1,320 @@ +#!/bin/bash +# Copyright 2024 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 +source tests-common.sh || exit + +inherit zig-utils + +# Set ZIG_TEST_COMPILATION env-var to "1" if you want to test binary +# compilation and running under QEMU. Assumes "zig" is present in PATH +# and qemu binfmt is enabled. +# +# If CPU is marked with ":no-run", it means program compiled for it +# successfully but crashed when running under QEMU. +if [[ "${ZIG_TEST_COMPILATION:-0}" -eq 1 ]]; then + MY_WORKDIR="$(mktemp -d)" + my_cleanup() { + popd > /dev/null + rm -rf "${MY_WORKDIR}" + } + trap 'my_cleanup' EXIT + + pushd "${MY_WORKDIR}" > /dev/null || die + cat <<- _EOF_ > main.zig || die + const std = @import("std"); + + pub fn main() !void { + const stdout = std.io.getStdOut(); + try stdout.writeAll("Hello, Gentoo!\n"); + } + _EOF_ + + zig_test_compile_and_run() { + eindent + einfo "${1}: ${2}" + eoutdent + + if [[ "${2}" == native* ]]; then + return 0 + fi + + if [[ "${1}" == arm* ]]; then + # Bunch of unimplemented Zig + # routines for more "bare-bone" arm. + case "${2}" in + # Some errors in inline assembly, likely too low baseline + generic-soft_float | generic+soft_float) return 0;; + # undefined symbol: __sync_fetch_and_add_1 + # compiler-rt not implemented in upstream for it yet: + # https://github.com/ziglang/zig/issues/4959 + generic+v5te-soft_float) return 0;; + *) ;; + esac + fi + + local ret=0 + + local args=( + -target "${1}" + -mcpu "${2//:no-run/}" + main.zig + ) + if ! zig build-exe "${args[@]}" > /dev/null; then + eerror "Failed to compile for: ${1}, ${2}" + ((++ret)) + return ${ret} + fi + + # Can't run macOS binaries in Linux user-mode QEMU emulators + if [[ "${1}" == *macos* || "${2}" == *":no-run" ]]; then + return ${ret} + fi + + if ! ./main > /dev/null; then + eerror "Failed to run for: ${1}, ${2}" + ((++ret)) + fi + + return ${ret} + } +else + zig_test_compile_and_run() { :; } +fi + +test-convert_c_env_to_zig_tuple() { + local ret=0 + + local -n map=${1} + + local c_tuple + for key in "${!map[@]}"; do + local expected="${map["${key}"]}" + + local c_tuple + local c_flags + if [[ "${key}" == *:* ]]; then + c_tuple="${key%%:*}" + c_flags="${key##*:}" + else + c_tuple="${key}" + c_flags="" + fi + + local actual="$(zig-utils_c_env_to_zig_target "${c_tuple}" "${c_flags}")" + if [[ "${expected}" != "${actual}" ]]; then + eerror "Translating ${c_tuple}: expected ${expected}, found ${actual}" + ((++ret)) + continue + fi + + local zig_cpu="$(zig-utils_c_env_to_zig_cpu "${c_tuple}" "${c_flags}")" + if ! zig_test_compile_and_run "${expected}" "${zig_cpu}"; then + ((++ret)) + continue + fi + done + + return ${ret} +} + +test-convert_c_env_to_zig_cpu() { + local ret=0 + + local -n map=${1} + local chost=${2} + + local c_flags + for c_flags in "${!map[@]}"; do + local expected="${map["${c_flags}"]}" + local actual="$(zig-utils_c_env_to_zig_cpu "${chost}" "${c_flags}")" + if [[ "${expected//:no-run/}" != "${actual}" ]]; then + eerror "Translating ${c_flags}: expected ${expected//:no-run/}, found ${actual}" + ((++ret)) + continue + fi + + local zig_target="$(zig-utils_c_env_to_zig_target "${chost}" "${c_flags}")" + if ! zig_test_compile_and_run "${zig_target}" "${expected}"; then + ((++ret)) + continue + fi + done + + return ${ret} +} + +tbegin '"C tuple to Zig tuple"' +declare -A c_to_zig_map=( + # Just remove "vendor" field + [aarch64-unknown-linux-gnu]=aarch64-linux-gnu + [arm-unknown-linux-musleabi]=arm-linux-musleabi + [x86_64-pc-linux-gnu]=x86_64-linux-gnu + [loongarch64-unknown-linux-gnu]=loongarch64-linux-gnu + [powerpc64le-unknown-linux-gnu]=powerpc64le-linux-gnu + + # ARM big-endian + [armeb-unknown-linux-gnueabi]=armeb-linux-gnueabi + + # https://bugs.gentoo.org/924920 + [armv7a-unknown-linux-gnueabihf]=arm-linux-gnueabihf + + # ARM to Thumb + [arm-unknown-linux-musleabi:"-march=armv7e-m"]=thumb-linux-musleabi + + # ARM families + [armv6j-unknown-linux-gnueabihf]=arm-linux-gnueabihf + [armv6j-linux-gnueabihf]=arm-linux-gnueabihf + [armv7a-softfp-linux-gnueabi]=arm-linux-gnueabi + [armv7a-linux-gnueabi]=arm-linux-gnueabi + + # X86 (32-bit) families + [i486-pc-linux-gnu]=x86-linux-gnu + [i686-linux-gnu]=x86-linux-gnu + + # MacOS + [x86_64-apple-darwin15]=x86_64-macos-none + [arm64-apple-darwin24]=aarch64-macos-none +) +test-convert_c_env_to_zig_tuple c_to_zig_map +tend ${?} + +tbegin '"CFLAGS to Zig CPU for ARM"' +CHOST="armv7a-unknown-linux-musleabihf" +c_to_zig_map=( + [" "]="generic-soft_float" + ["-mcpu=native"]="native-soft_float" + ["-mcpu=cortex-a9"]="cortex_a9-soft_float" + + ["-mcpu=cortex-a9 -march=iwmmxt2"]="cortex_a9+iwmmxt2-soft_float" + + ["-march=armv7e-m"]="generic+v7em-soft_float" + ["-march=armv5te"]="generic+v5te-soft_float" + ["-march=armv6j -mfpu=vfp"]="generic+v6j+vfp2-soft_float" + ["-march=armv7-a -mfpu=vfpv3-d16"]="generic+v7a+vfp3d16-soft_float" + ["-march=armv7-a -mfpu=crypto-neon-fp-armv8"]="generic+v7a+crypto+neon+fp_armv8-soft_float" + + # https://bugs.gentoo.org/924920 + ["-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard"]=generic+v7a+vfp3d16-soft_float +) +test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}" +tend ${?} + +tbegin '"CFLAGS to Zig CPU for AARCH64"' +CHOST="aarch64-unknown-linux-gnu" +c_to_zig_map=( + [" "]="generic" + ["-mcpu=native"]="native" + ["-mcpu=cortex-a78"]="cortex_a78" + + ["-march=armv8.3-a"]="generic+v8_3a" + ["-mcpu=cortex-a78 -march=armv8.3-a"]="cortex_a78+v8_3a" +) +test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}" +tend ${?} + +tbegin '"CFLAGS to Zig CPU for X86"' +CHOST="i686-pc-linux-gnu" +c_to_zig_map=( + [" "]="i686" + ["-march=native"]="native" + + ["-march=i486"]="i486" + ["-march=i586"]="i586" + ["-march=i686"]="i686" + ["-O2 -pipe -march=pentium-m"]="pentium_m" +) +test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}" +tend ${?} + +tbegin '"CFLAGS to Zig CPU for X86-64"' +CHOST="x86_64-pc-linux-gnu" +c_to_zig_map=( + [" "]="x86_64" + ["-march=native"]="native" + + ["-march=x86-64-v2"]="x86_64_v2" + ["-march=x86-64"]="x86_64" + ["-march=znver2"]="znver2" +) +test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}" +tend ${?} + +tbegin '"CFLAGS to Zig CPU for RISCV32"' +CHOST="riscv32-unknown-linux-gnu" +c_to_zig_map=( + [" "]="generic_rv32" + ["-mcpu=native"]="native" + ["-mcpu=sifive-e31"]="sifive_e31" + + ["-mabi=ilp32d -march=rv32imafdc"]="generic_rv32+i+m+a+f+d+c+d" + ["-mcpu=native -mabi=ilp32 -march=rv32imac"]="native+i+m+a+c" +) +test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}" +tend ${?} + +tbegin '"CFLAGS to Zig CPU for RISCV64"' +CHOST="riscv64-unknown-linux-gnu" +c_to_zig_map=( + [" "]="generic_rv64" + ["-mcpu=native"]="native" + ["-mcpu=sifive-u74"]="sifive_u74" + + ["-mabi=lp64 -march=rv64imac"]="generic_rv64+i+m+a+c" + ["-mabi=lp64d -march=rv64gc"]="generic_rv64+i+m+a+f+d+zicsr+zifencei+c+d" + ["-march=rv64gcv"]="generic_rv64+i+m+a+f+d+zicsr+zifencei+c+v" + ["-march=rv64imafdc -mcpu=sifive-u74"]="sifive_u74+i+m+a+f+d+c" + ["-mcpu=native -mabi=lp64 -march=rv64imac"]="native+i+m+a+c" +) +test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}" +tend ${?} + +tbegin '"CFLAGS to Zig CPU for LoongArch64"' +CHOST="loongarch64-unknown-linux-gnu" +c_to_zig_map=( + [" "]="generic_la64" + ["-march=native"]="native" + ["-march=la664"]="la664" + + ["-march=loongarch64 -mabi=lp64d"]="loongarch64+d" + ["-mabi=lp64f"]="generic_la64+f" +) +test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}" +tend ${?} + +tbegin '"CFLAGS to Zig CPU for PowerPC"' +CHOST="powerpc-unknown-linux-gnu" +c_to_zig_map=( + [" "]="ppc" + ["-mcpu=native"]="native" + + ["-mcpu=G5"]="g5" + + # qemu: uncaught target signal 4 (Illegal instruction) - core dumped + ["-mcpu=power7"]="pwr7:no-run" + ["-mcpu=power8"]="pwr8:no-run" + + ["-mcpu=powerpc"]="ppc" + ["-mcpu=powerpcle"]="ppc" +) +test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}" +tend ${?} + +tbegin '"CFLAGS to Zig CPU for PowerPC64"' +CHOST="powerpc64-unknown-linux-gnu" +c_to_zig_map=( + [" "]="ppc64" + ["-mcpu=native"]="native" + + # qemu: uncaught target signal 4 (Illegal instruction) - core dumped + ["-mcpu=power10"]="pwr10:no-run" + + ["-mcpu=power9"]="pwr9" + ["-mcpu=powerpc64"]="ppc64" + ["-mcpu=powerpc64le"]="ppc64le" +) +test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}" +tend ${?} + +texit diff --git a/eclass/texlive-module.eclass b/eclass/texlive-module.eclass index f8b6f0858cd6..15dcdea5df20 100644 --- a/eclass/texlive-module.eclass +++ b/eclass/texlive-module.eclass @@ -79,7 +79,7 @@ esac if [[ -z ${_TEXLIVE_MODULE_ECLASS} ]]; then _TEXLIVE_MODULE_ECLASS=1 -inherit texlive-common +inherit eapi9-pipestatus texlive-common HOMEPAGE="https://www.tug.org/texlive/" @@ -537,16 +537,15 @@ texlive-module_src_install() { grep_expressions+=(-e "/${f//./\\.}\$") done + local status + # "success-status aware grep", returning exit status 0 instead of 1. + _tl_sgrep() { grep "$@"; return "$(( $? <= 1 ? 0 : $? ))"; } ebegin "Installing man pages" find texmf-dist/doc/man -type f -name '*.[0-9n]' -print | - grep -v "${grep_expressions[@]}" | + _tl_sgrep -v "${grep_expressions[@]}" | xargs -d '\n' --no-run-if-empty nonfatal doman - local pipestatus="${PIPESTATUS[*]}" - # The grep in the middle of the pipe may return 1 in case - # everything from the input is dropped. - # See https://bugs.gentoo.org/931994 - [[ ${pipestatus} == "0 "[01]" 0" ]] - eend $? || die "error installing man pages (pipestatus: ${pipestatus})" + status=$(pipestatus -v) + eend $? || die "error installing man pages (PIPESTATUS: ${status})" # Delete all man pages under texmf-dist/doc/man find texmf-dist/doc/man -type f -name '*.[0-9n]' -delete || diff --git a/eclass/toolchain-funcs.eclass b/eclass/toolchain-funcs.eclass index 2911ed66e63c..0abed5b8d75e 100644 --- a/eclass/toolchain-funcs.eclass +++ b/eclass/toolchain-funcs.eclass @@ -647,6 +647,50 @@ _tc-has-openmp() { return ${ret} } +# @FUNCTION: tc-check-min_ver +# @USAGE: <gcc or clang> <minimum version> +# @DESCRIPTION: +# Minimum version of active GCC or Clang to require. +# +# You should test for any necessary minimum version in pkg_pretend in order to +# warn the user of required toolchain changes. You must still check for it at +# build-time, e.g. +# @CODE +# pkg_pretend() { +# [[ ${MERGE_TYPE} != binary ]] && tc-check-min_ver gcc 13.2.0 +# } +# +# pkg_setup() { +# [[ ${MERGE_TYPE} != binary ]] && tc-check-min_ver gcc 13.2.0 +# } +# @CODE +tc-check-min_ver() { + do_check() { + debug-print "Compiler version check for ${1}" + debug-print "Detected: ${2}" + debug-print "Required: ${3}" + if ver_test ${2} -lt ${3}; then + eerror "Your current compiler is too old for this package!" + die "Active compiler is too old for this package (found ${1} ${2})." + fi + } + + case ${1} in + gcc) + tc-is-gcc || return + do_check GCC $(gcc-version) ${2} + ;; + clang) + tc-is-clang || return + do_check Clang $(clang-version) ${2} + ;; + *) + eerror "Unknown first parameter for ${FUNCNAME} - must be gcc or clang" + die "${FUNCNAME}: Parameter ${1} unknown" + ;; + esac +} + # @FUNCTION: tc-check-openmp # @DESCRIPTION: # Test for OpenMP support with the current compiler and error out with diff --git a/eclass/toolchain.eclass b/eclass/toolchain.eclass index d72047e891d1..d85994855704 100644 --- a/eclass/toolchain.eclass +++ b/eclass/toolchain.eclass @@ -1,4 +1,4 @@ -# Copyright 1999-2024 Gentoo Authors +# Copyright 1999-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: toolchain.eclass @@ -411,16 +411,29 @@ if tc_has_feature valgrind ; then fi if [[ ${PN} != gnat-gpl ]] && tc_has_feature ada ; then - BDEPEND+=" - ada? ( - || ( - sys-devel/gcc:${SLOT}[ada] - <sys-devel/gcc-${SLOT}[ada] - <dev-lang/ada-bootstrap-${SLOT} - dev-lang/gnat-gpl[ada] + if tc_use_major_version_only ; then + BDEPEND+=" + ada? ( + || ( + sys-devel/gcc:${SLOT}[ada] + <sys-devel/gcc-${SLOT}[ada] + <dev-lang/ada-bootstrap-$((${SLOT} + 1)) + dev-lang/gnat-gpl[ada] + ) ) - ) - " + " + else + BDEPEND+=" + ada? ( + || ( + sys-devel/gcc:${SLOT}[ada] + <sys-devel/gcc-${SLOT}[ada] + <dev-lang/ada-bootstrap-${SLOT} + dev-lang/gnat-gpl[ada] + ) + ) + " + fi fi # TODO: Add a pkg_setup & pkg_pretend check for whether the active compiler @@ -675,6 +688,11 @@ toolchain_src_prepare() { eapply_user + # Workaround -march=native not working for stage1 with non-GCC (bug #933772). + if ! tc-is-gcc && [[ "${CFLAGS}${CXXFLAGS}" == *-march=native* ]] ; then + CLANG_DISABLE_CET_HACK=1 + fi + if ! use vanilla ; then tc_enable_hardened_gcc fi @@ -703,7 +721,7 @@ toolchain_src_prepare() { gnuconfig_update - if ! use prefix-guest && [[ -n ${EPREFIX} ]] ; then + if ! is_crosscompile && ! use prefix-guest && [[ -n ${EPREFIX} ]] ; then einfo "Prefixifying dynamic linkers..." for f in gcc/config/*/*linux*.h ; do ebegin " Updating ${f}" @@ -970,13 +988,22 @@ toolchain_setup_ada() { # As a penultimate resort, try dev-lang/ada-bootstrap. if ver_test ${ada_bootstrap} -gt ${PV} || [[ -z ${ada_bootstrap} ]] ; then ebegin "Testing fallback dev-lang/ada-bootstrap for Ada" - if has_version -b "<dev-lang/ada-bootstrap-${SLOT}" ; then - # TODO: Figure out ada-bootstrap versioning/slots + # XXX: This can be cleaned up like BDEPEND for tc_use_major_version_only + # once we only support such versions. + if has_version -b "=dev-lang/ada-bootstrap-${SLOT}*" || has_version -b "<dev-lang/ada-bootstrap-${SLOT}" ; then + # Workaround the old scheme + if has_version -b "=dev-lang/ada-bootstrap-0_p2021*" ; then + ada_bootstrap=10 + else + local latest_ada_bootstrap=$(best_version -b "<dev-lang/ada-bootstrap-${SLOT}") + latest_ada_bootstrap="${latest_ada_bootstrap#dev-lang/ada-bootstrap-}" + latest_ada_bootstrap=$(ver_cut 1 ${latest_ada_bootstrap}) + ada_bootstrap="${latest_ada_bootstrap}" + + export ADA_INCLUDE_PATH="${BROOT}/usr/lib/ada-bootstrap/usr/lib/gcc/${CHOST}/${ada_bootstrap}/adainclude::${ADA_INCLUDE_PATH}" + export ADA_OBJECTS_PATH="${BROOT}/usr/lib/ada-bootstrap/usr/lib/gcc/${CHOST}/${ada_bootstrap}/adalib:${ADA_OBJECTS_PATH}" + fi - #local latest_ada_bootstrap=$(best_version -b "<dev-lang/ada-bootstrap-${SLOT}") - #latest_ada_bootstrap="${latest_ada_bootstrap#dev-lang/ada-bootstrap-}" - #latest_ada_bootstrap=$(ver_cut 1 ${latest_ada_bootstrap}) - ada_bootstrap="10" ada_bootstrap_type=ada-bootstrap ada_bootstrap_bin_dir="${BROOT}/usr/lib/ada-bootstrap/bin" @@ -1085,19 +1112,26 @@ toolchain_setup_ada() { # Create bin wrappers because not all of the build system respects # GNATBIND or GNATMAKE. - mkdir "${T}"/ada-wrappers || die - local tool - for tool in gnat{,bind,chop,clean,kr,link,ls,make,name,prep} ; do - cat <<-EOF > "${T}"/ada-wrappers/${tool} || die - #!/bin/sh - exec "${ada_bootstrap_bin_dir}"/${CHOST}-${tool} "\$@" - EOF + _toolchain_make_gnat_wrappers() { + mkdir "${T}"/ada-wrappers || die + local tool + for tool in gnat{,bind,chop,clean,kr,link,ls,make,name,prep} ; do + cat <<-EOF > "${T}"/ada-wrappers/${tool} || die + #!/bin/sh + exec "${ada_bootstrap_bin_dir}"/${CHOST}-${tool} "\$@" + EOF + + export "${tool^^}"="${T}"/ada-wrappers/${tool} + done + chmod +x "${T}"/ada-wrappers/gnat{,bind,chop,clean,kr,link,ls,make,name,prep} || die - export "${tool^^}"="${T}"/ada-wrappers/${tool} - done - chmod +x "${T}"/ada-wrappers/gnat{,bind,chop,clean,kr,link,ls,make,name,prep} || die + export PATH="${T}/ada-wrappers:${old_path}" + } + + # Only make the wrappers for native builds. For cross, we can't + # do it as CBUILD vs CHOST will get mixed up then. + ! tc-is-cross-compiler && _toolchain_make_gnat_wrappers - export PATH="${T}/ada-wrappers:${old_path}" export CC="$(tc-getCC) -specs=${T}/ada.spec" } @@ -1149,11 +1183,6 @@ toolchain_src_configure() { export ac_cv_std_swap_in_utility=no fi - # Workaround -march=native not working for stage1 with non-GCC (bug #933772). - if ! tc-is-gcc && [[ "${CFLAGS}${CXXFLAGS}" == *-march=native* ]] ; then - CLANG_DISABLE_CET_HACK=1 - fi - local flag for flag in $(all-flag-vars) ; do einfo "${flag}=\"${!flag}\"" @@ -1309,8 +1338,13 @@ toolchain_src_configure() { confgcc+=( --enable-lto ) # Build compiler itself using LTO - if tc_version_is_at_least 9.1 && _tc_use_if_iuse lto ; then - BUILD_CONFIG_TARGETS+=( bootstrap-lto ) + if _tc_use_if_iuse lto ; then + # GCC 11 at least has a -Wlto-type-mismatch issue with Ada + if ! tc_version_is_at_least 12.1 && is_ada ; then + :; + elif tc_version_is_at_least 9.1 ; then + BUILD_CONFIG_TARGETS+=( bootstrap-lto ) + fi fi if tc_version_is_at_least 12 && _tc_use_if_iuse cet && [[ -z ${CLANG_DISABLE_CET_HACK} && ${CTARGET} == x86_64-*-gnu* ]] ; then @@ -1635,8 +1669,9 @@ toolchain_src_configure() { [[ ${CTARGET} == *-darwin* ]] && \ confgcc+=( --enable-version-specific-runtime-libs ) + # Linux specifically here for bug #946397. # TODO: amdgcn-amdhsa? - [[ ${CTARGET} == x86_64* ]] && confgcc+=( + [[ ${CTARGET} == x86_64*-*-linux-* ]] && confgcc+=( --enable-offload-defaulted --enable-offload-targets=nvptx-none ) @@ -1769,7 +1804,7 @@ toolchain_src_configure() { fi case ${CBUILD}-${CHOST}-${CTARGET} in - *i686-w64-mingw32*|*x86_64-w64-mingw32*) + *-w*-mingw*) # config/i386/t-cygming requires fixincludes (bug #925204) GCC_RUN_FIXINCLUDES=1 ;; @@ -2606,7 +2641,7 @@ toolchain_src_install() { # - "${D}${LIBPATH}" # As dostrip does not specify host to override ${CHOST} tools just skip # non-native binary stripping. - is_crosscompile && dostrip -x "${LIBPATH}" + is_crosscompile && dostrip -x "${LIBPATH#"${EPREFIX}"}" cd "${S}" || die if is_crosscompile; then @@ -2770,8 +2805,10 @@ gcc_movelibs() { mv "${ED}"/usr/nvptx-none/lib/mgomp/mptx-3.1/*.{a,spec} "${ED}"/usr/lib/gcc/${CHOST}/${GCCMAJOR}/accel/nvptx-none/mgomp/mptx-3.1/ mv "${ED}"/usr/lib/gcc/nvptx-none/${GCCMAJOR}/*.{a,spec} "${ED}"/usr/lib/gcc/${CHOST}/${GCCMAJOR}/accel/nvptx-none/ || die mv "${ED}"/usr/lib/gcc/nvptx-none/${GCCMAJOR}/mgomp/*.{a,spec} "${ED}"/usr/lib/gcc/${CHOST}/${GCCMAJOR}/accel/nvptx-none/mgomp/ || die - mv "${ED}"/usr/lib/gcc/nvptx-none/${GCCMAJOR}/mptx-3.1/*.{a,spec} "${ED}"/usr/lib/gcc/${CHOST}/${GCCMAJOR}/accel/nvptx-none/mptx-3.1/ || die - mv "${ED}"/usr/lib/gcc/nvptx-none/${GCCMAJOR}/mgomp/mptx-3.1/*.{a,spec} "${ED}"/usr/lib/gcc/${CHOST}/${GCCMAJOR}/accel/nvptx-none/mgomp/mptx-3.1/ || die + # Nonfatal because the multilib variants change: see r15-5975-g86b3a7532d56f7 and r15-6029-gd4e1f7cfdb8375 + # TODO: Should we enable all of them unconditionally? Expose it somehow (USE_EXPAND?)? + mv "${ED}"/usr/lib/gcc/nvptx-none/${GCCMAJOR}/mptx-3.1/*.{a,spec} "${ED}"/usr/lib/gcc/${CHOST}/${GCCMAJOR}/accel/nvptx-none/mptx-3.1/ + mv "${ED}"/usr/lib/gcc/nvptx-none/${GCCMAJOR}/mgomp/mptx-3.1/*.{a,spec} "${ED}"/usr/lib/gcc/${CHOST}/${GCCMAJOR}/accel/nvptx-none/mgomp/mptx-3.1/ fi # We remove directories separately to avoid this case: @@ -2924,6 +2961,12 @@ toolchain_pkg_postrm() { rm -f "${EROOT}"/usr/bin/${CTARGET}-{gcc,{g,c}++}{,32,64} fi return 0 + else + # Removed the last GCC installed (bug #906040) + if ! has_version "sys-devel/gcc" && has_version "sys-devel/clang" ; then + einfo "Last GCC version removed. Cleaning up ${EROOT}/etc/clang/gentoo-gcc-install.cfg." + echo > "${EROOT}"/etc/clang/gentoo-gcc-install.cfg + fi fi # gcc stopped installing .la files fixer in June 2020. diff --git a/eclass/verify-sig.eclass b/eclass/verify-sig.eclass index 0e6b9b43e557..12b689f0f4b2 100644 --- a/eclass/verify-sig.eclass +++ b/eclass/verify-sig.eclass @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Gentoo Authors +# Copyright 2020-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: verify-sig.eclass @@ -48,6 +48,8 @@ esac if [[ -z ${_VERIFY_SIG_ECLASS} ]]; then _VERIFY_SIG_ECLASS=1 +inherit eapi9-pipestatus + IUSE="verify-sig" # @ECLASS_VARIABLE: VERIFY_SIG_METHOD @@ -423,6 +425,36 @@ verify-sig_verify_signed_checksums() { esac } +# @FUNCTION: verify-sig_uncompress_verify_unpack +# @USAGE: <compressed-tar> <sig-file> [<key-file>] +# @DESCRIPTION: +# Uncompress the <compressed-tar> tarball, verify the uncompressed +# archive against the signature in <sig-file> and unpack it. This is +# useful for kernel.org packages that sign the uncompressed tarball +# instead of the compressed archive. <key-file> can either be passed +# directly, or it defaults to VERIFY_SIG_OPENPGP_KEY_PATH. The function +# dies if verification or any of the unpacking steps fail. +verify-sig_uncompress_verify_unpack() { + local file=${1} + local unpacker + + # TODO: integrate with unpacker.eclass somehow? + case ${file} in + *.tar.xz) + unpacker=( xz -cd ) + ;; + *) + die "${FUNCNAME}: only .tar.xz archives are supported at the moment" + ;; + esac + + einfo "Unpacking ${file} ..." + verify-sig_verify_detached - "${@:2}" < <( + "${unpacker[@]}" "${file}" | tee >(tar -xf - || die) + pipestatus || die + ) +} + # @FUNCTION: verify-sig_src_unpack # @DESCRIPTION: # Default src_unpack override that verifies signatures for all diff --git a/eclass/xorg-3.eclass b/eclass/xorg-3.eclass index ee4038533bfd..2ca5959dd1e7 100644 --- a/eclass/xorg-3.eclass +++ b/eclass/xorg-3.eclass @@ -8,7 +8,7 @@ # Author: Tomáš Chvátal <scarabeus@gentoo.org> # Author: Donnie Berkholz <dberkholz@gentoo.org> # Author: Matt Turner <mattst88@gentoo.org> -# @SUPPORTED_EAPIS: 7 8 +# @SUPPORTED_EAPIS: 8 # @PROVIDES: multilib-minimal # @BLURB: Reduces code duplication in the modularized X11 ebuilds. # @DESCRIPTION: @@ -23,7 +23,7 @@ # everything else should be automatic. case ${EAPI} in - 7|8) ;; + 8) ;; *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; esac @@ -111,9 +111,8 @@ HOMEPAGE="https://www.x.org/wiki/ https://gitlab.freedesktop.org/xorg/${XORG_MOD # @ECLASS_VARIABLE: XORG_TARBALL_SUFFIX # @PRE_INHERIT # @DESCRIPTION: -# Most X11 projects provide tarballs as tar.bz2 or tar.xz. This eclass defaults -# to bz2. -: "${XORG_TARBALL_SUFFIX:="bz2"}" +# Most X11 projects provide tarballs as tar.xz. This eclass defaults to xz. +: "${XORG_TARBALL_SUFFIX:="xz"}" if [[ ${PV} == *9999* ]]; then : "${EGIT_REPO_URI:="https://gitlab.freedesktop.org/xorg/${XORG_MODULE}${XORG_PACKAGE_NAME}.git"}" diff --git a/eclass/zig-utils.eclass b/eclass/zig-utils.eclass new file mode 100644 index 000000000000..5502d997935e --- /dev/null +++ b/eclass/zig-utils.eclass @@ -0,0 +1,559 @@ +# Copyright 2024-2025 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: zig-utils.eclass +# @MAINTAINER: +# Eric Joldasov <bratishkaerik@landless-city.net> +# @AUTHOR: +# Eric Joldasov <bratishkaerik@landless-city.net> +# @SUPPORTED_EAPIS: 8 +# @BLURB: Prepare Zig toolchain and set global variables +# @DESCRIPTION: +# Prepare Zig toolchain and set global variables. +# Supports Zig 0.13+. +# Does not set any default function, ebuilds must call them manually. +# Generally, only "zig-utils_setup" is needed. +# +# Intended to be used by ebuilds that call "zig build-exe/lib/obj" +# or "zig test" directly and by "dev-lang/zig". +# For ebuilds with ZBS (Zig Build System), it's usually better +# to inherit zig.eclass instead, as it has default phases-functions. + +if [[ -z ${_ZIG_UTILS_ECLASS} ]]; then +_ZIG_UTILS_ECLASS=1 + +case ${EAPI} in + 8) ;; + *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; +esac + +inherit edo flag-o-matic linux-info + +# @ECLASS_VARIABLE: ZIG_SLOT +# @PRE_INHERIT +# @REQUIRED +# @DESCRIPTION: +# Zig slot that will be used in "ezig" function. Also, if +# ZIG_OPTIONAL is empty, adds dev-lang/zig and dev-lang/zig-bin +# dependency to BDEPEND. Must be >= "0.13". +# +# Example: +# @CODE +# ZIG_SLOT="0.13" +# @CODE +# +# When a new Zig release occurs, it is advisable for maintainers to +# check whether their ebuild supports that new version. If yes, they +# they should bump ZIG_SLOT to the latest version; if not supported, +# they need to patch any issues with new version and again bump +# ZIG_SLOT. This helps to reduce dependencies on outdated Zig +# versions. +# +# This policy of "1 exclusive Zig slot" will work until it +# stabilizes enough (probably near 1.0), then it will be re-evaluated +# and most likely changed to more common in other eclasses ZIG_MIN/ +# ZIG_MAX form. + +# @ECLASS_VARIABLE: ZIG_NEEDS_LLVM +# @PRE_INHERIT +# @DEFAULT_UNSET +# @DESCRIPTION: +# If set to a non-empty value, the package will BDEPEND on a Zig package +# with LLVM enabled. This is currently required for packages that require +# C/C++ source files to be compiled with Zig. + +# @ECLASS_VARIABLE: ZIG_OPTIONAL +# @PRE_INHERIT +# @DEFAULT_UNSET +# @DESCRIPTION: +# If set to a non-empty value, all logic in zig-utils and +# zig eclasses will be considered optional. No dependencies +# will be added and no phase functions will be exported. +# +# For zig-utils.eclass users: +# You have to add Zig dependency in your BDEPEND manually and call +# at least "zig-utils_setup" before using "ezig". +# +# For zig.eclass users: see documentation in zig.eclass +# instead. +if [[ ! ${ZIG_OPTIONAL} ]]; then + _ZIG_USEDEP="" + if [[ ${ZIG_NEEDS_LLVM} ]]; then + _ZIG_USEDEP="[llvm(+)]" + fi + + # NOTE: zig-bin is always built with LLVM support, so no USE needed. + BDEPEND=" + || ( + dev-lang/zig:${ZIG_SLOT}${_ZIG_USEDEP} + dev-lang/zig-bin:${ZIG_SLOT} + ) + " +fi + +# @ECLASS_VARIABLE: ZIG_TARGET +# @DEFAULT_UNSET +# @DESCRIPTION: +# Zig target tuple to use. Has the following format: +# arch-os[.os_version_range]-abi[.abi_version] +# Can be passed as: +# * "-target " option in "zig test" or "zig build-exe/lib/obj", +# * "-Dtarget=" option in "zig build" +# (if project uses "std.Build.standardTargetOptions"). +# +# Can be set by user in make.conf. If not set, then auto-generated by +# "zig-utils_setup". +# +# Example: +# @CODE +# # Autodetected by Zig: +# ZIG_TARGET="native" +# # Machine running Linux x86_64 system, with glibc: +# ZIG_TARGET="x86_64-linux-gnu" +# # Similar to above, but versions are passed explicitly: +# ZIG_TARGET="x86_64-linux.6.1.12...6.6.16-gnu.2.38" +# # Machine running Linux PPC64 little-endian system, with musl +# ZIG_TARGET="powerpc64le-linux-musl" +# @CODE +# +# Note for eclass users: it is discouraged to overwrite ZIG_TARGET +# value by ebuilds. In most cases, if you need to hardcode value for +# -Dtarget, it's better to change "build.zig" code instead to use +# appropriate values. For example, if some build-time executable +# intented for host is compiled for cross-platform target, change in +# build.zig "target" for that executable to be "b.graph.host". +# +# In rare cases, if you really need to hardcode ZIG_TARGET, use this +# syntax before calling `zig-utils_setup` (or `zig_pkg_setup`) to +# allow user override: +# @CODE +# pkg_setup() { +# : "${ZIG_TARGET:=aarch64-freestanding-none}" +# zig_pkg_setup +# } +# @CODE + +# @ECLASS_VARIABLE: ZIG_CPU +# @DEFAULT_UNSET +# @DESCRIPTION: +# Zig target CPU and features to use. Has the following format: +# family_name(\+enable_feature|\-disable_feature)* +# Can be passed as: +# * "-mcpu " option in "zig test" or "zig build-exe/lib/obj", +# * "-Dcpu=" option in "zig build" +# (if project uses "std.Build.standardTargetOptions"). +# +# Can be set by user in make.conf. If not set, then auto-generated by +# "zig-utils_setup". +# +# Example: +# @CODE +# # Autodetected by Zig: +# ZIG_CPU="native" +# # AMD Zen 2 processor +# ZIG_CPU="znver2" +# # x86_64 processor, X87 support enabled, SSE2 support disabled +# ZIG_CPU="x86_64+x87-sse2" +# @CODE +# +# Note for eclass users: it is discouraged to overwrite ZIG_CPU +# value by ebuilds. In most cases, if you need to hardcode value for +# -Dcpu, it's better to change "build.zig" code instead to use +# appropriate values. For example, if some build-time executable +# intented for host is compiled for cross-platform target, change in +# build.zig "target" for that executable to be "b.graph.host". +# +# In rare cases, if you really need to hardcode ZIG_CPU, use this +# syntax before calling `zig-utils_setup` (or `zig_pkg_setup`) to +# allow user override: +# @CODE +# pkg_setup() { +# : "${ZIG_CPU:=apple_m1}" +# zig_pkg_setup +# } +# @CODE + +# @ECLASS_VARIABLE: ZIG_EXE +# @OUTPUT_VARIABLE +# @DESCRIPTION: +# Absolute path to the used Zig executable. +# Set by "zig-utils_setup"/"zig-utils_find_installation". +# +# Please note that when passing one flag several times with different +# values: +# * (only "zig build") in "-Dbar=false -Dbar" form: +# errors due to conflict of flags, +# * (only "zig build") in "-Dbar=false -Dbar=true" form: +# "bar" becomes a list, which is likely not what you want, +# * in "-fbar -fno-bar" form: +# latest value overwrites values before. +# Example above shows only boolean option, but it is same with other +# types of options (enums, "std.zig.BuildId", "std.SemanticVersion", +# integers, strings, etc.). + +# @ECLASS_VARIABLE: ZIG_VER +# @OUTPUT_VARIABLE +# @DESCRIPTION: +# Zig version as reported in dev-lang/zig-${PV} PV part. +# Set by "zig-utils_setup"/"zig-utils_find_installation". +# +# Example: +# @CODE +# 0.13.0 +# @CODE + +# @FUNCTION: zig-utils_c_env_to_zig_target +# @USAGE: <C-style target tuple> <CFLAGS> +# @DESCRIPTION: +# Translates C-style target tuple (like CHOST) and CFLAGS to Zig-style +# target tuple. For full information "zig-utils_c_env_to_zig_cpu" is +# needed, because some information is located in different places in C +# and Zig, for example: +# * Moved from C target to Zig CPU: x86 and ARM families, +# * Moved from CFLAGS to Zig tuple: ARM Thumb mode. +# +# Mostly used during cross-compilation to get target triple if user +# did not set ZIG_TARGET variable, and always during bootstraping Zig. +# +# See ZIG_TARGET description for more information. +zig-utils_c_env_to_zig_target() { + if [[ ${#} -ne 2 ]]; then + die "${FUNCNAME[0]}: expected 2 arguments, got ${#}" + fi + local c_tuple="${1}" + local c_arch="${c_tuple%%-*}" + local c_abi="${c_tuple##*-}" + + local c_flags="${2}" + local c_flags_march="$(CFLAGS="${c_flags}" get-flag march)" + + local arch os abi + + case "${c_arch}" in + i?86) arch=x86;; + arm64) arch=aarch64;; + arm*) + if [[ "${c_flags_march}" == *-m ]]; then + arch=thumb + else + arch=arm + fi + + if [[ "${c_arch}" == *eb ]]; then + arch+="eb" + fi + ;; + *) arch="${c_arch}";; + esac + + case "${c_tuple}" in + *-linux*) os=linux;; + *-apple*) os=macos;; + esac + + case "${c_abi}" in + darwin*) abi=none;; + *) abi="${c_abi}";; + esac + + echo "${arch}-${os}-${abi}" +} + +# @FUNCTION: zig-utils_c_env_to_zig_cpu +# @USAGE: <C-style target tuple> <CFLAGS> +# @DESCRIPTION: +# Translates C-style target tuple (like CHOST) and CFLAGS to Zig-style +# target CPU and features. For full information +# "zig-utils_c_env_to_zig_target" is needed, because some information +# is located in different places in C and Zig, for example: +# * Moved from C target to Zig CPU: x86 and ARM families, +# * Moved from CFLAGS to Zig tuple: ARM Thumb mode. +# +# Used to get target CPU if user did not set ZIG_CPU variable. +# +# See ZIG_CPU description for more information. +zig-utils_c_env_to_zig_cpu() { + if [[ ${#} -ne 2 ]]; then + die "${FUNCNAME[0]}: expected 2 arguments, got ${#}" + fi + local c_tuple="${1}" + local c_arch="${c_tuple%%-*}" + + local c_flags="${2}" + local c_flags_mabi="$(CFLAGS="${c_flags}" get-flag mabi)" + local c_flags_march="$(CFLAGS="${c_flags}" get-flag march)" + local c_flags_mcpu="$(CFLAGS="${c_flags}" get-flag mcpu)" + local c_flags_mfpu="$(CFLAGS="${c_flags}" get-flag mfpu)" + + local base_cpu features="" + + case "${c_arch}" in + x86_64 | i?86) + local c_cpu="${c_flags_march}" + case "${c_cpu}" in + "") base_cpu="${c_arch}";; + *) base_cpu="${c_cpu//[-.]/_}";; + esac + ;; + aarch64 | aarch64_be | arm*) + local c_cpu="${c_flags_mcpu}" + case "${c_cpu}" in + "") base_cpu=generic;; + *) base_cpu="${c_cpu//[-.]/_}";; + esac + + case "${c_flags_march}" in + "") ;; + armv*) + local c_arm_family="${c_flags_march##arm}" + c_arm_family="${c_arm_family//./_}" + c_arm_family="${c_arm_family//-/}" + features+="+${c_arm_family}" + ;; + *) features+="+${c_flags_march}";; + esac + + if [[ "${c_arch}" != aarch64* && "${c_arch}" != arm64 ]]; then + if [[ "${c_flags_mfpu}" == crypto-* ]]; then + c_flags_mfpu="${c_flags_mfpu##crypto-}" + features+="+crypto" + fi + if [[ "${c_flags_mfpu}" == neon-* ]]; then + c_flags_mfpu="${c_flags_mfpu##neon-}" + features+="+neon" + fi + + case "${c_flags_mfpu}" in + "" | auto) ;; + neon) features+="+neon";; + fp16) features+="+fp16";; + fp-armv8) features+="+fp_armv8";; + + vfp | vfpv2) features+="+vfp2";; + + vfp3 | vfpv3) features+="+vfp3";; + vfpv3-fp16) features+="+vfp3sp";; + vfpv3-d16) features+="+vfp3d16";; + vfpv3-d16-fp16) features+="+vfp3d16sp";; + vfpv3xd) features+="+vfp3d16sp";; + vfpv3xd-fp16) features+="+vfp3d16sp+fp16";; + + vfpv4) features+="+vfp4";; + vfpv4-fp16) features+="+vfp4sp";; + vfpv4-d16) features+="+vfp4d16";; + fpv4-sp-fp16) features+="+vfp4d16sp";; + + fpv5-d16) features+="+fp_armv8d16+fp64";; + *) die -n "Unknown ARM FPU: ${c_flags_mfpu}";; + esac + + local is_softfloat="$(CTARGET="${c_tuple}" tc-tuple-is-softfloat)" + case "${is_softfloat}" in + only | yes) features+="+soft_float";; + softfp | no) features+="-soft_float";; + *) die -n "tc-tuple-is-softfloat returned unexpected value: ${is_softfloat}" + esac + fi + ;; + riscv32 | riscv64) + local c_cpu="${c_flags_mcpu}" + case "${c_cpu}" in + "") + case "${c_arch}" in + riscv32) base_cpu=generic_rv32;; + riscv64) base_cpu=generic_rv64;; + esac + ;; + *) base_cpu="${c_cpu//[-.]/_}";; + esac + + local base_isa="${c_flags_march:0:4}" + local extensions="${c_flags_march:4}" + + case "${base_isa}" in + "" | rv32 | rv64) ;; + *) die -n "Unknown RISC-V architecture: ${base_isa}";; + esac + + local extension + while read -n 1 extension; do + case "${extension}" in + "") ;; + g) features+="+i+m+a+f+d+zicsr+zifencei";; + _) die -n "Can't translate multi-letter RISC-V extensions yet";; + *) features+="+${extension}";; + esac + done <<< "${extensions}" + + case "${c_flags_mabi}" in + ilp32d | lp64d) features+="+d";; + ilp32e | lp64e) features+="+e";; + ilp32f | lp64f) features+="+f";; + "" | ilp32 | lp64) ;; + *) die -n "Unknown RISC-V ABI: ${c_flags_mabi}";; + esac + ;; + loongarch64) + local c_cpu="${c_flags_march}" + case "${c_cpu}" in + "") base_cpu=generic_la64;; + *) base_cpu="${c_cpu//[-.]/_}";; + esac + + case "${c_flags_mabi}" in + lp64d) features+="+d";; + lp64f) features+="+f";; + lp64s | "") ;; + *) die -n "Unknown LoongArch ABI: ${c_flags_mabi}";; + esac + ;; + powerpc | powerpcle | powerpc64 | powerpc64le) + local c_cpu="${c_flags_mcpu}" + case "${c_cpu}" in + "") + case "${c_arch}" in + powerpc | powerpcle) base_cpu=ppc;; + powerpc64 | powerpc64le) base_cpu=ppc64;; + esac + ;; + G*) base_cpu="${c_cpu//G/g}";; + powerpcle) base_cpu=ppc;; + powerpc*) base_cpu="${c_cpu//powerpc/ppc}";; + power*) base_cpu="${c_cpu//power/pwr}";; + *) base_cpu="${c_cpu//[-.]/_}";; + esac + ;; + *) base_cpu=generic;; + esac + + echo "${base_cpu}${features}" +} + +# @FUNCTION: zig-utils_find_installation +# @DESCRIPTION: +# Detects suitable Zig installation and sets ZIG_VER and ZIG_EXE +# variables. +# +# See ZIG_EXE and ZIG_VER descriptions for more information. +zig-utils_find_installation() { + # Adapted from https://github.com/gentoo/gentoo/pull/28986 + # Many thanks to Florian Schmaus (Flowdalic)! + + [[ -n "${ZIG_SLOT}" ]] || die "${FUNCNAME[0]}: ZIG_SLOT must be set" + if ver_test "${ZIG_SLOT}" -lt "0.13"; then + die "${ECLASS}: ZIG_SLOT must be >= 0.13, found ${ZIG_SLOT}" + fi + + einfo "Searching Zig ${ZIG_SLOT}..." + + local zig_supported_versions=( + "9999" + "0.13.1" + "0.13.0" + ) + + local base_path="${BROOT}/usr/bin" + + local -x ZIG_GLOBAL_CACHE_DIR="${T}/zig-detect" + mkdir -p "${ZIG_GLOBAL_CACHE_DIR}" || die + touch "${ZIG_GLOBAL_CACHE_DIR}/empty.zig" || die + + local selected_path selected_ver + for selected_ver in "${zig_supported_versions[@]}"; do + # Check if candidate satisfies ZIG_SLOT condition. + if [[ "${selected_ver}" != "${ZIG_SLOT}"* ]]; then + continue + fi + + # Prefer "dev-lang/zig" over "dev-lang/zig-bin" + local candidate_path + for candidate_path in "${base_path}"/zig{,-bin}-"${selected_ver}"; do + if [[ -x "${candidate_path}" ]]; then + if [[ ${ZIG_NEEDS_LLVM} ]]; then + "${candidate_path}" test -fllvm -OReleaseSmall "${ZIG_GLOBAL_CACHE_DIR}/empty.zig" &> /dev/null || continue + fi + selected_path="${candidate_path}" + break 2 + fi + done + done + + if [[ -z "${selected_path}" ]]; then + die "Could not find (suitable) Zig at \"${base_path}\"" + fi + + declare -g ZIG_EXE="${selected_path}" + declare -g ZIG_VER="${selected_ver}" + # Sanity check, comment from upstream: + # > Check libc++ linkage to make sure Zig was built correctly, + # > but only for "env" and "version" to avoid affecting the + # > startup time for build-critical commands + # > (check takes about ~10 μs) + "${ZIG_EXE}" version > /dev/null || + die "Sanity check failed for \"${ZIG_EXE}\"" +} + +# @FUNCTION: zig-utils_setup +# @DESCRIPTION: +# Checks if running Linux kernel version is supported by Zig. +# Populates ZIG_TARGET, ZIG_CPU, ZIG_EXE and ZIG_VER global +# variables with detected values, or, if user set them already, +# leaves as-is. +zig-utils_setup() { + # Should be first because it sets ZIG_VER which might be used + # in the future when setting ZIG_TARGET and ZIG_CPU variables + # for incompatible versions. + if [[ -z "${ZIG_EXE}" ]]; then + zig-utils_find_installation + fi + + : "${ZIG_CPU:=$(zig-utils_c_env_to_zig_cpu "${CHOST}" "${CFLAGS}")}" + if tc-is-cross-compiler; then + : "${ZIG_TARGET:=$(zig-utils_c_env_to_zig_target "${CHOST}" "${CFLAGS}")}" + else + : "${ZIG_TARGET:=native}" + fi + declare -g ZIG_CPU ZIG_TARGET + + einfo "ZIG_EXE: \"${ZIG_EXE}\"" + einfo "ZIG_VER: ${ZIG_VER}" + einfo "ZIG_TARGET: ${ZIG_TARGET}" + einfo "ZIG_CPU: ${ZIG_CPU}" +} + +# @FUNCTION: ezig +# @USAGE: [<args>...] +# @DESCRIPTION: +# Runs ZIG_EXE with supplied arguments. Dies if ZIG_EXE is not set or +# if command exits with error. Respects `nonfatal`. +# +# Always disables progress tree. By default enables ANSI escape codes +# (colors, etc.), user can set NO_COLOR environment variable to +# disable them. +# +# Note that color support also determines how compile errors will be +# printed: source code lines and reference traces are not available +# when colors are disabled. +ezig() { + # Sync description above and comments below with upstream's + # "std.io.tty.detectConfig". + debug-print-function "${FUNCNAME[0]}" "${@}" + + if [[ -z "${ZIG_EXE}" ]] ; then + die "${FUNCNAME[0]}: ZIG_EXE is not set. Was 'zig-utils_setup' called before using ezig?" + fi + + # Progress tree is helpful indicator in TTY, but unfortunately + # they make Portage logs harder to read in plaintext. + # + # We don't have global toggle for all Zig commands to disable + # progress tree, however we can emulate this using 2 steps. + + # Disable progress tree and colors. Errors are now less detailed. + local -x TERM=dumb + # Re-enable colors. Errors are now yet again detailed for reading. + local -x CLICOLOR_FORCE=1 + # User's NO_COLOR has more priority and can disable colors again. + "${ZIG_EXE}" "${@}" || die -n "Failed to run command: ${ZIG_EXE} ${@}" +} +fi diff --git a/eclass/zig.eclass b/eclass/zig.eclass new file mode 100644 index 000000000000..2a0178e66d71 --- /dev/null +++ b/eclass/zig.eclass @@ -0,0 +1,559 @@ +# Copyright 2024 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: zig.eclass +# @MAINTAINER: +# Eric Joldasov <bratishkaerik@landless-city.net> +# @AUTHOR: +# Alfred Wingate <parona@protonmail.com> +# Violet Purcell <vimproved@inventati.org> +# Eric Joldasov <bratishkaerik@landless-city.net> +# @SUPPORTED_EAPIS: 8 +# @PROVIDES: zig-utils +# @BLURB: Functions for working with ZBS (Zig Build System) +# @DESCRIPTION: +# Functions for working with Zig build system and package manager. +# Supports Zig 0.13+. Exports default functions for convenience. +# +# Note that zig.eclass is mostly tailored for projects that: +# 1) Install something in build.zig steps: "artifacts" (executable, +# libraries, objects), source codes, assets, tests, scripts etc. But +# many authors also use it to write Zig "modules", build logic +# and/or bindings/wrappers for C/C++ libraries. They install nothing +# and are only used at build-time, so it's unneccessary and mostly +# useless to make ebuilds for them. +# 2) Have required `target`, `cpu` and optional `optimize` options in +# build.zig that accept standard Zig-style target and optimize mode. +# They are usually created by calling `b.standardTargetOptions` and +# `b.standardOptimizeOption` functions. +# +# For end-user executables, usually it's recommended to patch to call +# these options and upstream it, but in some cases authors have good +# reasons to not have them, f.e. if it is built only for WASM +# platform with ReleaseSmall, and is not intended to run in /usr/bin/. +# In this case, declare dummy options using `b.option` and ignore +# their values, or else eclass wouldn't work. +# +# Another case is when upstream has `target` option but it has +# custom format and does not accept usual Zig targets, but rather +# something specific to the project like "linux-baseline-lts", or +# combine CPU and target in one option. +# In this case, it's best to rename that option to something like +# `target-custom`, then declare `target` option and make converter +# from one value to other. +# +# For non-executable binaries like C libraries, objects etc. our +# policy is stricter, all 3 options are required and should not +# be ignored, with no exceptions. + +if [[ -z ${_ZIG_ECLASS} ]]; then +_ZIG_ECLASS=1 + +case ${EAPI} in + 8) ;; + *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; +esac + +inherit multiprocessing zig-utils + +# @ECLASS_VARIABLE: ZIG_OPTIONAL +# @PRE_INHERIT +# @DEFAULT_UNSET +# @DESCRIPTION: +# If set to a non-empty value, all logic in zig-utils and +# zig eclasses will be considered optional. No dependencies +# will be added and no phase functions will be exported. +# +# For zig.eclass users: +# You need to add Zig and pkgconfig dependencies in your BDEPEND, set +# QA_FLAGS_IGNORED and call all phase functions manually. If you want +# to use "ezig build" directly, call "zig_pkg_setup" before it. +# +# For zig-utils.eclass users: see documentation in +# zig-utils.eclass instead. +if [[ ! ${ZIG_OPTIONAL} ]]; then + BDEPEND="virtual/pkgconfig" + + # See https://github.com/ziglang/zig/issues/3382 + # Zig Build System does not support CFLAGS/LDFLAGS/etc. + QA_FLAGS_IGNORED=".*" +fi + +# @ECLASS_VARIABLE: ZBS_DEPENDENCIES +# @PRE_INHERIT +# @DEFAULT_UNSET +# @DESCRIPTION: +# Bash associative array with all tarballs that will be fetched by +# "ezig fetch" in zig_src_unpack phase. Value is URL where +# tarball is located, key is name under which it would be downloaded +# and renamed. So generally it has effect of "value -> key". +# +# Note: if Zig Build System dependency can't be represented in SRC_URI +# (like direct Git commit URIs), you should do the following +# (zig-ebuilder does archiving automatically for you): +# 1. Archive each folder with dependency content in some tarball, +# so f.e. if you have 2 Git dependencies, create 2 tarballs. +# 2. Archive all previous tarballs into one combined tarball (also +# called tarball-tarball from now on), no subdirs, so that eclass +# can firstly unpack this tarball with "unpack", +# and secondly unpack its content with "zig fetch". +# 3. (zig-ebuilder can't do this) Host this tarball somewhere +# and put URL of this tarball in SRC_URI, and archives in +# ZBS_DEPENDENCIES, keys must be names of archives, values empty. +# +# Example: +# @CODE +# declare -r -A ZBS_DEPENDENCIES=( +# [tarball_a-<long-hash>.tar.gz]='URL_A' +# [tarball_b-<long-hash>.tar.gz]='URL_B' +# +# # If there are Git dependencies: +# [git_c-<long-hash>.tar.gz]='' +# # Tarball-tarball should contain inside above tarball flatly. +# ) +# @CODE + +# @ECLASS_VARIABLE: ZBS_DEPENDENCIES_SRC_URI +# @OUTPUT_VARIABLE +# @DEFAULT_UNSET +# @DESCRIPTION: +# Content of ZBS_DEPENDENCIES converted at inherit-time, to be used in +# SRC_URI. Note that elements with empty keys will be skipped. +# Example: +# @CODE +# SRC_URI=" +# <URL to project sources, patches, non-Zig resources etc.> +# +# # If there are Git dependencies: +# # <URL to tarball-tarball> +# +# ${ZBS_DEPENDENCIES_SRC_URI} +# " +# @CODE + +# @FUNCTION: _zig_set_zbs_uris +# @INTERNAL +# @DESCRIPTION: +# Sets ZBS_DEPENDENCIES_SRC_URI variable based on ZBS_DEPENDENCIES. +_zig_set_zbs_uris() { + # Thanks to Alfred Wingate "parona" for inspiration here: + # https://gitlab.com/Parona/parona-overlay/-/blob/874dcfe03116574a33ed51f469cc993e98db1fa2/eclass/zig.eclass + + ZBS_DEPENDENCIES_SRC_URI= + + local dependency + for dependency in "${!ZBS_DEPENDENCIES[@]}"; do + local uri="${ZBS_DEPENDENCIES[${dependency}]}" + if [[ -n "${uri}" ]]; then + ZBS_DEPENDENCIES_SRC_URI+=" ${uri} -> ${dependency}" + fi + done +} +_zig_set_zbs_uris + +# @ECLASS_VARIABLE: my_zbs_args +# @DESCRIPTION: +# Bash array with ebuild-specified arguments to pass to the +# "zig build" after "src_configure". +# It's appended to the ZBS_ARGS during "src_configure". Note: if you +# need to override default optimize mode of this eclass (ReleaseSafe) +# with your default, please use "--release=small" etc. syntax so that +# user can still override it in ZBS_ARGS_EXTRA. +# +# Example: +# @CODE +# src_configure() { +# local my_zbs_args=( +# -Dpie=true +# ) +# +# zig_src_configure +# } +# @CODE +: "${my_zbs_args:=}" + +# @ECLASS_VARIABLE: ZBS_ARGS_EXTRA +# @USER_VARIABLE +# @DESCRIPTION: +# Bash string with user-specified arguments to pass to the "zig build" +# after "src_configure". +# It's appended to the ZBS_ARGS during "zig_src_configure". +# +# If this does not have amount of jobs, eclass will try to take amount +# of jobs from MAKEOPTS, and if it also does not have them, it will +# default to $(nproc). +# +# Example: +# @CODE +# ZBS_ARGS_EXTRA="-j8 --release=small" +# @CODE +: "${ZBS_ARGS_EXTRA:=}" + +# @ECLASS_VARIABLE: ZBS_VERBOSE +# @USER_VARIABLE +# @DESCRIPTION: +# If enabled, eclass will add "--summary all --verbose" options to +# "ezig build", so that it prints every command before executing, +# and summarry tree at the end of step. If not, will do nothing. +# Enabled by default. Set to OFF to disable these verbose messages. +# +# Note: this variable does not control other options starting with +# "--verbose-", such as "--verbose-link" or "--verbose-cimport". If +# you need them, add them manually to ZBS_ARGS_EXTRA. +: "${ZBS_VERBOSE:=ON}" + +# @ECLASS_VARIABLE: BUILD_DIR +# @DEFAULT_UNSET +# @DESCRIPTION: +# Directory where all "ezig build" calls will be proceeded. +# Defaults to "${WORKDIR}/${P}-build" if not set. +: "${BUILD_DIR:=${WORKDIR}/${P}-build}" + +# @ECLASS_VARIABLE: ZBS_ECLASS_DIR +# @DESCRIPTION: +# Directory where various files used by this eclass are stored. +# They can be supplied by the ebuild or by eclass. +# Currently, it's used only for Zig packages, which are stored in "p/" +# subdirectory. +# Defaults to "${WORKDIR}/zig-eclass" if not set. +# Should be set before calling "zig_src_unpack" or +# "zig_live_fetch". +: "${ZBS_ECLASS_DIR:=${WORKDIR}/zig-eclass}" + +# @FUNCTION: zig_get_jobs +# @DESCRIPTION: +# Returns number of jobs from ZBS_ARGS_EXTRA or MAKEOPTS. +# If there is none, defaults to number of available processing units. +zig_get_jobs() { + local all_args="${MAKEOPTS} ${ZBS_ARGS_EXTRA}" + local default_jobs="$(get_nproc)" + local jobs="$(makeopts_jobs "${all_args}" "${default_jobs}")" + + if [[ "${jobs}" == "0" ]]; then + # Zig build system does not allow "-j0", and does not have + # option for unlimited parallelism. Pass our default number + # of jobs here. + echo "${default_jobs}" + else + echo "${jobs}" + fi +} + +# @FUNCTION: zig_init_base_args +# @DESCRIPTION: +# Stores basic args for future "ezig build" calls in ZBS_ARGS_BASE. +# Package manager option is managed by "zig_src_prepare", +# ebuild and user options are added by "zig_src_configure". +# +# This function is used by "zig_pkg_setup", and it is neccessary +# that args are available as early as possible, so that ebuilds +# could use them in steps like "src_unpack" if neccessary, while +# still having verbosity and amount of jobs from user respected. +# +# +# TODO: currently this function enables "--search-prefix" (1) and +# "--sysroot" (2) only when cross-compiling, should be fixed to +# unconditionally enabling it. +# +# For solving (1) this patch should be reworked and upstreamed: +# https://paste.sr.ht/~bratishkaerik/2ddffe2bf0f8f9d6dfb60403c2e9560334edaa88 +# +# (2) +# "--sysroot" should be passed together with "--search-prefix" above, +# if we pass only "--sysroot" it gives these errors: +# @CODE +# error: unable to find dynamic system library 'zstd' using strategy 'paths_first'. searched paths: none +# @CODE +zig_init_base_args() { + [[ "${ZBS_ARGS_BASE}" ]] && return + + # Sync with the output format of `zig libc`. + # TODO maybe add to upstream to use ZON format instead... + # Will also help "https://github.com/ziglang/zig/issues/20327", + # and hopefully will respect our settings too. + cat <<- _EOF_ > "${T}/zig_libc.txt" || die "Failed to provide Zig libc info" + # Note: they are not prepended by "--sysroot" value, + # so repeat it here. + # Also, no quotes here, they are interpreted verbatim. + include_dir=${ESYSROOT}/usr/include/ + sys_include_dir=${ESYSROOT}/usr/include/ + crt_dir=${ESYSROOT}/usr/$(get_libdir)/ + # Windows with MSVC only. + msvc_lib_dir= + # Windows with MSVC only. + kernel32_lib_dir= + # Haiku only. + gcc_dir= + _EOF_ + + declare -g -a ZBS_ARGS_BASE=( + -j$(zig_get_jobs) + + -Dtarget="${ZIG_TARGET}" + -Dcpu="${ZIG_CPU}" + --release=safe + + --prefix-exe-dir bin/ + --prefix-lib-dir "$(get_libdir)/" + --prefix-include-dir include/ + + # Should be relative path to make other calls easier, + # so remove leading slash here. + --prefix "${EPREFIX:+${EPREFIX#/}/}usr/" + + --libc "${T}/zig_libc.txt" + ) + if [[ "${ZBS_VERBOSE}" != OFF ]]; then + ZBS_ARGS_BASE+=( --summary all --verbose ) + fi + + if tc-is-cross-compiler; then + ZBS_ARGS_BASE+=( + --search-prefix "${ESYSROOT}/usr/" + --sysroot "${ESYSROOT}/" + ) + fi +} + +# @FUNCTION: zig_pkg_setup +# @DESCRIPTION: +# Sets up environmental variables for Zig toolchain +# and basic args for Zig Build System. +zig_pkg_setup() { + [[ "${MERGE_TYPE}" != binary ]] || return 0 + + zig-utils_setup + zig_init_base_args + + mkdir "${T}/zig-cache/" || die + + # Environment variables set by this eclass. + + # Used by Zig Build System to find `pkg-config`. + # UPSTREAM Used only by 9999 for now, should land in future + # 0.14 release. + export PKG_CONFIG="${PKG_CONFIG:-"$(tc-getPKG_CONFIG)"}" + # Used by whole Zig toolchain (most of the sub-commands) + # to find local and global cache directories. + export ZIG_LOCAL_CACHE_DIR="${T}/zig-cache/local/" + export ZIG_GLOBAL_CACHE_DIR="${T}/zig-cache/global/" +} + +# @FUNCTION: zig_live_fetch +# @USAGE: [<args>...] +# @DESCRIPTION: +# Fetches packages, if they exist, to the "ZBS_ECLASS_DIR/p/". +# Adds build file path to ZBS_BASE_ARGS. +# If you have some lazy dependency which is not triggered in default +# configuration, pass options like you would pass them for regular +# "ezig build". Try to cover all of them before "src_configure". +# **Note**: this function will be deprecated once/if +# https://github.com/ziglang/zig/pull/19975 lands. +# +# Example: +# @CODE +# src_unpack() { +# # If there are no lazy dependency: +# zig_live_fetch +# +# # If there are lazy dependencies that can be triggered together: +# zig_live_fetch -Denable-wayland -Denable-xwayland +# +# # If there are 2 lazy dependencies that can't be triggered +# # together in one call because they conflict: +# zig_live_fetch -Dmain-backend=opengl +# zig_live_fetch -Dmain-backend=vulkan +# } +# @CODE +zig_live_fetch() { + # This function will likely be called in src_unpack, + # before [zig_]src_prepare, so this directory might not + # exist yet. + mkdir -p "${BUILD_DIR}" > /dev/null || die + pushd "${BUILD_DIR}" > /dev/null || die + + ZBS_ARGS_BASE+=( --build-file "${S}/build.zig" ) + + local args=( + "${ZBS_ARGS_BASE[@]}" + + --global-cache-dir "${ZBS_ECLASS_DIR}/" + + # Function arguments + "${@}" + ) + + einfo "ZBS: live-fetching with:" + einfo "${args[@]}" + ezig build --help "${args[@]}" > /dev/null + + popd > /dev/null || die +} + +# @FUNCTION: zig_src_unpack +# @DESCRIPTION: +# Unpacks every archive in SRC_URI and ZBS_DEPENDENCIES, +# in that order. Adds build file path to ZBS_BASE_ARGS. +zig_src_unpack() { + # Thanks to Alfred Wingate "parona" for inspiration here: + # https://gitlab.com/Parona/parona-overlay/-/blob/874dcfe03116574a33ed51f469cc993e98db1fa2/eclass/zig.eclass + + ZBS_ARGS_BASE+=( --build-file "${S}/build.zig" ) + + if [[ "${#ZBS_DEPENDENCIES_SRC_URI}" -eq 0 ]]; then + default_src_unpack + return + fi + + local zig_deps=() + for dependency in "${!ZBS_DEPENDENCIES[@]}"; do + zig_deps+=("${dependency}") + done + + # First unpack non-Zig dependencies, so that + # tarball with all Git dependencies tarballs is unpacked early. + local dist + for dist in ${A}; do + if ! has "${dist}" "${zig_deps[@]}"; then + unpack "${dist}" + fi + done + + # Now unpack all Zig dependencies, including those that are + # now unpacked from tarball-tarball. + local zig_dep + for zig_dep in "${zig_deps[@]}"; do + # Hide now-spammy hash from stdout + ezig fetch --global-cache-dir "${ZBS_ECLASS_DIR}/" \ + "${DISTDIR}/${zig_dep}" > /dev/null + done + einfo "ZBS: ${#zig_deps[@]} dependencies unpacked" +} + +# @FUNCTION: zig_src_prepare +# @DESCRIPTION: +# Calls default "src_prepare" function, creates BUILD_DIR directory +# and enables system mode (by adding to ZBS_BASE_ARGS). +# +# System mode is toggled here and not in "src_unpack" because they +# could have been fetched by "live_fetch" in live ebuilds instead. +zig_src_prepare() { + default_src_prepare + + mkdir -p "${BUILD_DIR}" || die + einfo "BUILD_DIR: \"${BUILD_DIR}\"" + + local system_dir="${ZBS_ECLASS_DIR}/p/" + mkdir -p "${system_dir}" || die + ZBS_ARGS_BASE+=( + # Disable network access after ensuring all dependencies + # are unpacked (by "src_unpack" or "live_fetch") + --system "${system_dir}" + ) +} + +# @FUNCTION: zig_src_configure +# @DESCRIPTION: +# Creates ZBS_ARGS array which can be used in all future phases, +# by combining ZBS_ARGS_BASE set previously, my_zbs_args from ebuild, +# and ZBS_ARGS_EXTRA by user, in this order. +# +# Specific flags currently only add support for the cross-compilation. +# They are likely to be extended in the future. +zig_src_configure() { + # Handle quoted whitespace. + eval "local -a ZBS_ARGS_EXTRA=( ${ZBS_ARGS_EXTRA} )" + + # Since most arguments in array are also cached by ZBS, we + # want to reuse array as much as possible, so prevent + # modification of it. + declare -g -a -r ZBS_ARGS=( + # Base arguments from pkg_setup/setup_base_args + "${ZBS_ARGS_BASE[@]}" + + # Arguments from ebuild + "${my_zbs_args[@]}" + + # Arguments from user + "${ZBS_ARGS_EXTRA[@]}" + ) + + einfo "ZBS: configured with:" + einfo "${ZBS_ARGS[@]}" +} + +# @FUNCTION: zig_src_compile +# @USAGE: [<args>...] +# @DESCRIPTION: +# Calls "ezig build" with previously set ZBS_ARGS. +# Args passed to this function will be passed after ZBS_ARGS. +zig_src_compile() { + pushd "${BUILD_DIR}" > /dev/null || die + + local args=( "${ZBS_ARGS[@]}" "${@}" ) + einfo "ZBS: compiling with: ${args[@]}" + nonfatal ezig build "${args[@]}" || die "ZBS: compilation failed" + + popd > /dev/null || die +} + +# @FUNCTION: zig_src_test +# @USAGE: [<args>...] +# @DESCRIPTION: +# If "test" step exist, calls "ezig build test" with previously set +# ZBS_ARGS. +# Args passed to this function will be passed after ZBS_ARGS. +# Note: currently step detection might give false positives in +# very rare cases, it will be improved in the future. +zig_src_test() { + pushd "${BUILD_DIR}" > /dev/null || die + + local args=( "${ZBS_ARGS[@]}" "${@}" ) + + # UPSTREAM std.testing.tmpDir and a lot of other functions + # do not respect --cache-dir or ZIG_LOCAL_CACHE_DIR: + # https://github.com/ziglang/zig/issues/19874 + mkdir ".zig-cache/" || die + + # UPSTREAM Currently, step name can have any characters in it, + # including whitespaces, so splitting names and descriptions + # by whitespaces is not enough for some cases. + # We probably need something like "--list-steps names_only". + # In practice, almost nobody sets such names. + # Ignore failures like rare random "error.BrokenPipe" here. + # If they are real, they would appear in "ezig build test" anyway. + if grep -q '^[ ]*test[ ]' < <( + nonfatal ezig build --list-steps "${args[@]}" + ); then + einfo "ZBS: testing with: ${args[@]}" + nonfatal ezig build test "${args[@]}" || + die "ZBS: tests failed" + else + einfo "Test step not found, skipping." + fi + + popd > /dev/null || die +} + +# @FUNCTION: zig_src_install +# @USAGE: [<args>...] +# @DESCRIPTION: +# Calls "ezig build" with DESTDIR and previously set ZBS_ARGS. +# Args passed to this function will be passed after ZBS_ARGS. +# Also installs documentation via "einstalldocs". +zig_src_install() { + pushd "${BUILD_DIR}" > /dev/null || die + local args=( "${ZBS_ARGS[@]}" "${@}" ) + einfo "ZBS: installing with: ${args[@]}" + DESTDIR="${D}" nonfatal ezig build "${args[@]}" || + die "ZBS: installing failed" + popd > /dev/null || die + + einstalldocs +} + +fi + +if [[ ! ${ZIG_OPTIONAL} ]]; then + EXPORT_FUNCTIONS pkg_setup src_unpack src_prepare src_configure src_compile src_test src_install +fi |