diff options
author | 2018-11-02 07:20:57 +0000 | |
---|---|---|
committer | 2018-11-02 07:24:12 +0000 | |
commit | 45a6d830fb44980db4f9c03b7285d3a19fde42f5 (patch) | |
tree | 34bc6a6fc56b6cd17df5327004d6f5ec632201f5 /eclass | |
parent | Kernel overlay init commit (diff) | |
download | kernel-45a6d830fb44980db4f9c03b7285d3a19fde42f5.tar.gz kernel-45a6d830fb44980db4f9c03b7285d3a19fde42f5.tar.bz2 kernel-45a6d830fb44980db4f9c03b7285d3a19fde42f5.zip |
Initial commit of kernel related packages
Signed-off-by: Alice Ferrazzi <alicef@gentoo.org>
Diffstat (limited to 'eclass')
-rw-r--r-- | eclass/kernel-2.eclass | 1637 | ||||
-rw-r--r-- | eclass/linux-info.eclass | 966 | ||||
-rw-r--r-- | eclass/linux-mod.eclass | 758 |
3 files changed, 3361 insertions, 0 deletions
diff --git a/eclass/kernel-2.eclass b/eclass/kernel-2.eclass new file mode 100644 index 0000000..8e595d5 --- /dev/null +++ b/eclass/kernel-2.eclass @@ -0,0 +1,1637 @@ +# Copyright 1999-2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: kernel-2.eclass +# @MAINTAINER: +# Gentoo Kernel project <kernel@gentoo.org> +# @AUTHOR: +# John Mylchreest <johnm@gentoo.org> +# Mike Pagano <mpagano@gentoo.org> +# <so many, many others, please add yourself> +# @SUPPORTED_EAPIS: 2 3 4 5 6 +# @BLURB: Eclass for kernel packages +# @DESCRIPTION: +# This is the kernel.eclass rewrite for a clean base regarding the 2.6 +# series of kernel with back-compatibility for 2.4 +# Please direct your bugs to the current eclass maintainer :) +# added functionality: +# unipatch - a flexible, singular method to extract, add and remove patches. + +# @ECLASS-VARIABLE: K_USEPV +# @DEFAULT_UNSET +# @DESCRIPTION: +# When setting the EXTRAVERSION variable, it should +# add PV to the end. +# this is useful for things like wolk. IE: +# EXTRAVERSION would be something like : -wolk-4.19-r1 + +# @ECLASS-VARIABLE: K_NOSETEXTRAVERSION +# @DEFAULT_UNSET +# @DESCRIPTION: +# if this is set then EXTRAVERSION will not be +# automatically set within the kernel Makefile + +# @ECLASS-VARIABLE: K_NOUSENAME +# @DEFAULT_UNSET +# @DESCRIPTION: +# if this is set then EXTRAVERSION will not include the +# first part of ${PN} in EXTRAVERSION + +# @ECLASS-VARIABLE: K_NOUSEPR +# @DEFAULT_UNSET +# @DESCRIPTION: +# if this is set then EXTRAVERSION will not include the +# anything based on ${PR}. + +# @ECLASS-VARIABLE: K_PREPATCHED +# @DEFAULT_UNSET +# @DESCRIPTION: +# if the patchset is prepatched (ie: mm-sources, +# ck-sources, ac-sources) it will use PR (ie: -r5) as +# the patchset version for +# and not use it as a true package revision + +# @ECLASS-VARIABLE: K_EXTRAEINFO +# @DEFAULT_UNSET +# @DESCRIPTION: +# this is a new-line seperated list of einfo displays in +# postinst and can be used to carry additional postinst +# messages + +# @ECLASS-VARIABLE: K_EXTRAELOG +# @DEFAULT_UNSET +# @DESCRIPTION: +# same as K_EXTRAEINFO except using elog instead of einfo + +# @ECLASS-VARIABLE: K_EXTRAEWARN +# @DEFAULT_UNSET +# @DESCRIPTION: +# same as K_EXTRAEINFO except using ewarn instead of einfo + +# @ECLASS-VARIABLE: K_SYMLINK +# @DEFAULT_UNSET +# @DESCRIPTION: +# if this is set, then forcably create symlink anyway + +# @ECLASS-VARIABLE: K_BASE_VER +# @DEFAULT_UNSET +# @DESCRIPTION: +# for git-sources, declare the base version this patch is +# based off of. + +# @ECLASS-VARIABLE: K_DEFCONFIG +# @DEFAULT_UNSET +# @DESCRIPTION: +# Allow specifying a different defconfig target. +# If length zero, defaults to "defconfig". + +# @ECLASS-VARIABLE: K_WANT_GENPATCHES +# @DEFAULT_UNSET +# @DESCRIPTION: +# Apply genpatches to kernel source. Provide any +# combination of "base", "extras" or "experimental". + +# @ECLASS-VARIABLE: K_EXP_GENPATCHES_PULL +# @DEFAULT_UNSET +# @DESCRIPTION: +# If set, we pull "experimental" regardless of the USE FLAG +# but expect the ebuild maintainer to use K_EXP_GENPATCHES_LIST. + +# @ECLASS-VARIABLE: K_EXP_GENPATCHES_NOUSE +# @DEFAULT_UNSET +# @DESCRIPTION: +# If set, no USE flag will be provided for "experimental"; +# as a result the user cannot choose to apply those patches. + +# @ECLASS-VARIABLE: K_EXP_GENPATCHES_LIST +# @DEFAULT_UNSET +# @DESCRIPTION: +# A list of patches to pick from "experimental" to apply when +# the USE flag is unset and K_EXP_GENPATCHES_PULL is set. + +# @ECLASS-VARIABLE: K_FROM_GIT +# @DEFAULT_UNSET +# @DESCRIPTION: +# If set, this variable signals that the kernel sources derives +# from a git tree and special handling will be applied so that +# any patches that are applied will actually apply. + +# @ECLASS-VARIABLE: K_GENPATCHES_VER +# @DEFAULT_UNSET +# @DESCRIPTION: +# The version of the genpatches tarball(s) to apply. +# A value of "5" would apply genpatches-2.6.12-5 to +# my-sources-2.6.12.ebuild + +# @ECLASS-VARIABLE: K_SECURITY_UNSUPPORTED +# @DEFAULT_UNSET +# @DESCRIPTION: +# If set, this kernel is unsupported by Gentoo Security +# to the current eclass maintainer :) + +# @ECLASS-VARIABLE: K_DEBLOB_AVAILABLE +# @DEFAULT_UNSET +# @DESCRIPTION: +# A value of "0" will disable all of the optional deblob +# code. If empty, will be set to "1" if deblobbing is +# possible. Test ONLY for "1". + +# @ECLASS-VARIABLE: K_DEBLOB_TAG +# @DEFAULT_UNSET +# @DESCRIPTION: +# This will be the version of deblob script. It's a upstream SVN tag +# such asw -gnu or -gnu1. + +# @ECLASS-VARIABLE: K_PREDEBLOBBED +# @DEFAULT_UNSET +# @DESCRIPTION: +# This kernel was already deblobbed elsewhere. +# If false, either optional deblobbing will be available +# or the license will note the inclusion of linux-firmware code. + +# @ECLASS-VARIABLE: K_LONGTERM +# @DEFAULT_UNSET +# @DESCRIPTION: +# If set, the eclass will search for the kernel source +# in the long term directories on the upstream servers +# as the location has been changed by upstream + +# @ECLASS-VARIABLE: H_SUPPORTEDARCH +# @DEFAULT_UNSET +# @DESCRIPTION: +# this should be a space separated list of ARCH's which +# can be supported by the headers ebuild + +# @ECLASS-VARIABLE: UNIPATCH_LIST +# @DEFAULT_UNSET +# @DESCRIPTION: +# space delimetered list of patches to be applied to the kernel + +# @ECLASS-VARIABLE: UNIPATCH_EXCLUDE +# @DEFAULT_UNSET +# @DESCRIPTION: +# An addition var to support exlusion based completely +# on "<passedstring>*" and not "<passedno#>_*" +# this should _NOT_ be used from the ebuild as this is +# reserved for end users passing excludes from the cli + +# @ECLASS-VARIABLE: UNIPATCH_DOCS +# @DEFAULT_UNSET +# @DESCRIPTION: +# space delimemeted list of docs to be installed to +# the doc dir + +# @ECLASS-VARIABLE: UNIPATCH_STRICTORDER +# @DEFAULT_UNSET +# @DESCRIPTION: +# if this is set places patches into directories of +# order, so they are applied in the order passed +# Changing any other variable in this eclass is not supported; you can request +# for additional variables to be added by contacting the current maintainer. +# If you do change them, there is a chance that we will not fix resulting bugs; +# that of course does not mean we're not willing to help. + +PYTHON_COMPAT=( python{2_6,2_7} ) + +inherit toolchain-funcs python-any-r1 +[[ ${EAPI:-0} == [012345] ]] && inherit epatch +[[ ${EAPI:-0} == [0123456] ]] && inherit estack eapi7-ver +case ${EAPI:-0} in + 2|3|4|5|6) + EXPORT_FUNCTIONS src_{unpack,prepare,compile,install,test} \ + pkg_{setup,preinst,postinst,postrm} ;; + *) die "${ECLASS}: EAPI ${EAPI} not supported" ;; +esac + +# Added by Daniel Ostrow <dostrow@gentoo.org> +# This is an ugly hack to get around an issue with a 32-bit userland on ppc64. +# I will remove it when I come up with something more reasonable. +[[ ${PROFILE_ARCH} == "ppc64" ]] && CHOST="powerpc64-${CHOST#*-}" + +export CTARGET=${CTARGET:-${CHOST}} +if [[ ${CTARGET} == ${CHOST} && ${CATEGORY/cross-} != ${CATEGORY} ]]; then + export CTARGET=${CATEGORY/cross-} +fi + +HOMEPAGE="https://www.kernel.org/ https://www.gentoo.org/ ${HOMEPAGE}" +: ${LICENSE:="GPL-2"} + +# This is the latest KV_PATCH of the deblob tool available from the +# libre-sources upstream. If you bump this, you MUST regenerate the Manifests +# for ALL kernel-2 consumer packages where deblob is available. +: ${DEBLOB_MAX_VERSION:=38} + +# No need to run scanelf/strip on kernel sources/headers (bug #134453). +RESTRICT="binchecks strip" + +# set LINUX_HOSTCFLAGS if not already set +: ${LINUX_HOSTCFLAGS:="-Wall -Wstrict-prototypes -Os -fomit-frame-pointer -I${S}/include"} + + +# @FUNCTION: debug-print-kernel2-variables +# @USAGE: +# @DESCRIPTION: +# this function exists only to help debug kernel-2.eclass +# if you are adding new functionality in, put a call to it +# at the start of src_unpack, or during SRC_URI/dep generation. + +debug-print-kernel2-variables() { + for v in PVR CKV OKV KV KV_FULL KV_MAJOR KV_MINOR KV_PATCH RELEASETYPE \ + RELEASE UNIPATCH_LIST_DEFAULT UNIPATCH_LIST_GENPATCHES \ + UNIPATCH_LIST S KERNEL_URI K_WANT_GENPATCHES ; do + debug-print "${v}: ${!v}" + done +} + +# @FUNCTION: handle_genpatches +# @USAGE: [--set-unipatch-list] +# @DESCRIPTION: +# add genpatches to list of patches to apply if wanted + +handle_genpatches() { + local tarball want_unipatch_list + [[ -z ${K_WANT_GENPATCHES} || -z ${K_GENPATCHES_VER} ]] && return 1 + + if [[ -n ${1} ]]; then + # set UNIPATCH_LIST_GENPATCHES only on explicit request + # since that requires 'use' call which can be used only in phase + # functions, while the function is also called in global scope + if [[ ${1} == --set-unipatch-list ]]; then + want_unipatch_list=1 + else + die "Usage: ${FUNCNAME} [--set-unipatch-list]" + fi + fi + + debug-print "Inside handle_genpatches" + local OKV_ARRAY + IFS="." read -r -a OKV_ARRAY <<<"${OKV}" + + # for > 3.0 kernels, handle genpatches tarball name + # genpatches for 3.0 and 3.0.1 might be named + # genpatches-3.0-1.base.tar.xz and genpatches-3.0-2.base.tar.xz + # respectively. Handle this. + + for i in ${K_WANT_GENPATCHES} ; do + if [[ ${KV_MAJOR} -ge 3 ]]; then + if [[ ${#OKV_ARRAY[@]} -ge 3 ]]; then + tarball="genpatches-${KV_MAJOR}.${KV_MINOR}-${K_GENPATCHES_VER}.${i}.tar.xz" + else + tarball="genpatches-${KV_MAJOR}.${KV_PATCH}-${K_GENPATCHES_VER}.${i}.tar.xz" + fi + else + tarball="genpatches-${OKV}-${K_GENPATCHES_VER}.${i}.tar.xz" + fi + + local use_cond_start="" use_cond_end="" + + if [[ "${i}" == "experimental" && -z ${K_EXP_GENPATCHES_PULL} && -z ${K_EXP_GENPATCHES_NOUSE} ]] ; then + use_cond_start="experimental? ( " + use_cond_end=" )" + + if [[ -n ${want_unipatch_list} ]] && use experimental ; then + UNIPATCH_LIST_GENPATCHES+=" ${DISTDIR}/${tarball}" + debug-print "genpatches tarball: $tarball" + fi + elif [[ -n ${want_unipatch_list} ]]; then + UNIPATCH_LIST_GENPATCHES+=" ${DISTDIR}/${tarball}" + debug-print "genpatches tarball: $tarball" + fi + GENPATCHES_URI+=" ${use_cond_start}mirror://gentoo/${tarball}${use_cond_end}" + done +} + +# @FUNCTION: detect_version +# @USAGE: +# @DESCRIPTION: +# this function will detect and set +# - OKV: Original Kernel Version (2.6.0/2.6.0-test11) +# - KV: Kernel Version (2.6.0-gentoo/2.6.0-test11-gentoo-r1) +# - EXTRAVERSION: The additional version appended to OKV (-gentoo/-gentoo-r1) +detect_version() { + + # We've already run, so nothing to do here. + [[ -n ${KV_FULL} ]] && return 0 + + # CKV is used as a comparison kernel version, which is used when + # PV doesnt reflect the genuine kernel version. + # this gets set to the portage style versioning. ie: + # CKV=2.6.11_rc4 + CKV=${CKV:-${PV}} + OKV=${OKV:-${CKV}} + OKV=${OKV/_beta/-test} + OKV=${OKV/_rc/-rc} + OKV=${OKV/-r*} + OKV=${OKV/_p*} + + KV_MAJOR=$(ver_cut 1 ${OKV}) + # handle if OKV is X.Y or X.Y.Z (e.g. 3.0 or 3.0.1) + local OKV_ARRAY + IFS="." read -r -a OKV_ARRAY <<<"${OKV}" + + # if KV_MAJOR >= 3, then we have no more KV_MINOR + #if [[ ${KV_MAJOR} -lt 3 ]]; then + if [[ ${#OKV_ARRAY[@]} -ge 3 ]]; then + KV_MINOR=$(ver_cut 2 ${OKV}) + KV_PATCH=$(ver_cut 3 ${OKV}) + if [[ ${KV_MAJOR}${KV_MINOR}${KV_PATCH} -ge 269 ]]; then + KV_EXTRA=$(ver_cut 4- ${OKV}) + KV_EXTRA=${KV_EXTRA/[-_]*} + else + KV_PATCH=$(ver_cut 3- ${OKV}) + fi + else + KV_PATCH=$(ver_cut 2 ${OKV}) + KV_EXTRA=$(ver_cut 3- ${OKV}) + KV_EXTRA=${KV_EXTRA/[-_]*} + fi + + debug-print "KV_EXTRA is ${KV_EXTRA}" + + KV_PATCH=${KV_PATCH/[-_]*} + + local v n=0 missing + #if [[ ${KV_MAJOR} -lt 3 ]]; then + if [[ ${#OKV_ARRAY[@]} -ge 3 ]]; then + for v in CKV OKV KV_{MAJOR,MINOR,PATCH} ; do + [[ -z ${!v} ]] && n=1 && missing="${missing}${v} "; + done + else + for v in CKV OKV KV_{MAJOR,PATCH} ; do + [[ -z ${!v} ]] && n=1 && missing="${missing}${v} "; + done + fi + + [[ $n -eq 1 ]] && \ + eerror "Missing variables: ${missing}" && \ + die "Failed to extract kernel version (try explicit CKV in ebuild)!" + unset v n missing + +# if [[ ${KV_MAJOR} -ge 3 ]]; then + if [[ ${#OKV_ARRAY[@]} -lt 3 ]]; then + KV_PATCH_ARR=(${KV_PATCH//\./ }) + + # at this point 031412, Linus is putting all 3.x kernels in a + # 3.x directory, may need to revisit when 4.x is released + KERNEL_BASE_URI="mirror://kernel/linux/kernel/v${KV_MAJOR}.x" + + [[ -n "${K_LONGTERM}" ]] && + KERNEL_BASE_URI="${KERNEL_BASE_URI}/longterm/v${KV_MAJOR}.${KV_PATCH_ARR}" + else + #KERNEL_BASE_URI="mirror://kernel/linux/kernel/v${KV_MAJOR}.0" + #KERNEL_BASE_URI="mirror://kernel/linux/kernel/v${KV_MAJOR}.${KV_MINOR}" + if [[ ${KV_MAJOR} -ge 3 ]]; then + KERNEL_BASE_URI="mirror://kernel/linux/kernel/v${KV_MAJOR}.x" + else + KERNEL_BASE_URI="mirror://kernel/linux/kernel/v${KV_MAJOR}.${KV_MINOR}" + fi + + [[ -n "${K_LONGTERM}" ]] && + #KERNEL_BASE_URI="${KERNEL_BASE_URI}/longterm" + KERNEL_BASE_URI="${KERNEL_BASE_URI}/longterm/v${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}" + fi + + debug-print "KERNEL_BASE_URI is ${KERNEL_BASE_URI}" + + if [[ ${#OKV_ARRAY[@]} -ge 3 ]] && [[ ${KV_MAJOR} -ge 3 ]]; then + # handle non genpatch using sources correctly + if [[ -z ${K_WANT_GENPATCHES} && -z ${K_GENPATCHES_VER} && ${KV_PATCH} -gt 0 ]]; then + KERNEL_URI="${KERNEL_BASE_URI}/patch-${OKV}.xz" + UNIPATCH_LIST_DEFAULT="${DISTDIR}/patch-${CKV}.xz" + fi + KERNEL_URI="${KERNEL_URI} ${KERNEL_BASE_URI}/linux-${KV_MAJOR}.${KV_MINOR}.tar.xz" + else + KERNEL_URI="${KERNEL_BASE_URI}/linux-${OKV}.tar.xz" + fi + + RELEASE=${CKV/${OKV}} + RELEASE=${RELEASE/_beta} + RELEASE=${RELEASE/_rc/-rc} + RELEASE=${RELEASE/_pre/-pre} + # We cannot trivally call kernel_is here, because it calls us to detect the + # version + #kernel_is ge 2 6 && RELEASE=${RELEASE/-pre/-git} + [ $(($KV_MAJOR * 1000 + ${KV_MINOR:-0})) -ge 2006 ] && RELEASE=${RELEASE/-pre/-git} + RELEASETYPE=${RELEASE//[0-9]} + + # Now we know that RELEASE is the -rc/-git + # and RELEASETYPE is the same but with its numerics stripped + # we can work on better sorting EXTRAVERSION. + # first of all, we add the release + EXTRAVERSION="${RELEASE}" + debug-print "0 EXTRAVERSION:${EXTRAVERSION}" + [[ -n ${KV_EXTRA} ]] && [[ ${KV_MAJOR} -lt 3 ]] && EXTRAVERSION=".${KV_EXTRA}${EXTRAVERSION}" + + debug-print "1 EXTRAVERSION:${EXTRAVERSION}" + if [[ -n "${K_NOUSEPR}" ]]; then + # Don't add anything based on PR to EXTRAVERSION + debug-print "1.0 EXTRAVERSION:${EXTRAVERSION}" + elif [[ -n ${K_PREPATCHED} ]]; then + debug-print "1.1 EXTRAVERSION:${EXTRAVERSION}" + EXTRAVERSION="${EXTRAVERSION}-${PN/-*}${PR/r}" + elif [[ "${ETYPE}" = "sources" ]]; then + debug-print "1.2 EXTRAVERSION:${EXTRAVERSION}" + # For some sources we want to use the PV in the extra version + # This is because upstream releases with a completely different + # versioning scheme. + case ${PN/-*} in + wolk) K_USEPV=1;; + vserver) K_USEPV=1;; + esac + + [[ -z "${K_NOUSENAME}" ]] && EXTRAVERSION="${EXTRAVERSION}-${PN/-*}" + [[ -n "${K_USEPV}" ]] && EXTRAVERSION="${EXTRAVERSION}-${PV//_/-}" + [[ -n "${PR//r0}" ]] && EXTRAVERSION="${EXTRAVERSION}-${PR}" + fi + debug-print "2 EXTRAVERSION:${EXTRAVERSION}" + + # The only messing around which should actually effect this is for KV_EXTRA + # since this has to limit OKV to MAJ.MIN.PAT and strip EXTRA off else + # KV_FULL evaluates to MAJ.MIN.PAT.EXT.EXT after EXTRAVERSION + + if [[ -n ${KV_EXTRA} ]]; then + if [[ -n ${KV_MINOR} ]]; then + OKV="${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}" + else + OKV="${KV_MAJOR}.${KV_PATCH}" + fi + KERNEL_URI="${KERNEL_BASE_URI}/patch-${CKV}.xz + ${KERNEL_BASE_URI}/linux-${OKV}.tar.xz" + UNIPATCH_LIST_DEFAULT="${DISTDIR}/patch-${CKV}.xz" + fi + + # We need to set this using OKV, but we need to set it before we do any + # messing around with OKV based on RELEASETYPE + KV_FULL=${OKV}${EXTRAVERSION} + + # we will set this for backwards compatibility. + S="${WORKDIR}"/linux-${KV_FULL} + KV=${KV_FULL} + + # -rc-git pulls can be achieved by specifying CKV + # for example: + # CKV="2.6.11_rc3_pre2" + # will pull: + # linux-2.6.10.tar.xz & patch-2.6.11-rc3.xz & patch-2.6.11-rc3-git2.xz + + if [[ ${KV_MAJOR}${KV_MINOR} -eq 26 ]]; then + + if [[ ${RELEASETYPE} == -rc ]] || [[ ${RELEASETYPE} == -pre ]]; then + OKV="${KV_MAJOR}.${KV_MINOR}.$((${KV_PATCH} - 1))" + KERNEL_URI="${KERNEL_BASE_URI}/testing/patch-${CKV//_/-}.xz + ${KERNEL_BASE_URI}/linux-${OKV}.tar.xz" + UNIPATCH_LIST_DEFAULT="${DISTDIR}/patch-${CKV//_/-}.xz" + fi + + if [[ ${RELEASETYPE} == -git ]]; then + KERNEL_URI="${KERNEL_BASE_URI}/snapshots/patch-${OKV}${RELEASE}.xz + ${KERNEL_BASE_URI}/linux-${OKV}.tar.xz" + UNIPATCH_LIST_DEFAULT="${DISTDIR}/patch-${OKV}${RELEASE}.xz" + fi + + if [[ ${RELEASETYPE} == -rc-git ]]; then + OKV="${KV_MAJOR}.${KV_MINOR}.$((${KV_PATCH} - 1))" + KERNEL_URI="${KERNEL_BASE_URI}/snapshots/patch-${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}${RELEASE}.xz + ${KERNEL_BASE_URI}/testing/patch-${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}${RELEASE/-git*}.xz + ${KERNEL_BASE_URI}/linux-${OKV}.tar.xz" + + UNIPATCH_LIST_DEFAULT="${DISTDIR}/patch-${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}${RELEASE/-git*}.xz ${DISTDIR}/patch-${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}${RELEASE}.xz" + fi + else + KV_PATCH_ARR=(${KV_PATCH//\./ }) + + # the different majorminor versions have different patch start versions + OKV_DICT=(["2"]="${KV_MAJOR}.$((${KV_PATCH_ARR} - 1))" ["3"]="2.6.39" ["4"]="3.19") + + if [[ ${RELEASETYPE} == -rc ]] || [[ ${RELEASETYPE} == -pre ]]; then + + OKV=${K_BASE_VER:-$OKV_DICT["${KV_MAJOR}"]} + + # as of 12/5/2017, the rc patch is no longer offered as a compressed + # file, and no longer is it mirrored on kernel.org + if [[ ${KV_MAJOR} -ge 4 ]] && [[ ${KV_PATCH} -ge 12 ]]; then + KERNEL_URI="https://git.kernel.org/torvalds/p/v${KV_FULL}/v${OKV} -> patch-${KV_FULL}.patch + ${KERNEL_BASE_URI}/linux-${OKV}.tar.xz" + UNIPATCH_LIST_DEFAULT="${DISTDIR}/patch-${CKV//_/-}.patch" + else + KERNEL_URI="${KERNEL_BASE_URI}/testing/patch-${CKV//_/-}.xz + ${KERNEL_BASE_URI}/linux-${OKV}.tar.xz" + UNIPATCH_LIST_DEFAULT="${DISTDIR}/patch-${CKV//_/-}.xz" + fi + fi + + if [[ ${RELEASETYPE} == -git ]]; then + KERNEL_URI="${KERNEL_BASE_URI}/snapshots/patch-${OKV}${RELEASE}.xz + ${KERNEL_BASE_URI}/linux-${OKV}.tar.xz" + UNIPATCH_LIST_DEFAULT="${DISTDIR}/patch-${OKV}${RELEASE}.xz" + fi + + if [[ ${RELEASETYPE} == -rc-git ]]; then + OKV=${K_BASE_VER:-$OKV_DICT["${KV_MAJOR}"]} + KERNEL_URI="${KERNEL_BASE_URI}/snapshots/patch-${KV_MAJOR}.${KV_PATCH}${RELEASE}.xz + ${KERNEL_BASE_URI}/testing/patch-${KV_MAJOR}.${KV_PATCH}${RELEASE/-git*}.xz + ${KERNEL_BASE_URI}/linux-${OKV}.tar.xz" + + UNIPATCH_LIST_DEFAULT="${DISTDIR}/patch-${KV_MAJOR}.${KV_PATCH}${RELEASE/-git*}.xz ${DISTDIR}/patch-${KV_MAJOR}.${KV_PATCH}${RELEASE}.xz" + fi + + + fi + + debug-print-kernel2-variables + + handle_genpatches +} + +# @FUNCTION: kernel_is +# @USAGE: <conditional version | version> +# @DESCRIPTION: +# user for comparing kernel versions +# or just identifying a version +# e.g kernel_is 2 4 +# e.g kernel_is ge 4.8.11 +# Note: duplicated in linux-info.eclass +kernel_is() { + # ALL of these should be set before we can safely continue this function. + # some of the sources have in the past had only one set. + local v n=0 + for v in OKV KV_{MAJOR,MINOR,PATCH} ; do [[ -z ${!v} ]] && n=1 ; done + [[ $n -eq 1 ]] && detect_version + unset v n + + # Now we can continue + local operator test value + + case ${1#-} in + lt) operator="-lt"; shift;; + gt) operator="-gt"; shift;; + le) operator="-le"; shift;; + ge) operator="-ge"; shift;; + eq) operator="-eq"; shift;; + *) operator="-eq";; + esac + [[ $# -gt 3 ]] && die "Error in kernel-2_kernel_is(): too many parameters" + + : $(( test = (KV_MAJOR << 16) + (KV_MINOR << 8) + KV_PATCH )) + : $(( value = (${1:-${KV_MAJOR}} << 16) + (${2:-${KV_MINOR}} << 8) + ${3:-${KV_PATCH}} )) + [ ${test} ${operator} ${value} ] +} + +# @FUNCTION: kernel_is_2_4 +# @USAGE: +# @DESCRIPTION: +# return true if kernel is version 2.4 +kernel_is_2_4() { + kernel_is 2 4 +} + +# @FUNCTION: kernel_is_2_6 +# @USAGE: +# @DESCRIPTION: +# return true if kernel is version 2.6 +kernel_is_2_6() { + kernel_is 2 6 || kernel_is 2 5 +} + +# Capture the sources type and set DEPENDs +if [[ ${ETYPE} == sources ]]; then + DEPEND="!build? ( + sys-apps/sed + >=sys-devel/binutils-2.11.90.0.31 + )" + RDEPEND="!build? ( + dev-lang/perl + sys-devel/bc + sys-devel/bison + sys-devel/flex + sys-devel/make + >=sys-libs/ncurses-5.2 + virtual/libelf + )" + + SLOT="${PVR}" + DESCRIPTION="Sources based on the Linux Kernel." + IUSE="symlink build" + + # Bug #266157, deblob for libre support + if [[ -z ${K_PREDEBLOBBED} ]] ; then + # Bug #359865, force a call to detect_version if needed + kernel_is ge 2 6 27 && \ + [[ -z "${K_DEBLOB_AVAILABLE}" ]] && \ + kernel_is le 2 6 ${DEBLOB_MAX_VERSION} && \ + K_DEBLOB_AVAILABLE=1 + if [[ ${K_DEBLOB_AVAILABLE} == "1" ]] ; then + IUSE="${IUSE} deblob" + + # Reflect that kernels contain firmware blobs unless otherwise + # stripped + LICENSE="${LICENSE} !deblob? ( linux-firmware )" + + DEPEND+=" deblob? ( ${PYTHON_DEPS} )" + + if [[ -n KV_MINOR ]]; then + DEBLOB_PV="${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}" + else + DEBLOB_PV="${KV_MAJOR}.${KV_PATCH}" + fi + + if [[ ${KV_MAJOR} -ge 3 ]]; then + DEBLOB_PV="${KV_MAJOR}.${KV_MINOR}" + fi + + # deblob svn tag, default is -gnu, to change, use K_DEBLOB_TAG in ebuild + K_DEBLOB_TAG=${K_DEBLOB_TAG:--gnu} + DEBLOB_A="deblob-${DEBLOB_PV}" + DEBLOB_CHECK_A="deblob-check-${DEBLOB_PV}" + DEBLOB_HOMEPAGE="https://www.fsfla.org/svn/fsfla/software/linux-libre/releases/tags/" + DEBLOB_URI_PATH="${DEBLOB_PV}${K_DEBLOB_TAG}" + DEBLOB_CHECK_URI="${DEBLOB_HOMEPAGE}/${DEBLOB_URI_PATH}/deblob-check -> ${DEBLOB_CHECK_A}" + DEBLOB_URI="${DEBLOB_HOMEPAGE}/${DEBLOB_URI_PATH}/${DEBLOB_A}" + HOMEPAGE="${HOMEPAGE} ${DEBLOB_HOMEPAGE}" + + KERNEL_URI="${KERNEL_URI} + deblob? ( + ${DEBLOB_URI} + ${DEBLOB_CHECK_URI} + )" + else + # We have no way to deblob older kernels, so just mark them as + # tainted with non-libre materials. + LICENSE="${LICENSE} linux-firmware" + fi + fi + +elif [[ ${ETYPE} == headers ]]; then + DESCRIPTION="Linux system headers" + IUSE="headers-only" + + # Since we should NOT honour KBUILD_OUTPUT in headers + # lets unset it here. + unset KBUILD_OUTPUT + + SLOT="0" +fi + +# Cross-compile support functions + +# @FUNCTION: kernel_header_destdir +# @USAGE: +# @DESCRIPTION: +# return header destination directory +kernel_header_destdir() { + [[ ${CTARGET} == ${CHOST} ]] \ + && echo /usr/include \ + || echo /usr/${CTARGET}/usr/include +} + +# @FUNCTION: cross_pre_c_headers +# @USAGE: +# @DESCRIPTION: +# set use if necessary for cross compile support +cross_pre_c_headers() { + use headers-only && [[ ${CHOST} != ${CTARGET} ]] +} + +# @FUNCTION: env_setup_xmakeopts +# @USAGE: +# @DESCRIPTION: +# set the ARCH/CROSS_COMPILE when cross compiling + +env_setup_xmakeopts() { + # Kernel ARCH != portage ARCH + export KARCH=$(tc-arch-kernel) + + # When cross-compiling, we need to set the ARCH/CROSS_COMPILE + # variables properly or bad things happen ! + xmakeopts="ARCH=${KARCH}" + if [[ ${CTARGET} != ${CHOST} ]] && ! cross_pre_c_headers ; then + xmakeopts="${xmakeopts} CROSS_COMPILE=${CTARGET}-" + elif type -p ${CHOST}-ar > /dev/null ; then + xmakeopts="${xmakeopts} CROSS_COMPILE=${CHOST}-" + fi + export xmakeopts +} + +# @FUNCTION: unpack_2_4 +# @USAGE: +# @DESCRIPTION: +# unpack and generate .config for 2.4 kernels + +unpack_2_4() { + # this file is required for other things to build properly, + # so we autogenerate it + make -s mrproper ${xmakeopts} || die "make mrproper failed" + make -s symlinks ${xmakeopts} || die "make symlinks failed" + make -s include/linux/version.h ${xmakeopts} || die "make include/linux/version.h failed" + echo ">>> version.h compiled successfully." +} + +# @FUNCTION: unpack_2_6 +# @USAGE: +# @DESCRIPTION: +# unpack and generate .config for 2.6 kernels + +unpack_2_6() { + # this file is required for other things to build properly, so we + # autogenerate it ... generate a .config to keep version.h build from + # spitting out an annoying warning + make -s mrproper ${xmakeopts} 2>/dev/null \ + || die "make mrproper failed" + + # quick fix for bug #132152 which triggers when it cannot include linux + # headers (ie, we have not installed it yet) + if ! make -s defconfig ${xmakeopts} &>/dev/null 2>&1 ; then + touch .config + eerror "make defconfig failed." + eerror "assuming you dont have any headers installed yet and continuing" + fi + + make -s include/linux/version.h ${xmakeopts} 2>/dev/null \ + || die "make include/linux/version.h failed" + rm -f .config >/dev/null +} + +# @FUNCTION: universal_unpack +# @USAGE: +# @DESCRIPTION: +# unpack kernel sources + +universal_unpack() { + debug-print "Inside universal_unpack" + + local OKV_ARRAY + IFS="." read -r -a OKV_ARRAY <<<"${OKV}" + + cd "${WORKDIR}" + if [[ ${#OKV_ARRAY[@]} -ge 3 ]] && [[ ${KV_MAJOR} -ge 3 ]]; then + unpack linux-${KV_MAJOR}.${KV_MINOR}.tar.xz + else + unpack linux-${OKV}.tar.xz + fi + + if [[ -d "linux" ]]; then + debug-print "Moving linux to linux-${KV_FULL}" + mv linux linux-${KV_FULL} \ + || die "Unable to move source tree to ${KV_FULL}." + elif [[ "${OKV}" != "${KV_FULL}" ]]; then + if [[ ${#OKV_ARRAY[@]} -ge 3 ]] && [[ ${KV_MAJOR} -ge 3 ]] && + [[ "${ETYPE}" = "sources" ]]; then + debug-print "moving linux-${KV_MAJOR}.${KV_MINOR} to linux-${KV_FULL} " + mv linux-${KV_MAJOR}.${KV_MINOR} linux-${KV_FULL} \ + || die "Unable to move source tree to ${KV_FULL}." + else + debug-print "moving linux-${OKV} to linux-${KV_FULL} " + mv linux-${OKV} linux-${KV_FULL} \ + || die "Unable to move source tree to ${KV_FULL}." + fi + elif [[ ${#OKV_ARRAY[@]} -ge 3 ]] && [[ ${KV_MAJOR} -ge 3 ]]; then + mv linux-${KV_MAJOR}.${KV_MINOR} linux-${KV_FULL} \ + || die "Unable to move source tree to ${KV_FULL}." + fi + cd "${S}" + + # remove all backup files + find . -iname "*~" -exec rm {} \; 2> /dev/null + +} + +# @FUNCTION: unpack_set_extraversion +# @USAGE: +# @DESCRIPTION: +# handle EXTRAVERSION + +unpack_set_extraversion() { + cd "${S}" + sed -i -e "s:^\(EXTRAVERSION =\).*:\1 ${EXTRAVERSION}:" Makefile + cd "${OLDPWD}" +} + +# @FUNCTION: unpack_fix_install_path +# @USAGE: +# @DESCRIPTION: +# Should be done after patches have been applied +# Otherwise patches that modify the same area of Makefile will fail + +unpack_fix_install_path() { + cd "${S}" + sed -i -e 's:#export\tINSTALL_PATH:export\tINSTALL_PATH:' Makefile +} + +# Compile Functions + +# @FUNCTION: compile_headers +# @USAGE: +# @DESCRIPTION: +# header compilation + +compile_headers() { + env_setup_xmakeopts + + # if we couldnt obtain HOSTCFLAGS from the Makefile, + # then set it to something sane + local HOSTCFLAGS=$(getfilevar HOSTCFLAGS "${S}"/Makefile) + HOSTCFLAGS=${HOSTCFLAGS:--Wall -Wstrict-prototypes -O2 -fomit-frame-pointer} + + if kernel_is 2 4; then + yes "" | make oldconfig ${xmakeopts} + echo ">>> make oldconfig complete" + make dep ${xmakeopts} + elif kernel_is 2 6; then + # 2.6.18 introduces headers_install which means we dont need any + # of this crap anymore :D + kernel_is ge 2 6 18 && return 0 + + # autoconf.h isnt generated unless it already exists. plus, we have + # no guarantee that any headers are installed on the system... + [[ -f ${EROOT}usr/include/linux/autoconf.h ]] \ + || touch include/linux/autoconf.h + + # if K_DEFCONFIG isn't set, force to "defconfig" + # needed by mips + if [[ -z ${K_DEFCONFIG} ]]; then + if kernel_is ge 2 6 16 ; then + case ${CTARGET} in + powerpc64*) K_DEFCONFIG="ppc64_defconfig";; + powerpc*) K_DEFCONFIG="pmac32_defconfig";; + *) K_DEFCONFIG="defconfig";; + esac + else + K_DEFCONFIG="defconfig" + fi + fi + + # if there arent any installed headers, then there also isnt an asm + # symlink in /usr/include/, and make defconfig will fail, so we have + # to force an include path with $S. + HOSTCFLAGS="${HOSTCFLAGS} -I${S}/include/" + ln -sf asm-${KARCH} "${S}"/include/asm || die + cross_pre_c_headers && return 0 + + make ${K_DEFCONFIG} HOSTCFLAGS="${HOSTCFLAGS}" ${xmakeopts} || die "defconfig failed (${K_DEFCONFIG})" + if compile_headers_tweak_config ; then + yes "" | make oldconfig HOSTCFLAGS="${HOSTCFLAGS}" ${xmakeopts} || die "2nd oldconfig failed" + fi + make prepare HOSTCFLAGS="${HOSTCFLAGS}" ${xmakeopts} || die "prepare failed" + make prepare-all HOSTCFLAGS="${HOSTCFLAGS}" ${xmakeopts} || die "prepare failed" + fi +} + +# @FUNCTION: compile_headers_tweak_config +# @USAGE: +# @DESCRIPTION: +# some targets can be very very picky, so let's finesse the +# .config based upon any info we may have + +compile_headers_tweak_config() { + case ${CTARGET} in + sh*) + sed -i '/CONFIG_CPU_SH/d' .config || die + echo "CONFIG_CPU_SH${CTARGET:2:1}=y" >> .config + return 0;; + esac + + # no changes, so lets do nothing + return 1 +} + +# install functions + +# @FUNCTION: install_universal +# @USAGE: +# @DESCRIPTION: +# Fix permissions in tarball + +install_universal() { + cd "${WORKDIR}" + chown -R 0:0 * >& /dev/null + chmod -R a+r-w+X,u+w * + cd ${OLDPWD} +} + +# @FUNCTION: install_headers +# @USAGE: +# @DESCRIPTION: +# Install headers + +install_headers() { + local ddir=$(kernel_header_destdir) + + # 2.6.18 introduces headers_install which means we dont need any + # of this crap anymore :D + if kernel_is ge 2 6 18 ; then + env_setup_xmakeopts + emake headers_install INSTALL_HDR_PATH="${ED}"${ddir}/.. ${xmakeopts} || die + + # let other packages install some of these headers + rm -rf "${ED}"${ddir}/scsi || die #glibc/uclibc/etc... + return 0 + fi + + # Do not use "linux/*" as that can cause problems with very long + # $S values where the cmdline to cp is too long + pushd "${S}" >/dev/null + dodir ${ddir}/linux + cp -pPR "${S}"/include/linux "${ED}"${ddir}/ || die + rm -rf "${ED}"${ddir}/linux/modules || die + + dodir ${ddir}/asm + cp -pPR "${S}"/include/asm/* "${ED}"${ddir}/asm || die + + if kernel_is 2 6 ; then + dodir ${ddir}/asm-generic + cp -pPR "${S}"/include/asm-generic/* "${ED}"${ddir}/asm-generic || die + fi + + # clean up + find "${D}" -name '*.orig' -exec rm -f {} \; + + popd >/dev/null +} + +# @FUNCTION: install_sources +# @USAGE: +# @DESCRIPTION: +# Install sources + +install_sources() { + local file + + cd "${S}" + dodir /usr/src + echo ">>> Copying sources ..." + + file="$(find ${WORKDIR} -iname "docs" -type d)" + if [[ -n ${file} ]]; then + for file in $(find ${file} -type f); do + echo "${file//*docs\/}" >> "${S}"/patches.txt + echo "===================================================" >> "${S}"/patches.txt + cat ${file} >> "${S}"/patches.txt + echo "===================================================" >> "${S}"/patches.txt + echo "" >> "${S}"/patches.txt + done + fi + + mv "${WORKDIR}"/linux* "${ED}"usr/src || die + + if [[ -n "${UNIPATCH_DOCS}" ]] ; then + for i in ${UNIPATCH_DOCS}; do + dodoc "${T}"/${i} + done + fi +} + +# @FUNCTION: preinst_headers +# @USAGE: +# @DESCRIPTION: +# Headers preinst steps + +preinst_headers() { + local ddir=$(kernel_header_destdir) + [[ -L ${EPREFIX}${ddir}/linux ]] && { rm "${EPREFIX}"${ddir}/linux || die; } + [[ -L ${EPREFIX}${ddir}/asm ]] && { rm "${EPREFIX}"${ddir}/asm || die; } +} + +# @FUNCTION: postinst_sources +# @USAGE: +# @DESCRIPTION: +# Sources post installation function. +# see inline comments + +postinst_sources() { + local MAKELINK=0 + + # if we have USE=symlink, then force K_SYMLINK=1 + use symlink && K_SYMLINK=1 + + # We do support security on a deblobbed kernel, bug #555878. + # If some particular kernel version doesn't have security + # supported because of USE=deblob or otherwise, one can still + # set K_SECURITY_UNSUPPORTED on a per ebuild basis. + #[[ $K_DEBLOB_AVAILABLE == 1 ]] && \ + # use deblob && \ + # K_SECURITY_UNSUPPORTED=deblob + + # if we are to forcably symlink, delete it if it already exists first. + if [[ ${K_SYMLINK} > 0 ]]; then + [[ -h ${EROOT}usr/src/linux ]] && { rm "${EROOT}"usr/src/linux || die; } + MAKELINK=1 + fi + + # if the link doesnt exist, lets create it + [[ ! -h ${EROOT}usr/src/linux ]] && MAKELINK=1 + + if [[ ${MAKELINK} == 1 ]]; then + ln -sf linux-${KV_FULL} "${EROOT}"usr/src/linux || die + fi + + # Don't forget to make directory for sysfs + [[ ! -d ${EROOT}sys ]] && kernel_is 2 6 && { mkdir "${EROOT}"sys || die ; } + + echo + elog "If you are upgrading from a previous kernel, you may be interested" + elog "in the following document:" + elog " - General upgrade guide: https://wiki.gentoo.org/wiki/Kernel/Upgrade" + echo + + # if K_EXTRAEINFO is set then lets display it now + if [[ -n ${K_EXTRAEINFO} ]]; then + echo ${K_EXTRAEINFO} | fmt | + while read -s ELINE; do einfo "${ELINE}"; done + fi + + # if K_EXTRAELOG is set then lets display it now + if [[ -n ${K_EXTRAELOG} ]]; then + echo ${K_EXTRAELOG} | fmt | + while read -s ELINE; do elog "${ELINE}"; done + fi + + # if K_EXTRAEWARN is set then lets display it now + if [[ -n ${K_EXTRAEWARN} ]]; then + echo ${K_EXTRAEWARN} | fmt | + while read -s ELINE; do ewarn "${ELINE}"; done + fi + + # optionally display security unsupported message + # Start with why + if [[ -n ${K_SECURITY_UNSUPPORTED} ]]; then + ewarn "${PN} is UNSUPPORTED by Gentoo Security." + fi + # And now the general message. + if [[ -n ${K_SECURITY_UNSUPPORTED} ]]; then + ewarn "This means that it is likely to be vulnerable to recent security issues." + echo + ewarn "Upstream kernel developers recommend always running the latest " + ewarn "release of any current long term supported Linux kernel version." + ewarn "To see a list of these versions, their most current release and " + ewarn "long term support status, please go to https://www.kernel.org ." + echo + ewarn "For specific information on why this kernel is unsupported, please read:" + ewarn "https://wiki.gentoo.org/wiki/Project:Kernel_Security" + fi + + # warn sparc users that they need to do cross-compiling with >= 2.6.25(bug #214765) + KV_MAJOR=$(ver_cut 1 ${OKV}) + KV_MINOR=$(ver_cut 2 ${OKV}) + KV_PATCH=$(ver_cut 3 ${OKV}) + if [[ "$(tc-arch)" = "sparc" ]]; then + if [[ $(gcc-major-version) -lt 4 && $(gcc-minor-version) -lt 4 ]]; then + if [[ ${KV_MAJOR} -ge 3 || ${KV_MAJOR}.${KV_MINOR}.${KV_PATCH} > 2.6.24 ]] ; then + echo + elog "NOTE: Since 2.6.25 the kernel Makefile has changed in a way that" + elog "you now need to do" + elog " make CROSS_COMPILE=sparc64-unknown-linux-gnu-" + elog "instead of just" + elog " make" + elog "to compile the kernel. For more information please browse to" + elog "https://bugs.gentoo.org/show_bug.cgi?id=214765" + echo + fi + fi + fi +} + +# pkg_setup functions + +# @FUNCTION: setup_headers +# @USAGE: +# @DESCRIPTION: +# Determine if ${PN} supports arch + +setup_headers() { + [[ -z ${H_SUPPORTEDARCH} ]] && H_SUPPORTEDARCH=${PN/-*/} + for i in ${H_SUPPORTEDARCH}; do + [[ $(tc-arch) == "${i}" ]] && H_ACCEPT_ARCH="yes" + done + + if [[ ${H_ACCEPT_ARCH} != "yes" ]]; then + echo + eerror "This version of ${PN} does not support $(tc-arch)." + eerror "Please merge the appropriate sources, in most cases" + eerror "(but not all) this will be called $(tc-arch)-headers." + die "Package unsupported for $(tc-arch)" + fi +} + +# @FUNCTION: unipatch +# @USAGE: <list of patches to apply> +# @DESCRIPTION: +# Universal function that will apply patches to source + +unipatch() { + local i x y z extention PIPE_CMD UNIPATCH_DROP KPATCH_DIR PATCH_DEPTH ELINE + local STRICT_COUNT PATCH_LEVEL myLC_ALL myLANG + + # set to a standard locale to ensure sorts are ordered properly. + myLC_ALL="${LC_ALL}" + myLANG="${LANG}" + LC_ALL="C" + LANG="" + + [ -z "${KPATCH_DIR}" ] && KPATCH_DIR="${WORKDIR}/patches/" + [ ! -d ${KPATCH_DIR} ] && mkdir -p ${KPATCH_DIR} + + # We're gonna need it when doing patches with a predefined patchlevel + eshopts_push -s extglob + + # This function will unpack all passed tarballs, add any passed patches, + # and remove any passed patchnumbers + # usage can be either via an env var or by params + # although due to the nature we pass this within this eclass + # it shall be by param only. + # -z "${UNIPATCH_LIST}" ] && UNIPATCH_LIST="${@}" + UNIPATCH_LIST="${@}" + + #unpack any passed tarballs + for i in ${UNIPATCH_LIST}; do + if echo ${i} | grep -qs -e "\.tar" -e "\.tbz" -e "\.tgz" ; then + if [ -n "${UNIPATCH_STRICTORDER}" ]; then + unset z + STRICT_COUNT=$((10#${STRICT_COUNT} + 1)) + for((y=0; y<$((6 - ${#STRICT_COUNT})); y++)); + do z="${z}0"; + done + PATCH_ORDER="${z}${STRICT_COUNT}" + + mkdir -p "${KPATCH_DIR}/${PATCH_ORDER}" + pushd "${KPATCH_DIR}/${PATCH_ORDER}" >/dev/null + unpack ${i##*/} + popd >/dev/null + else + pushd "${KPATCH_DIR}" >/dev/null + unpack ${i##*/} + popd >/dev/null + fi + + [[ ${i} == *:* ]] && echo ">>> Strict patch levels not currently supported for tarballed patchsets" + else + extention=${i/*./} + extention=${extention/:*/} + PIPE_CMD="" + case ${extention} in + xz) PIPE_CMD="xz -dc";; + lzma) PIPE_CMD="lzma -dc";; + bz2) PIPE_CMD="bzip2 -dc";; + patch*) PIPE_CMD="cat";; + diff) PIPE_CMD="cat";; + gz|Z|z) PIPE_CMD="gzip -dc";; + ZIP|zip) PIPE_CMD="unzip -p";; + *) UNIPATCH_DROP="${UNIPATCH_DROP} ${i/:*/}";; + esac + + PATCH_LEVEL=${i/*([^:])?(:)} + i=${i/:*/} + x=${i/*\//} + x=${x/\.${extention}/} + + if [ -n "${PIPE_CMD}" ]; then + if [ ! -r "${i}" ]; then + echo + eerror "FATAL: unable to locate:" + eerror "${i}" + eerror "for read-only. The file either has incorrect permissions" + eerror "or does not exist." + die Unable to locate ${i} + fi + + if [ -n "${UNIPATCH_STRICTORDER}" ]; then + unset z + STRICT_COUNT=$((10#${STRICT_COUNT} + 1)) + for((y=0; y<$((6 - ${#STRICT_COUNT})); y++)); + do z="${z}0"; + done + PATCH_ORDER="${z}${STRICT_COUNT}" + + mkdir -p ${KPATCH_DIR}/${PATCH_ORDER}/ + $(${PIPE_CMD} ${i} > ${KPATCH_DIR}/${PATCH_ORDER}/${x}.patch${PATCH_LEVEL}) || die "uncompressing patch failed" + else + $(${PIPE_CMD} ${i} > ${KPATCH_DIR}/${x}.patch${PATCH_LEVEL}) || die "uncompressing patch failed" + fi + fi + fi + + # If experimental was not chosen by the user, drop experimental patches not in K_EXP_GENPATCHES_LIST. + if [[ "${i}" == *"genpatches-"*".experimental."* && -n ${K_EXP_GENPATCHES_PULL} ]] ; then + if [[ -z ${K_EXP_GENPATCHES_NOUSE} ]] && use experimental; then + continue + fi + + local j + for j in ${KPATCH_DIR}/*/50*_*.patch*; do + for k in ${K_EXP_GENPATCHES_LIST} ; do + [[ "$(basename ${j})" == ${k}* ]] && continue 2 + done + UNIPATCH_DROP+=" $(basename ${j})" + done + else + UNIPATCH_LIST_GENPATCHES+=" ${DISTDIR}/${tarball}" + debug-print "genpatches tarball: $tarball" + + # check gcc version < 4.9.X uses patch 5000 and = 4.9.X uses patch 5010 + if [[ $(gcc-major-version) -eq 4 ]] && [[ $(gcc-minor-version) -ne 9 ]]; then + # drop 5000_enable-additional-cpu-optimizations-for-gcc-4.9.patch + if [[ $UNIPATCH_DROP != *"5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch"* ]]; then + UNIPATCH_DROP+=" 5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch" + fi + else + if [[ $UNIPATCH_DROP != *"5000_enable-additional-cpu-optimizations-for-gcc.patch"* ]]; then + #drop 5000_enable-additional-cpu-optimizations-for-gcc.patch + UNIPATCH_DROP+=" 5000_enable-additional-cpu-optimizations-for-gcc.patch" + fi + fi + fi + done + + #populate KPATCH_DIRS so we know where to look to remove the excludes + x=${KPATCH_DIR} + KPATCH_DIR="" + for i in $(find ${x} -type d | sort -n); do + KPATCH_DIR="${KPATCH_DIR} ${i}" + done + + # do not apply fbcondecor patch to sparc/sparc64 as it breaks boot + # bug #272676 + if [[ "$(tc-arch)" = "sparc" || "$(tc-arch)" = "sparc64" ]]; then + if [[ ${KV_MAJOR} -ge 3 || ${KV_MAJOR}.${KV_MINOR}.${KV_PATCH} > 2.6.28 ]]; then + if [[ ! -z ${K_WANT_GENPATCHES} ]] ; then + UNIPATCH_DROP="${UNIPATCH_DROP} *_fbcondecor*.patch" + echo + ewarn "fbcondecor currently prevents sparc/sparc64 from booting" + ewarn "for kernel versions >= 2.6.29. Removing fbcondecor patch." + ewarn "See https://bugs.gentoo.org/show_bug.cgi?id=272676 for details" + echo + fi + fi + fi + + #so now lets get rid of the patchno's we want to exclude + UNIPATCH_DROP="${UNIPATCH_EXCLUDE} ${UNIPATCH_DROP}" + for i in ${UNIPATCH_DROP}; do + ebegin "Excluding Patch #${i}" + for x in ${KPATCH_DIR}; do rm -f ${x}/${i}* 2>/dev/null; done + eend $? + done + + # and now, finally, we patch it :) + for x in ${KPATCH_DIR}; do + for i in $(find ${x} -maxdepth 1 -iname "*.patch*" -or -iname "*.diff*" | sort -n); do + STDERR_T="${T}/${i/*\//}" + STDERR_T="${STDERR_T/.patch*/.err}" + + [ -z ${i/*.patch*/} ] && PATCH_DEPTH=${i/*.patch/} + #[ -z ${i/*.diff*/} ] && PATCH_DEPTH=${i/*.diff/} + + if [ -z "${PATCH_DEPTH}" ]; then PATCH_DEPTH=0; fi + + #################################################################### + # IMPORTANT: This is temporary code to support Linux git 3.15_rc1! # + # # + # The patch contains a removal of a symlink, followed by addition # + # of a file with the same name as the symlink in the same # + # location; this causes the dry-run to fail, filed bug #507656. # + # # + # https://bugs.gentoo.org/show_bug.cgi?id=507656 # + #################################################################### + if [[ -n ${K_FROM_GIT} ]] ; then + if [[ ${KV_MAJOR} -gt 3 || ( ${KV_MAJOR} -eq 3 && ${KV_PATCH} -gt 15 ) && + ${RELEASETYPE} == -rc ]] ; then + ebegin "Applying ${i/*\//} (-p1)" + if [ $(patch -p1 --no-backup-if-mismatch -f < ${i} >> ${STDERR_T}) "$?" -le 2 ]; then + eend 0 + rm ${STDERR_T} || die + break + else + eend 1 + eerror "Failed to apply patch ${i/*\//}" + eerror "Please attach ${STDERR_T} to any bug you may post." + eshopts_pop + die "Failed to apply ${i/*\//} on patch depth 1." + fi + fi + fi + #################################################################### + + while [ ${PATCH_DEPTH} -lt 5 ]; do + echo "Attempting Dry-run:" >> ${STDERR_T} + echo "cmd: patch -p${PATCH_DEPTH} --no-backup-if-mismatch --dry-run -f < ${i}" >> ${STDERR_T} + echo "=======================================================" >> ${STDERR_T} + if [ $(patch -p${PATCH_DEPTH} --no-backup-if-mismatch --dry-run -f < ${i} >> ${STDERR_T}) $? -eq 0 ]; then + ebegin "Applying ${i/*\//} (-p${PATCH_DEPTH})" + echo "Attempting patch:" > ${STDERR_T} + echo "cmd: patch -p${PATCH_DEPTH} --no-backup-if-mismatch -f < ${i}" >> ${STDERR_T} + echo "=======================================================" >> ${STDERR_T} + if [ $(patch -p${PATCH_DEPTH} --no-backup-if-mismatch -f < ${i} >> ${STDERR_T}) "$?" -eq 0 ]; then + eend 0 + rm ${STDERR_T} || die + break + else + eend 1 + eerror "Failed to apply patch ${i/*\//}" + eerror "Please attach ${STDERR_T} to any bug you may post." + eshopts_pop + die "Failed to apply ${i/*\//} on patch depth ${PATCH_DEPTH}." + fi + else + PATCH_DEPTH=$((${PATCH_DEPTH} + 1)) + fi + done + if [ ${PATCH_DEPTH} -eq 5 ]; then + eerror "Failed to dry-run patch ${i/*\//}" + eerror "Please attach ${STDERR_T} to any bug you may post." + eshopts_pop + die "Unable to dry-run patch on any patch depth lower than 5." + fi + done + done + + # When genpatches is used, we want to install 0000_README which documents + # the patches that were used; such that the user can see them, bug #301478. + if [[ ! -z ${K_WANT_GENPATCHES} ]] ; then + UNIPATCH_DOCS="${UNIPATCH_DOCS} 0000_README" + fi + + # When files listed in UNIPATCH_DOCS are found in KPATCH_DIR's, we copy it + # to the temporary directory and remember them in UNIPATCH_DOCS to install + # them during the install phase. + local tmp + for x in ${KPATCH_DIR}; do + for i in ${UNIPATCH_DOCS}; do + if [[ -f ${x}/${i} ]] ; then + tmp="${tmp} ${i}" + cp -f "${x}/${i}" "${T}"/ || die + fi + done + done + UNIPATCH_DOCS="${tmp}" + + # clean up KPATCH_DIR's - fixes bug #53610 + for x in ${KPATCH_DIR}; do rm -Rf ${x}; done + + LC_ALL="${myLC_ALL}" + LANG="${myLANG}" + eshopts_pop +} + +# @FUNCTION: getfilevar +# @USAGE: <variable> <configfile> +# @DESCRIPTION: +# pulled from linux-info + +getfilevar() { + local workingdir basefname basedname xarch=$(tc-arch-kernel) + + if [[ -z ${1} ]] && [[ ! -f ${2} ]]; then + echo -e "\n" + eerror "getfilevar requires 2 variables, with the second a valid file." + eerror " getfilevar <VARIABLE> <CONFIGFILE>" + else + workingdir=${PWD} + basefname=$(basename ${2}) + basedname=$(dirname ${2}) + unset ARCH + + cd ${basedname} + echo -e "include ${basefname}\ne:\n\t@echo \$(${1})" | \ + make ${BUILD_FIXES} -s -f - e 2>/dev/null + cd ${workingdir} + + ARCH=${xarch} + fi +} + +# @FUNCTION: detect_arch +# @USAGE: +# @DESCRIPTION: +# This function sets ARCH_URI and ARCH_PATCH +# with the neccessary info for the arch sepecific compatibility +# patchsets. + +detect_arch() { + + local ALL_ARCH LOOP_ARCH LOOP_ARCH_L COMPAT_URI i TC_ARCH_KERNEL + + # COMPAT_URI is the contents of ${ARCH}_URI + # ARCH_URI is the URI for all the ${ARCH}_URI patches + # ARCH_PATCH is ARCH_URI broken into files for UNIPATCH + + ARCH_URI="" + ARCH_PATCH="" + TC_ARCH_KERNEL="" + ALL_ARCH="ALPHA AMD64 ARM HPPA IA64 M68K MIPS PPC PPC64 S390 SH SPARC X86" + + for LOOP_ARCH in ${ALL_ARCH}; do + COMPAT_URI="${LOOP_ARCH}_URI" + COMPAT_URI="${!COMPAT_URI}" + + declare -l LOOP_ARCH_L=${LOOP_ARCH} + + [[ -n ${COMPAT_URI} ]] && \ + ARCH_URI="${ARCH_URI} ${LOOP_ARCH_L}? ( ${COMPAT_URI} )" + + declare -u TC_ARCH_KERNEL=$(tc-arch-kernel) + if [[ ${LOOP_ARCH} == ${TC_ARCH_KERNEL} ]]; then + for i in ${COMPAT_URI}; do + ARCH_PATCH="${ARCH_PATCH} ${DISTDIR}/${i/*\//}" + done + fi + + done +} + +# @FUNCTION: headers___fix +# @USAGE: +# @DESCRIPTION: +# Voodoo to partially fix broken upstream headers. +# note: do not put inline/asm/volatile together (breaks "inline asm volatile") + +headers___fix() { + sed -i \ + -e '/^\#define.*_TYPES_H/{:loop n; bloop}' \ + -e 's:\<\([us]\(8\|16\|32\|64\)\)\>:__\1:g' \ + -e "s/\([[:space:]]\)inline\([[:space:](]\)/\1__inline__\2/g" \ + -e "s/\([[:space:]]\)asm\([[:space:](]\)/\1__asm__\2/g" \ + -e "s/\([[:space:]]\)volatile\([[:space:](]\)/\1__volatile__\2/g" \ + "$@" +} + +# @FUNCTION: kernel-2_src_unpack +# @USAGE: +# @DESCRIPTION: +# unpack sources, handle genpatches, deblob + +kernel-2_src_unpack() { + universal_unpack + debug-print "Doing unipatch" + + # request UNIPATCH_LIST_GENPATCHES in phase since it calls 'use' + handle_genpatches --set-unipatch-list + [[ -n ${UNIPATCH_LIST} || -n ${UNIPATCH_LIST_DEFAULT} || -n ${UNIPATCH_LIST_GENPATCHES} ]] && \ + unipatch "${UNIPATCH_LIST_DEFAULT} ${UNIPATCH_LIST_GENPATCHES} ${UNIPATCH_LIST}" + + debug-print "Doing premake" + + # allow ebuilds to massage the source tree after patching but before + # we run misc `make` functions below + [[ $(type -t kernel-2_hook_premake) == "function" ]] && kernel-2_hook_premake + + debug-print "Doing unpack_set_extraversion" + + [[ -z ${K_NOSETEXTRAVERSION} ]] && unpack_set_extraversion + unpack_fix_install_path + + # Setup xmakeopts and cd into sourcetree. + env_setup_xmakeopts + cd "${S}" + + # We dont need a version.h for anything other than headers + # at least, I should hope we dont. If this causes problems + # take out the if/fi block and inform me please. + # unpack_2_6 should now be 2.6.17 safe anyways + if [[ ${ETYPE} == headers ]]; then + kernel_is 2 4 && unpack_2_4 + kernel_is 2 6 && unpack_2_6 + fi + + if [[ $K_DEBLOB_AVAILABLE == 1 ]] && use deblob ; then + cp "${DISTDIR}/${DEBLOB_A}" "${T}" || die "cp ${DEBLOB_A} failed" + cp "${DISTDIR}/${DEBLOB_CHECK_A}" "${T}/deblob-check" || die "cp ${DEBLOB_CHECK_A} failed" + chmod +x "${T}/${DEBLOB_A}" "${T}/deblob-check" || die "chmod deblob scripts failed" + fi + + # fix a problem on ppc where TOUT writes to /usr/src/linux breaking sandbox + # only do this for kernel < 2.6.27 since this file does not exist in later + # kernels + if [[ -n ${KV_MINOR} && ${KV_MAJOR}.${KV_MINOR}.${KV_PATCH} < 2.6.27 ]] ; then + sed -i \ + -e 's|TOUT := .tmp_gas_check|TOUT := $(T).tmp_gas_check|' \ + "${S}"/arch/ppc/Makefile + else + sed -i \ + -e 's|TOUT := .tmp_gas_check|TOUT := $(T).tmp_gas_check|' \ + "${S}"/arch/powerpc/Makefile + fi +} + +# @FUNCTION: kernel-2_src_prepare +# @USAGE: +# @DESCRIPTION: +# Apply any user patches + +kernel-2_src_prepare() { + + debug-print "Applying any user patches" + + # apply any user patches + case ${EAPI:-0} in + 0|1|2|3|4|5) epatch_user ;; + 6) eapply_user ;; + esac +} + +# @FUNCTION: kernel-2_src_compile +# @USAGE: +# @DESCRIPTION: +# conpile headers or run deblob script + +kernel-2_src_compile() { + cd "${S}" + [[ ${ETYPE} == headers ]] && compile_headers + + if [[ $K_DEBLOB_AVAILABLE == 1 ]] && use deblob ; then + echo ">>> Running deblob script ..." + python_setup + sh "${T}/${DEBLOB_A}" --force || die "Deblob script failed to run!!!" + fi +} + +# @FUNCTION: kernel-2_src_test +# @USAGE: +# @DESCRIPTION: +# if you leave it to the default src_test, it will run make to +# find whether test/check targets are present; since "make test" +# actually produces a few support files, they are installed even +# though the package is binchecks-restricted. +# +# Avoid this altogether by making the function moot. +kernel-2_src_test() { :; } + +# @FUNCTION: kernel-2_pkg_preinst +# @DESCRIPTION: +# if ETYPE = headers, call preinst_headers + +kernel-2_pkg_preinst() { + [[ ${ETYPE} == headers ]] && preinst_headers +} + +# @FUNCTION: kernel-2_src_install +# @USAGE: +# @DESCRIPTION: +# Install headers or sources dependant on ETYPE + +kernel-2_src_install() { + install_universal + [[ ${ETYPE} == headers ]] && install_headers + [[ ${ETYPE} == sources ]] && install_sources +} + +# @FUNCTION: kernel-2_pkg_postinst +# @USAGE: +# @DESCRIPTION: +# call postinst_sources for ETYPE = sources + +kernel-2_pkg_postinst() { + [[ ${ETYPE} == sources ]] && postinst_sources +} + +# @FUNCTION: kernel-2_pkg_setup +# @USAGE: +# @DESCRIPTION: +# check for supported kernel version, die if ETYPE is unknown, call setup_headers +# if necessary + +kernel-2_pkg_setup() { + if kernel_is 2 4; then + if [[ $(gcc-major-version) -ge 4 ]] ; then + echo + ewarn "Be warned !! >=sys-devel/gcc-4.0.0 isn't supported with linux-2.4!" + ewarn "Either switch to another gcc-version (via gcc-config) or use a" + ewarn "newer kernel that supports gcc-4." + echo + ewarn "Also be aware that bugreports about gcc-4 not working" + ewarn "with linux-2.4 based ebuilds will be closed as INVALID!" + echo + fi + fi + + ABI="${KERNEL_ABI}" + if [[ ${ETYPE} != sources ]] && [[ ${ETYPE} != headers ]]; then + eerror "Unknown ETYPE=\"${ETYPE}\", must be \"sources\" or \"headers\"" + die "Unknown ETYPE=\"${ETYPE}\", must be \"sources\" or \"headers\"" + fi + + [[ ${ETYPE} == headers ]] && setup_headers + [[ ${ETYPE} == sources ]] && echo ">>> Preparing to unpack ..." +} + +# @FUNCTION: kernel-2_pkg_postrm +# @USAGE: +# @DESCRIPTION: +# Notify the user that after a depclean, there may be sources +# left behind that need to be manually cleaned + +kernel-2_pkg_postrm() { + # This warning only makes sense for kernel sources. + [[ ${ETYPE} == headers ]] && return 0 + + # If there isn't anything left behind, then don't complain. + [[ -e ${EROOT}usr/src/linux-${KV_FULL} ]] || return 0 + echo + ewarn "Note: Even though you have successfully unmerged " + ewarn "your kernel package, directories in kernel source location: " + ewarn "${EROOT}usr/src/linux-${KV_FULL}" + ewarn "with modified files will remain behind. By design, package managers" + ewarn "will not remove these modified files and the directories they reside in." + echo + ewarn "For more detailed kernel removal instructions, please see: " + ewarn "https://wiki.gentoo.org/wiki/Kernel/Removal" + echo +} diff --git a/eclass/linux-info.eclass b/eclass/linux-info.eclass new file mode 100644 index 0000000..98ec0ac --- /dev/null +++ b/eclass/linux-info.eclass @@ -0,0 +1,966 @@ +# Copyright 1999-2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: linux-info.eclass +# @MAINTAINER: +# kernel@gentoo.org +# @AUTHOR: +# Original author: John Mylchreest <johnm@gentoo.org> +# @BLURB: eclass used for accessing kernel related information +# @DESCRIPTION: +# This eclass is used as a central eclass for accessing kernel +# related information for source or binary already installed. +# It is vital for linux-mod.eclass to function correctly, and is split +# out so that any ebuild behaviour "templates" are abstracted out +# using additional eclasses. +# +# "kernel config" in this file means: +# The .config of the currently installed sources is used as the first +# preference, with a fall-back to bundled config (/proc/config.gz) if available. +# +# Before using any of the config-handling functions in this eclass, you must +# ensure that one of the following functions has been called (in order of +# preference), otherwise you will get bugs like #364041): +# linux-info_pkg_setup +# linux-info_get_any_version +# get_version +# get_running_version + +# A Couple of env vars are available to effect usage of this eclass +# These are as follows: + +# @ECLASS-VARIABLE: KERNEL_DIR +# @DESCRIPTION: +# A string containing the directory of the target kernel sources. The default value is +# "/usr/src/linux" + +# @ECLASS-VARIABLE: CONFIG_CHECK +# @DESCRIPTION: +# A string containing a list of .config options to check for before +# proceeding with the install. +# +# e.g.: CONFIG_CHECK="MTRR" +# +# You can also check that an option doesn't exist by +# prepending it with an exclamation mark (!). +# +# e.g.: CONFIG_CHECK="!MTRR" +# +# To simply warn about a missing option, prepend a '~'. +# It may be combined with '!'. +# +# In general, most checks should be non-fatal. The only time fatal checks should +# be used is for building kernel modules or cases that a compile will fail +# without the option. +# +# This is to allow usage of binary kernels, and minimal systems without kernel +# sources. + +# @ECLASS-VARIABLE: ERROR_<CFG> +# @DESCRIPTION: +# A string containing the error message to display when the check against CONFIG_CHECK +# fails. <CFG> should reference the appropriate option used in CONFIG_CHECK. +# +# e.g.: ERROR_MTRR="MTRR exists in the .config but shouldn't!!" + +# @ECLASS-VARIABLE: KBUILD_OUTPUT +# @DESCRIPTION: +# A string passed on commandline, or set from the kernel makefile. It contains the directory +# which is to be used as the kernel object directory. + +# There are also a couple of variables which are set by this, and shouldn't be +# set by hand. These are as follows: + +# @ECLASS-VARIABLE: KV_FULL +# @DESCRIPTION: +# A read-only variable. It's a string containing the full kernel version. ie: 2.6.9-gentoo-johnm-r1 + +# @ECLASS-VARIABLE: KV_MAJOR +# @DESCRIPTION: +# A read-only variable. It's an integer containing the kernel major version. ie: 2 + +# @ECLASS-VARIABLE: KV_MINOR +# @DESCRIPTION: +# A read-only variable. It's an integer containing the kernel minor version. ie: 6 + +# @ECLASS-VARIABLE: KV_PATCH +# @DESCRIPTION: +# A read-only variable. It's an integer containing the kernel patch version. ie: 9 + +# @ECLASS-VARIABLE: KV_EXTRA +# @DESCRIPTION: +# A read-only variable. It's a string containing the kernel EXTRAVERSION. ie: -gentoo + +# @ECLASS-VARIABLE: KV_LOCAL +# @DESCRIPTION: +# A read-only variable. It's a string containing the kernel LOCALVERSION concatenation. ie: -johnm + +# @ECLASS-VARIABLE: KV_DIR +# @DESCRIPTION: +# A read-only variable. It's a string containing the kernel source directory, will be null if +# KERNEL_DIR is invalid. + +# @ECLASS-VARIABLE: KV_OUT_DIR +# @DESCRIPTION: +# A read-only variable. It's a string containing the kernel object directory, will be KV_DIR unless +# KBUILD_OUTPUT is used. This should be used for referencing .config. + +# And to ensure all the weirdness with crosscompile +inherit toolchain-funcs +[[ ${EAPI:-0} == [0123456] ]] && inherit eapi7-ver + +EXPORT_FUNCTIONS pkg_setup + +IUSE="kernel_linux" + +# Overwritable environment Var's +# --------------------------------------- +KERNEL_DIR="${KERNEL_DIR:-${ROOT%/}/usr/src/linux}" + + +# Bug fixes +# fix to bug #75034 +case ${ARCH} in + ppc) BUILD_FIXES="${BUILD_FIXES} TOUT=${T}/.tmp_gas_check";; + ppc64) BUILD_FIXES="${BUILD_FIXES} TOUT=${T}/.tmp_gas_check";; +esac + +# @FUNCTION: set_arch_to_kernel +# @DESCRIPTION: +# Set the env ARCH to match what the kernel expects. +set_arch_to_kernel() { export ARCH=$(tc-arch-kernel); } +# @FUNCTION: set_arch_to_portage +# @DESCRIPTION: +# Set the env ARCH to match what portage expects. +set_arch_to_portage() { export ARCH=$(tc-arch); } + +# qeinfo "Message" +# ------------------- +# qeinfo is a quiet einfo call when EBUILD_PHASE +# should not have visible output. +qout() { + local outputmsg type + type=${1} + shift + outputmsg="${@}" + case "${EBUILD_PHASE}" in + depend) unset outputmsg;; + clean) unset outputmsg;; + preinst) unset outputmsg;; + esac + [ -n "${outputmsg}" ] && ${type} "${outputmsg}" +} + +qeinfo() { qout einfo "${@}" ; } +qewarn() { qout ewarn "${@}" ; } +qeerror() { qout eerror "${@}" ; } + +# File Functions +# --------------------------------------- + +# @FUNCTION: getfilevar +# @USAGE: variable configfile +# @RETURN: the value of the variable +# @DESCRIPTION: +# It detects the value of the variable defined in the file configfile. This is +# done by including the configfile, and printing the variable with Make. +# It WILL break if your makefile has missing dependencies! +getfilevar() { + local ERROR basefname basedname myARCH="${ARCH}" M="${S}" + ERROR=0 + + [ -z "${1}" ] && ERROR=1 + [ ! -f "${2}" ] && ERROR=1 + + if [ "${ERROR}" = 1 ] + then + echo -e "\n" + eerror "getfilevar requires 2 variables, with the second a valid file." + eerror " getfilevar <VARIABLE> <CONFIGFILE>" + else + basefname="$(basename ${2})" + basedname="$(dirname ${2})" + unset ARCH + + # We use nonfatal because we want the caller to take care of things #373151 + [[ ${EAPI:-0} == [0123] ]] && nonfatal() { "$@"; } + case ${EBUILD_PHASE_FUNC} in + pkg_info|pkg_nofetch|pkg_pretend) M="${T}" ;; + esac + echo -e "e:\\n\\t@echo \$(${1})\\ninclude ${basefname}" | \ + nonfatal emake -C "${basedname}" M="${M}" ${BUILD_FIXES} -s -f - 2>/dev/null + + ARCH=${myARCH} + fi +} + +# @FUNCTION: getfilevar_noexec +# @USAGE: variable configfile +# @RETURN: the value of the variable +# @DESCRIPTION: +# It detects the value of the variable defined in the file configfile. +# This is done with sed matching an expression only. If the variable is defined, +# you will run into problems. See getfilevar for those cases. +getfilevar_noexec() { + local ERROR basefname basedname mycat myARCH="${ARCH}" + ERROR=0 + mycat='cat' + + [ -z "${1}" ] && ERROR=1 + [ ! -f "${2}" ] && ERROR=1 + [ "${2%.gz}" != "${2}" ] && mycat='zcat' + + if [ "${ERROR}" = 1 ] + then + echo -e "\n" + eerror "getfilevar_noexec requires 2 variables, with the second a valid file." + eerror " getfilevar_noexec <VARIABLE> <CONFIGFILE>" + else + ${mycat} "${2}" | \ + sed -n \ + -e "/^[[:space:]]*${1}[[:space:]]*:\\?=[[:space:]]*\(.*\)\$/{ + s,^[^=]*[[:space:]]*=[[:space:]]*,,g ; + s,[[:space:]]*\$,,g ; + p + }" + fi +} + +# @ECLASS-VARIABLE: _LINUX_CONFIG_EXISTS_DONE +# @INTERNAL +# @DESCRIPTION: +# This is only set if one of the linux_config_*exists functions has been called. +# We use it for a QA warning that the check for a config has not been performed, +# as linux_chkconfig* in non-legacy mode WILL return an undefined value if no +# config is available at all. +_LINUX_CONFIG_EXISTS_DONE= + +linux_config_qa_check() { + local f="$1" + if [ -z "${_LINUX_CONFIG_EXISTS_DONE}" ]; then + ewarn "QA: You called $f before any linux_config_exists!" + ewarn "QA: The return value of $f will NOT guaranteed later!" + fi + + if ! use kernel_linux; then + die "$f called on non-Linux system, please fix the ebuild" + fi +} + +# @FUNCTION: linux_config_src_exists +# @RETURN: true or false +# @DESCRIPTION: +# It returns true if .config exists in a build directory otherwise false +linux_config_src_exists() { + export _LINUX_CONFIG_EXISTS_DONE=1 + use kernel_linux && [[ -n ${KV_OUT_DIR} && -s ${KV_OUT_DIR}/.config ]] +} + +# @FUNCTION: linux_config_bin_exists +# @RETURN: true or false +# @DESCRIPTION: +# It returns true if .config exists in /proc, otherwise false +linux_config_bin_exists() { + export _LINUX_CONFIG_EXISTS_DONE=1 + use kernel_linux && [[ -s /proc/config.gz ]] +} + +# @FUNCTION: linux_config_exists +# @RETURN: true or false +# @DESCRIPTION: +# It returns true if .config exists otherwise false +# +# This function MUST be checked before using any of the linux_chkconfig_* +# functions. +linux_config_exists() { + linux_config_src_exists || linux_config_bin_exists +} + +# @FUNCTION: linux_config_path +# @DESCRIPTION: +# Echo the name of the config file to use. If none are found, +# then return false. +linux_config_path() { + if linux_config_src_exists; then + echo "${KV_OUT_DIR}/.config" + elif linux_config_bin_exists; then + echo "/proc/config.gz" + else + return 1 + fi +} + +# @FUNCTION: require_configured_kernel +# @DESCRIPTION: +# This function verifies that the current kernel is configured (it checks against the existence of .config) +# otherwise it dies. +require_configured_kernel() { + if ! use kernel_linux; then + die "${FUNCNAME}() called on non-Linux system, please fix the ebuild" + fi + + if ! linux_config_src_exists; then + qeerror "Could not find a usable .config in the kernel source directory." + qeerror "Please ensure that ${KERNEL_DIR} points to a configured set of Linux sources." + qeerror "If you are using KBUILD_OUTPUT, please set the environment var so that" + qeerror "it points to the necessary object directory so that it might find .config." + die "Kernel not configured; no .config found in ${KV_OUT_DIR}" + fi + get_version || die "Unable to determine configured kernel version" +} + +# @FUNCTION: linux_chkconfig_present +# @USAGE: option +# @RETURN: true or false +# @DESCRIPTION: +# It checks that CONFIG_<option>=y or CONFIG_<option>=m is present in the current kernel .config +# If linux_config_exists returns false, the results of this are UNDEFINED. You +# MUST call linux_config_exists first. +linux_chkconfig_present() { + linux_config_qa_check linux_chkconfig_present + [[ $(getfilevar_noexec "CONFIG_$1" "$(linux_config_path)") == [my] ]] +} + +# @FUNCTION: linux_chkconfig_module +# @USAGE: option +# @RETURN: true or false +# @DESCRIPTION: +# It checks that CONFIG_<option>=m is present in the current kernel .config +# If linux_config_exists returns false, the results of this are UNDEFINED. You +# MUST call linux_config_exists first. +linux_chkconfig_module() { + linux_config_qa_check linux_chkconfig_module + [[ $(getfilevar_noexec "CONFIG_$1" "$(linux_config_path)") == m ]] +} + +# @FUNCTION: linux_chkconfig_builtin +# @USAGE: option +# @RETURN: true or false +# @DESCRIPTION: +# It checks that CONFIG_<option>=y is present in the current kernel .config +# If linux_config_exists returns false, the results of this are UNDEFINED. You +# MUST call linux_config_exists first. +linux_chkconfig_builtin() { + linux_config_qa_check linux_chkconfig_builtin + [[ $(getfilevar_noexec "CONFIG_$1" "$(linux_config_path)") == y ]] +} + +# @FUNCTION: linux_chkconfig_string +# @USAGE: option +# @RETURN: CONFIG_<option> +# @DESCRIPTION: +# It prints the CONFIG_<option> value of the current kernel .config (it requires a configured kernel). +# If linux_config_exists returns false, the results of this are UNDEFINED. You +# MUST call linux_config_exists first. +linux_chkconfig_string() { + linux_config_qa_check linux_chkconfig_string + getfilevar_noexec "CONFIG_$1" "$(linux_config_path)" +} + +# Versioning Functions +# --------------------------------------- + +# @FUNCTION: kernel_is +# @USAGE: [-lt -gt -le -ge -eq] major_number [minor_number patch_number] +# @RETURN: true or false +# @DESCRIPTION: +# It returns true when the current kernel version satisfies the comparison against the passed version. +# -eq is the default comparison. +# +# @CODE +# For Example where KV = 2.6.9 +# kernel_is 2 4 returns false +# kernel_is 2 returns true +# kernel_is 2 6 returns true +# kernel_is 2 6 8 returns false +# kernel_is 2 6 9 returns true +# @CODE + +# Note: duplicated in kernel-2.eclass +kernel_is() { + if ! use kernel_linux; then + die "${FUNCNAME}() called on non-Linux system, please fix the ebuild" + fi + + # if we haven't determined the version yet, we need to. + linux-info_get_any_version + + # Now we can continue + local operator test value + + case ${1#-} in + lt) operator="-lt"; shift;; + gt) operator="-gt"; shift;; + le) operator="-le"; shift;; + ge) operator="-ge"; shift;; + eq) operator="-eq"; shift;; + *) operator="-eq";; + esac + [[ $# -gt 3 ]] && die "Error in kernel-2_kernel_is(): too many parameters" + + : $(( test = (KV_MAJOR << 16) + (KV_MINOR << 8) + KV_PATCH )) + : $(( value = (${1:-${KV_MAJOR}} << 16) + (${2:-${KV_MINOR}} << 8) + ${3:-${KV_PATCH}} )) + [ ${test} ${operator} ${value} ] +} + +get_localversion() { + local lv_list i x + + local shopt_save=$(shopt -p nullglob) + shopt -s nullglob + local files=( ${1}/localversion* ) + ${shopt_save} + + # ignore files with ~ in it. + for i in "${files[@]}"; do + [[ -n ${i//*~*} ]] && lv_list="${lv_list} ${i}" + done + + for i in ${lv_list}; do + x="${x}$(<${i})" + done + x=${x/ /} + echo ${x} +} + +# Check if the Makefile is valid for direct parsing. +# Check status results: +# - PASS, use 'getfilevar' to extract values +# - FAIL, use 'getfilevar_noexec' to extract values +# The check may fail if: +# - make is not present +# - corruption exists in the kernel makefile +get_makefile_extract_function() { + local a='' b='' mkfunc='getfilevar' + a="$(getfilevar VERSION ${KERNEL_MAKEFILE})" + b="$(getfilevar_noexec VERSION ${KERNEL_MAKEFILE})" + [[ "${a}" != "${b}" ]] && mkfunc='getfilevar_noexec' + echo "${mkfunc}" +} + +# internal variable, so we know to only print the warning once +get_version_warning_done= + +# @FUNCTION: get_version +# @DESCRIPTION: +# It gets the version of the kernel inside KERNEL_DIR and populates the KV_FULL variable +# (if KV_FULL is already set it does nothing). +# +# The kernel version variables (KV_MAJOR, KV_MINOR, KV_PATCH, KV_EXTRA and KV_LOCAL) are also set. +# +# The KV_DIR is set using the KERNEL_DIR env var, the KV_DIR_OUT is set using a valid +# KBUILD_OUTPUT (in a decreasing priority list, we look for the env var, makefile var or the +# symlink /lib/modules/${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}${KV_EXTRA}/build). +get_version() { + if ! use kernel_linux; then + die "${FUNCNAME}() called on non-Linux system, please fix the ebuild" + fi + + local tmplocal + + # no need to execute this twice assuming KV_FULL is populated. + # we can force by unsetting KV_FULL + [ -n "${KV_FULL}" ] && return 0 + + # if we dont know KV_FULL, then we need too. + # make sure KV_DIR isnt set since we need to work it out via KERNEL_DIR + unset KV_DIR + + # KV_DIR will contain the full path to the sources directory we should use + [ -z "${get_version_warning_done}" ] && \ + qeinfo "Determining the location of the kernel source code" + [ -d "${KERNEL_DIR}" ] && KV_DIR="${KERNEL_DIR}" + + if [ -z "${KV_DIR}" ] + then + if [ -z "${get_version_warning_done}" ]; then + get_version_warning_done=1 + qewarn "Unable to find kernel sources at ${KERNEL_DIR}" + #qeinfo "This package requires Linux sources." + if [ "${KERNEL_DIR}" == "/usr/src/linux" ] ; then + qeinfo "Please make sure that ${KERNEL_DIR} points at your running kernel, " + qeinfo "(or the kernel you wish to build against)." + qeinfo "Alternatively, set the KERNEL_DIR environment variable to the kernel sources location" + else + qeinfo "Please ensure that the KERNEL_DIR environment variable points at full Linux sources of the kernel you wish to compile against." + fi + fi + return 1 + fi + + # See if the kernel dir is actually an output dir. #454294 + if [ -z "${KBUILD_OUTPUT}" -a -L "${KERNEL_DIR}/source" ]; then + KBUILD_OUTPUT=${KERNEL_DIR} + KERNEL_DIR=$(readlink -f "${KERNEL_DIR}/source") + KV_DIR=${KERNEL_DIR} + fi + + if [ -z "${get_version_warning_done}" ]; then + qeinfo "Found kernel source directory:" + qeinfo " ${KV_DIR}" + fi + + if [ ! -s "${KV_DIR}/Makefile" ] + then + if [ -z "${get_version_warning_done}" ]; then + get_version_warning_done=1 + qeerror "Could not find a Makefile in the kernel source directory." + qeerror "Please ensure that ${KERNEL_DIR} points to a complete set of Linux sources" + fi + return 1 + fi + + # OK so now we know our sources directory, but they might be using + # KBUILD_OUTPUT, and we need this for .config and localversions-* + # so we better find it eh? + # do we pass KBUILD_OUTPUT on the CLI? + local OUTPUT_DIR=${KBUILD_OUTPUT} + + # keep track of it + KERNEL_MAKEFILE="${KV_DIR}/Makefile" + + if [[ -z ${OUTPUT_DIR} ]]; then + # Decide the function used to extract makefile variables. + local mkfunc=$(get_makefile_extract_function "${KERNEL_MAKEFILE}") + + # And if we didn't pass it, we can take a nosey in the Makefile. + OUTPUT_DIR=$(${mkfunc} KBUILD_OUTPUT "${KERNEL_MAKEFILE}") + fi + + # And contrary to existing functions I feel we shouldn't trust the + # directory name to find version information as this seems insane. + # So we parse ${KERNEL_MAKEFILE}. We should be able to trust that + # the Makefile is simple enough to use the noexec extract function. + # This has been true for every release thus far, and it's faster + # than using make to evaluate the Makefile every time. + KV_MAJOR=$(getfilevar_noexec VERSION "${KERNEL_MAKEFILE}") + KV_MINOR=$(getfilevar_noexec PATCHLEVEL "${KERNEL_MAKEFILE}") + KV_PATCH=$(getfilevar_noexec SUBLEVEL "${KERNEL_MAKEFILE}") + KV_EXTRA=$(getfilevar_noexec EXTRAVERSION "${KERNEL_MAKEFILE}") + + if [ -z "${KV_MAJOR}" -o -z "${KV_MINOR}" -o -z "${KV_PATCH}" ] + then + if [ -z "${get_version_warning_done}" ]; then + get_version_warning_done=1 + qeerror "Could not detect kernel version." + qeerror "Please ensure that ${KERNEL_DIR} points to a complete set of Linux sources." + fi + return 1 + fi + + [ -d "${OUTPUT_DIR}" ] && KV_OUT_DIR="${OUTPUT_DIR}" + if [ -n "${KV_OUT_DIR}" ]; + then + qeinfo "Found kernel object directory:" + qeinfo " ${KV_OUT_DIR}" + fi + # and if we STILL have not got it, then we better just set it to KV_DIR + KV_OUT_DIR="${KV_OUT_DIR:-${KV_DIR}}" + + # Grab the kernel release from the output directory. + # TODO: we MUST detect kernel.release being out of date, and 'return 1' from + # this function. + if [ -s "${KV_OUT_DIR}"/include/config/kernel.release ]; then + KV_LOCAL=$(<"${KV_OUT_DIR}"/include/config/kernel.release) + elif [ -s "${KV_OUT_DIR}"/.kernelrelease ]; then + KV_LOCAL=$(<"${KV_OUT_DIR}"/.kernelrelease) + else + KV_LOCAL= + fi + + # KV_LOCAL currently contains the full release; discard the first bits. + tmplocal=${KV_LOCAL#${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}${KV_EXTRA}} + + # If the updated local version was not changed, the tree is not prepared. + # Clear out KV_LOCAL in that case. + # TODO: this does not detect a change in the localversion part between + # kernel.release and the value that would be generated. + if [ "$KV_LOCAL" = "$tmplocal" ]; then + KV_LOCAL= + else + KV_LOCAL=$tmplocal + fi + + # and in newer versions we can also pull LOCALVERSION if it is set. + # but before we do this, we need to find if we use a different object directory. + # This *WILL* break if the user is using localversions, but we assume it was + # caught before this if they are. + if [[ -z ${OUTPUT_DIR} ]] ; then + # Try to locate a kernel that is most relevant for us. + for OUTPUT_DIR in "${SYSROOT}" "${ROOT%/}" "" ; do + OUTPUT_DIR+="/lib/modules/${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}${KV_EXTRA}${KV_LOCAL}/build" + if [[ -e ${OUTPUT_DIR} ]] ; then + break + fi + done + fi + + # And we should set KV_FULL to the full expanded version + KV_FULL="${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}${KV_EXTRA}${KV_LOCAL}" + + qeinfo "Found sources for kernel version:" + qeinfo " ${KV_FULL}" + + return 0 +} + +# @FUNCTION: get_running_version +# @DESCRIPTION: +# It gets the version of the current running kernel and the result is the same as get_version() if the +# function can find the sources. +get_running_version() { + if ! use kernel_linux; then + die "${FUNCNAME}() called on non-Linux system, please fix the ebuild" + fi + + KV_FULL=$(uname -r) + + if [[ -f ${ROOT%/}/lib/modules/${KV_FULL}/source/Makefile && -f ${ROOT%/}/lib/modules/${KV_FULL}/build/Makefile ]]; then + KERNEL_DIR=$(readlink -f ${ROOT%/}/lib/modules/${KV_FULL}/source) + KBUILD_OUTPUT=$(readlink -f ${ROOT%/}/lib/modules/${KV_FULL}/build) + unset KV_FULL + get_version + return $? + elif [[ -f ${ROOT%/}/lib/modules/${KV_FULL}/source/Makefile ]]; then + KERNEL_DIR=$(readlink -f ${ROOT%/}/lib/modules/${KV_FULL}/source) + unset KV_FULL + get_version + return $? + elif [[ -f ${ROOT%/}/lib/modules/${KV_FULL}/build/Makefile ]]; then + KERNEL_DIR=$(readlink -f ${ROOT%/}/lib/modules/${KV_FULL}/build) + unset KV_FULL + get_version + return $? + else + # This handles a variety of weird kernel versions. Make sure to update + # tests/linux-info_get_running_version.sh if you want to change this. + local kv_full=${KV_FULL//[-+_]*} + KV_MAJOR=$(ver_cut 1 ${kv_full}) + KV_MINOR=$(ver_cut 2 ${kv_full}) + KV_PATCH=$(ver_cut 3 ${kv_full}) + KV_EXTRA="${KV_FULL#${KV_MAJOR}.${KV_MINOR}${KV_PATCH:+.${KV_PATCH}}}" + : ${KV_PATCH:=0} + fi + return 0 +} + +# This next function is named with the eclass prefix to avoid conflicts with +# some old versionator-like eclass functions. + +# @FUNCTION: linux-info_get_any_version +# @DESCRIPTION: +# This attempts to find the version of the sources, and otherwise falls back to +# the version of the running kernel. +linux-info_get_any_version() { + if ! use kernel_linux; then + die "${FUNCNAME}() called on non-Linux system, please fix the ebuild" + fi + + if ! get_version; then + ewarn "Unable to calculate Linux Kernel version for build, attempting to use running version" + if ! get_running_version; then + die "Unable to determine any Linux Kernel version, please report a bug" + fi + fi +} + + +# ebuild check functions +# --------------------------------------- + +# @FUNCTION: check_kernel_built +# @DESCRIPTION: +# This function verifies that the current kernel sources have been already prepared otherwise it dies. +check_kernel_built() { + if ! use kernel_linux; then + die "${FUNCNAME}() called on non-Linux system, please fix the ebuild" + fi + + # if we haven't determined the version yet, we need to + require_configured_kernel + + local versionh_path + if kernel_is -ge 3 7; then + versionh_path="include/generated/uapi/linux/version.h" + else + versionh_path="include/linux/version.h" + fi + + if [ ! -f "${KV_OUT_DIR}/${versionh_path}" ] + then + eerror "These sources have not yet been prepared." + eerror "We cannot build against an unprepared tree." + eerror "To resolve this, please type the following:" + eerror + eerror "# cd ${KV_DIR}" + eerror "# make oldconfig" + eerror "# make modules_prepare" + eerror + eerror "Then please try merging this module again." + die "Kernel sources need compiling first" + fi +} + +# @FUNCTION: check_modules_supported +# @DESCRIPTION: +# This function verifies that the current kernel support modules (it checks CONFIG_MODULES=y) otherwise it dies. +check_modules_supported() { + if ! use kernel_linux; then + die "${FUNCNAME}() called on non-Linux system, please fix the ebuild" + fi + + # if we haven't determined the version yet, we need too. + require_configured_kernel + + if ! linux_chkconfig_builtin "MODULES"; then + eerror "These sources do not support loading external modules." + eerror "to be able to use this module please enable \"Loadable modules support\"" + eerror "in your kernel, recompile and then try merging this module again." + die "No support for external modules in ${KV_FULL} config" + fi +} + +# @FUNCTION: check_extra_config +# @DESCRIPTION: +# It checks the kernel config options specified by CONFIG_CHECK. It dies only when a required config option (i.e. +# the prefix ~ is not used) doesn't satisfy the directive. Ignored on non-Linux systems. +check_extra_config() { + use kernel_linux || return + + local config negate die error reworkmodulenames + local soft_errors_count=0 hard_errors_count=0 config_required=0 + # store the value of the QA check, because otherwise we won't catch usages + # after if check_extra_config is called AND other direct calls are done + # later. + local old_LINUX_CONFIG_EXISTS_DONE="${_LINUX_CONFIG_EXISTS_DONE}" + + # if we haven't determined the version yet, we need to + linux-info_get_any_version + + # Determine if we really need a .config. The only time when we don't need + # one is when all of the CONFIG_CHECK options are prefixed with "~". + for config in ${CONFIG_CHECK}; do + if [[ "${config:0:1}" != "~" ]]; then + config_required=1 + break + fi + done + + if [[ ${config_required} == 0 ]]; then + # In the case where we don't require a .config, we can now bail out + # if the user has no .config as there is nothing to do. Otherwise + # code later will cause a failure due to missing .config. + if ! linux_config_exists; then + ewarn "Unable to check for the following kernel config options due" + ewarn "to absence of any configured kernel sources or compiled" + ewarn "config:" + for config in ${CONFIG_CHECK}; do + config=${config#\~} + config=${config#\!} + local_error="ERROR_${config}" + msg="${!local_error}" + if [[ -z ${msg} ]]; then + local_error="WARNING_${config}" + msg="${!local_error}" + fi + ewarn " - ${config}${msg:+ - }${msg}" + done + ewarn "You're on your own to make sure they are set if needed." + export LINUX_CONFIG_EXISTS_DONE="${old_LINUX_CONFIG_EXISTS_DONE}" + return 0 + fi + else + require_configured_kernel + fi + + einfo "Checking for suitable kernel configuration options..." + + for config in ${CONFIG_CHECK} + do + # if we specify any fatal, ensure we honor them + die=1 + error=0 + negate=0 + reworkmodulenames=0 + + if [[ ${config:0:1} == "~" ]]; then + die=0 + config=${config:1} + elif [[ ${config:0:1} == "@" ]]; then + die=0 + reworkmodulenames=1 + config=${config:1} + fi + if [[ ${config:0:1} == "!" ]]; then + negate=1 + config=${config:1} + fi + + if [[ ${negate} == 1 ]]; then + linux_chkconfig_present ${config} && error=2 + elif [[ ${reworkmodulenames} == 1 ]]; then + local temp_config="${config//*:}" i n + config="${config//:*}" + if linux_chkconfig_present ${config}; then + for i in ${MODULE_NAMES}; do + n="${i//${temp_config}}" + [[ -z ${n//\(*} ]] && \ + MODULE_IGNORE="${MODULE_IGNORE} ${temp_config}" + done + error=2 + fi + else + linux_chkconfig_present ${config} || error=1 + fi + + if [[ ${error} > 0 ]]; then + local report_func="eerror" local_error + local_error="ERROR_${config}" + local_error="${!local_error}" + + if [[ -z "${local_error}" ]]; then + # using old, deprecated format. + local_error="${config}_ERROR" + local_error="${!local_error}" + fi + if [[ ${die} == 0 && -z "${local_error}" ]]; then + #soft errors can be warnings + local_error="WARNING_${config}" + local_error="${!local_error}" + if [[ -n "${local_error}" ]] ; then + report_func="ewarn" + fi + fi + + if [[ -z "${local_error}" ]]; then + [[ ${error} == 1 ]] \ + && local_error="is not set when it should be." \ + || local_error="should not be set. But it is." + local_error="CONFIG_${config}:\t ${local_error}" + fi + if [[ ${die} == 0 ]]; then + ${report_func} " ${local_error}" + soft_errors_count=$[soft_errors_count + 1] + else + ${report_func} " ${local_error}" + hard_errors_count=$[hard_errors_count + 1] + fi + fi + done + + if [[ ${hard_errors_count} > 0 ]]; then + eerror "Please check to make sure these options are set correctly." + eerror "Failure to do so may cause unexpected problems." + eerror "Once you have satisfied these options, please try merging" + eerror "this package again." + export LINUX_CONFIG_EXISTS_DONE="${old_LINUX_CONFIG_EXISTS_DONE}" + die "Incorrect kernel configuration options" + elif [[ ${soft_errors_count} > 0 ]]; then + ewarn "Please check to make sure these options are set correctly." + ewarn "Failure to do so may cause unexpected problems." + else + eend 0 + fi + export LINUX_CONFIG_EXISTS_DONE="${old_LINUX_CONFIG_EXISTS_DONE}" +} + +check_zlibinflate() { + if ! use kernel_linux; then + die "${FUNCNAME}() called on non-Linux system, please fix the ebuild" + fi + + # if we haven't determined the version yet, we need to + require_configured_kernel + + # although I restructured this code - I really really really dont support it! + + # bug #27882 - zlib routines are only linked into the kernel + # if something compiled into the kernel calls them + # + # plus, for the cloop module, it appears that there's no way + # to get cloop.o to include a static zlib if CONFIG_MODVERSIONS + # is on + + local INFLATE + local DEFLATE + + einfo "Determining the usability of ZLIB_INFLATE support in your kernel" + + ebegin "checking ZLIB_INFLATE" + linux_chkconfig_builtin CONFIG_ZLIB_INFLATE + eend $? || die + + ebegin "checking ZLIB_DEFLATE" + linux_chkconfig_builtin CONFIG_ZLIB_DEFLATE + eend $? || die + + local LINENO_START + local LINENO_END + local SYMBOLS + local x + + LINENO_END="$(grep -n 'CONFIG_ZLIB_INFLATE y' ${KV_DIR}/lib/Config.in | cut -d : -f 1)" + LINENO_START="$(head -n $LINENO_END ${KV_DIR}/lib/Config.in | grep -n 'if \[' | tail -n 1 | cut -d : -f 1)" + (( LINENO_AMOUNT = $LINENO_END - $LINENO_START )) + (( LINENO_END = $LINENO_END - 1 )) + SYMBOLS="$(head -n $LINENO_END ${KV_DIR}/lib/Config.in | tail -n $LINENO_AMOUNT | sed -e 's/^.*\(CONFIG_[^\" ]*\).*/\1/g;')" + + # okay, now we have a list of symbols + # we need to check each one in turn, to see whether it is set or not + for x in $SYMBOLS ; do + if [ "${!x}" = "y" ]; then + # we have a winner! + einfo "${x} ensures zlib is linked into your kernel - excellent" + return 0 + fi + done + + eerror + eerror "This kernel module requires ZLIB library support." + eerror "You have enabled zlib support in your kernel, but haven't enabled" + eerror "enabled any option that will ensure that zlib is linked into your" + eerror "kernel." + eerror + eerror "Please ensure that you enable at least one of these options:" + eerror + + for x in $SYMBOLS ; do + eerror " * $x" + done + + eerror + eerror "Please remember to recompile and install your kernel, and reboot" + eerror "into your new kernel before attempting to load this kernel module." + + die "Kernel doesn't include zlib support" +} + +################################ +# Default pkg_setup +# Also used when inheriting linux-mod to force a get_version call +# @FUNCTION: linux-info_pkg_setup +# @DESCRIPTION: +# Force a get_version() call when inherited from linux-mod.eclass and then check if the kernel is configured +# to support the options specified in CONFIG_CHECK (if not null) +linux-info_pkg_setup() { + use kernel_linux || return + + linux-info_get_any_version + + if kernel_is 2 4; then + if [ "$( gcc-major-version )" -eq "4" ] ; then + echo + ewarn "Be warned !! >=sys-devel/gcc-4.0.0 isn't supported with" + ewarn "linux-2.4 (or modules building against a linux-2.4 kernel)!" + echo + ewarn "Either switch to another gcc-version (via gcc-config) or use a" + ewarn "newer kernel that supports gcc-4." + echo + ewarn "Also be aware that bugreports about gcc-4 not working" + ewarn "with linux-2.4 based ebuilds will be closed as INVALID!" + echo + fi + fi + + [ -n "${CONFIG_CHECK}" ] && check_extra_config; +} diff --git a/eclass/linux-mod.eclass b/eclass/linux-mod.eclass new file mode 100644 index 0000000..920790b --- /dev/null +++ b/eclass/linux-mod.eclass @@ -0,0 +1,758 @@ +# Copyright 1999-2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: linux-mod.eclass +# @MAINTAINER: +# kernel@gentoo.org +# @AUTHOR: +# John Mylchreest <johnm@gentoo.org>, +# Stefan Schweizer <genstef@gentoo.org> +# @BLURB: It provides the functionality required to install external modules against a kernel source tree. +# @DESCRIPTION: +# This eclass is used to interface with linux-info.eclass in such a way +# to provide the functionality and initial functions +# required to install external modules against a kernel source +# tree. + +# A Couple of env vars are available to effect usage of this eclass +# These are as follows: + +# @ECLASS-VARIABLE: MODULES_OPTIONAL_USE +# @DESCRIPTION: +# A string containing the USE flag to use for making this eclass optional +# The recommended non-empty value is 'modules' + +# @ECLASS-VARIABLE: MODULES_OPTIONAL_USE_IUSE_DEFAULT +# @DESCRIPTION: +# A boolean to control the IUSE default state for the MODULES_OPTIONAL_USE USE +# flag. Default value is unset (false). True represented by 1 or 'on', other +# values including unset treated as false. + +# @ECLASS-VARIABLE: KERNEL_DIR +# @DESCRIPTION: +# A string containing the directory of the target kernel sources. The default value is +# "/usr/src/linux" + +# @ECLASS-VARIABLE: ECONF_PARAMS +# @DESCRIPTION: +# It's a string containing the parameters to pass to econf. +# If this is not set, then econf isn't run. + +# @ECLASS-VARIABLE: BUILD_PARAMS +# @DESCRIPTION: +# It's a string with the parameters to pass to emake. + +# @ECLASS-VARIABLE: BUILD_TARGETS +# @DESCRIPTION: +# It's a string with the build targets to pass to make. The default value is "clean module" + +# @ECLASS-VARIABLE: MODULE_NAMES +# @DESCRIPTION: +# It's a string containing the modules to be built automatically using the default +# src_compile/src_install. It will only make ${BUILD_TARGETS} once in any directory. +# +# The structure of each MODULE_NAMES entry is as follows: +# +# modulename(libdir:srcdir:objdir) +# +# where: +# +# modulename = name of the module file excluding the .ko +# libdir = place in system modules directory where module is installed (by default it's misc) +# srcdir = place for ebuild to cd to before running make (by default it's ${S}) +# objdir = place the .ko and objects are located after make runs (by default it's set to srcdir) +# +# To get an idea of how these variables are used, here's a few lines +# of code from around line 540 in this eclass: +# +# einfo "Installing ${modulename} module" +# cd ${objdir} || die "${objdir} does not exist" +# insinto /lib/modules/${KV_FULL}/${libdir} +# doins ${modulename}.${KV_OBJ} || die "doins ${modulename}.${KV_OBJ} failed" +# +# For example: +# MODULE_NAMES="module_pci(pci:${S}/pci:${S}) module_usb(usb:${S}/usb:${S})" +# +# what this would do is +# +# cd "${S}"/pci +# make ${BUILD_PARAMS} ${BUILD_TARGETS} +# cd "${S}" +# insinto /lib/modules/${KV_FULL}/pci +# doins module_pci.${KV_OBJ} +# +# cd "${S}"/usb +# make ${BUILD_PARAMS} ${BUILD_TARGETS} +# cd "${S}" +# insinto /lib/modules/${KV_FULL}/usb +# doins module_usb.${KV_OBJ} + +# There is also support for automated modprobe.d file generation. +# This can be explicitly enabled by setting any of the following variables. + +# @ECLASS-VARIABLE: MODULESD_<modulename>_ENABLED +# @DESCRIPTION: +# This is used to disable the modprobe.d file generation otherwise the file will be +# always generated (unless no MODULESD_<modulename>_* variable is provided). Set to "no" to disable +# the generation of the file and the installation of the documentation. + +# @ECLASS-VARIABLE: MODULESD_<modulename>_EXAMPLES +# @DESCRIPTION: +# This is a bash array containing a list of examples which should +# be used. If you want us to try and take a guess set this to "guess". +# +# For each array_component it's added an options line in the modprobe.d file +# +# options array_component +# +# where array_component is "<modulename> options" (see modprobe.conf(5)) + +# @ECLASS-VARIABLE: MODULESD_<modulename>_ALIASES +# @DESCRIPTION: +# This is a bash array containing a list of associated aliases. +# +# For each array_component it's added an alias line in the modprobe.d file +# +# alias array_component +# +# where array_component is "wildcard <modulename>" (see modprobe.conf(5)) + +# @ECLASS-VARIABLE: MODULESD_<modulename>_ADDITIONS +# @DESCRIPTION: +# This is a bash array containing a list of additional things to +# add to the bottom of the file. This can be absolutely anything. +# Each entry is a new line. + +# @ECLASS-VARIABLE: MODULESD_<modulename>_DOCS +# @DESCRIPTION: +# This is a string list which contains the full path to any associated +# documents for <modulename>. These files are installed in the live tree. + +# @ECLASS-VARIABLE: KV_OBJ +# @DESCRIPTION: +# It's a read-only variable. It contains the extension of the kernel modules. + +inherit eutils linux-info multilib +EXPORT_FUNCTIONS pkg_setup pkg_preinst pkg_postinst src_install src_compile pkg_postrm + +case ${MODULES_OPTIONAL_USE_IUSE_DEFAULT:-n} in + [nNfF]*|[oO][fF]*|0|-) _modules_optional_use_iuse_default='' ;; + *) _modules_optional_use_iuse_default='+' ;; +esac + +[[ -n "${_modules_optional_use_iuse_default}" ]] && case ${EAPI:-0} in + 0) die "EAPI=${EAPI} is not supported with MODULES_OPTIONAL_USE_IUSE_DEFAULT due to lack of IUSE defaults" ;; +esac + +IUSE="kernel_linux ${MODULES_OPTIONAL_USE:+${_modules_optional_use_iuse_default}}${MODULES_OPTIONAL_USE}" +SLOT="0" +RDEPEND="${MODULES_OPTIONAL_USE}${MODULES_OPTIONAL_USE:+? (} kernel_linux? ( virtual/modutils ) ${MODULES_OPTIONAL_USE:+)}" +DEPEND="${RDEPEND} + ${MODULES_OPTIONAL_USE}${MODULES_OPTIONAL_USE:+? (} + sys-apps/sed + kernel_linux? ( virtual/linux-sources virtual/libelf ) + ${MODULES_OPTIONAL_USE:+)}" + +# eclass utilities +# ---------------------------------- + +check_vermagic() { + debug-print-function ${FUNCNAME} $* + + local curr_gcc_ver=$(gcc -dumpversion) + local tmpfile old_chost old_gcc_ver result=0 + [ -n "${MODULES_OPTIONAL_USE}" ] && use !${MODULES_OPTIONAL_USE} && return + + tmpfile=`find "${KV_DIR}/" -iname "*.o.cmd" -exec grep usr/lib/gcc {} \; -quit` + tmpfile=${tmpfile//*usr/lib} + tmpfile=${tmpfile//\/include*} + old_chost=${tmpfile//*gcc\/} + old_chost=${old_chost//\/*} + old_gcc_ver=${tmpfile//*\/} + + if [[ -z ${old_gcc_ver} || -z ${old_chost} ]]; then + ewarn "" + ewarn "Unable to detect what version of GCC was used to compile" + ewarn "the kernel. Build will continue, but you may experience problems." + elif [[ ${curr_gcc_ver} != ${old_gcc_ver} ]]; then + ewarn "" + ewarn "The version of GCC you are using (${curr_gcc_ver}) does" + ewarn "not match the version of GCC used to compile the" + ewarn "kernel (${old_gcc_ver})." + result=1 + elif [[ ${CHOST} != ${old_chost} ]]; then + ewarn "" + ewarn "The current CHOST (${CHOST}) does not match the chost" + ewarn "used when compiling the kernel (${old_chost})." + result=1 + fi + + if [[ ${result} -gt 0 ]]; then + ewarn "" + ewarn "Build will not continue, because you will experience problems." + ewarn "To fix this either change the version of GCC you wish to use" + ewarn "to match the kernel, or recompile the kernel first." + die "GCC Version Mismatch." + fi +} + +# @FUNCTION: use_m +# @RETURN: true or false +# @DESCRIPTION: +# It checks if the kernel version is greater than 2.6.5. +use_m() { + debug-print-function ${FUNCNAME} $* + + # if we haven't determined the version yet, we need too. + get_version; + + # if the kernel version is greater than 2.6.6 then we should use + # M= instead of SUBDIRS= + [ ${KV_MAJOR} -eq 3 ] && return 0 + [ ${KV_MAJOR} -eq 2 -a ${KV_MINOR} -gt 5 -a ${KV_PATCH} -gt 5 ] && \ + return 0 || return 1 +} + +# @FUNCTION: convert_to_m +# @USAGE: /path/to/the/file +# @DESCRIPTION: +# It converts a file (e.g. a makefile) to use M= instead of SUBDIRS= +convert_to_m() { + debug-print-function ${FUNCNAME} $* + + if use_m + then + [ ! -f "${1}" ] && \ + die "convert_to_m() requires a filename as an argument" + ebegin "Converting ${1/${WORKDIR}\//} to use M= instead of SUBDIRS=" + sed -i 's:SUBDIRS=:M=:g' "${1}" + eend $? + fi +} + +# internal function +# +# FUNCTION: update_depmod +# DESCRIPTION: +# It updates the modules.dep file for the current kernel. +update_depmod() { + debug-print-function ${FUNCNAME} $* + + # if we haven't determined the version yet, we need too. + get_version; + + ebegin "Updating module dependencies for ${KV_FULL}" + if [ -r "${KV_OUT_DIR}"/System.map ] + then + depmod -ae -F "${KV_OUT_DIR}"/System.map -b "${ROOT:-/}" ${KV_FULL} + eend $? + else + ewarn + ewarn "${KV_OUT_DIR}/System.map not found." + ewarn "You must manually update the kernel module dependencies using depmod." + eend 1 + ewarn + fi +} + +# internal function +# +# FUNCTION: move_old_moduledb +# DESCRIPTION: +# It updates the location of the database used by the module-rebuild utility. +move_old_moduledb() { + debug-print-function ${FUNCNAME} $* + + local OLDDIR="${ROOT%/}"/usr/share/module-rebuild + local NEWDIR="${ROOT%/}"/var/lib/module-rebuild + + if [[ -f "${OLDDIR}"/moduledb ]]; then + [[ ! -d "${NEWDIR}" ]] && mkdir -p "${NEWDIR}" + [[ ! -f "${NEWDIR}"/moduledb ]] && \ + mv "${OLDDIR}"/moduledb "${NEWDIR}"/moduledb + rm -f "${OLDDIR}"/* + rmdir "${OLDDIR}" + fi +} + +# internal function +# +# FUNCTION: update_moduledb +# DESCRIPTION: +# It adds the package to the /var/lib/module-rebuild/moduledb database used by the module-rebuild utility. +update_moduledb() { + debug-print-function ${FUNCNAME} $* + + local MODULEDB_DIR="${ROOT%/}"/var/lib/module-rebuild + move_old_moduledb + + if [[ ! -f "${MODULEDB_DIR}"/moduledb ]]; then + [[ ! -d "${MODULEDB_DIR}" ]] && mkdir -p "${MODULEDB_DIR}" + touch "${MODULEDB_DIR}"/moduledb + fi + + if ! grep -qs ${CATEGORY}/${PN}-${PVR} "${MODULEDB_DIR}"/moduledb ; then + einfo "Adding module to moduledb." + echo "a:1:${CATEGORY}/${PN}-${PVR}" >> "${MODULEDB_DIR}"/moduledb + fi +} + +# internal function +# +# FUNCTION: remove_moduledb +# DESCRIPTION: +# It removes the package from the /var/lib/module-rebuild/moduledb database used by +# the module-rebuild utility. +remove_moduledb() { + debug-print-function ${FUNCNAME} $* + + local MODULEDB_DIR="${ROOT%/}"/var/lib/module-rebuild + move_old_moduledb + + if grep -qs ${CATEGORY}/${PN}-${PVR} "${MODULEDB_DIR}"/moduledb ; then + einfo "Removing ${CATEGORY}/${PN}-${PVR} from moduledb." + sed -i -e "/.*${CATEGORY}\/${PN}-${PVR}.*/d" "${MODULEDB_DIR}"/moduledb + fi +} + +# @FUNCTION: set_kvobj +# @DESCRIPTION: +# It sets the KV_OBJ variable. +set_kvobj() { + debug-print-function ${FUNCNAME} $* + + if kernel_is ge 2 6 + then + KV_OBJ="ko" + else + KV_OBJ="o" + fi + # Do we really need to know this? + # Lets silence it. + # einfo "Using KV_OBJ=${KV_OBJ}" +} + +get-KERNEL_CC() { + debug-print-function ${FUNCNAME} $* + + if [[ -n ${KERNEL_CC} ]] ; then + echo "${KERNEL_CC}" + return + fi + + local kernel_cc + if [ -n "${KERNEL_ABI}" ]; then + # In future, an arch might want to define CC_$ABI + #kernel_cc="$(get_abi_CC)" + #[ -z "${kernel_cc}" ] && + kernel_cc="$(tc-getCC $(ABI=${KERNEL_ABI} get_abi_CHOST))" + else + kernel_cc=$(tc-getCC) + fi + echo "${kernel_cc}" +} + +# internal function +# +# FUNCTION: +# USAGE: /path/to/the/modulename_without_extension +# RETURN: A file in /etc/modprobe.d +# DESCRIPTION: +# This function will generate and install the neccessary modprobe.d file from the +# information contained in the modules exported parms. +# (see the variables MODULESD_<modulename>_ENABLED, MODULESD_<modulename>_EXAMPLES, +# MODULESD_<modulename>_ALIASES, MODULESD_<modulename>_ADDITION and MODULESD_<modulename>_DOCS). +# +# At the end the documentation specified with MODULESD_<modulename>_DOCS is installed. +generate_modulesd() { + debug-print-function ${FUNCNAME} $* + [ -n "${MODULES_OPTIONAL_USE}" ] && use !${MODULES_OPTIONAL_USE} && return + + local currm_path currm currm_t t myIFS myVAR + local module_docs module_enabled module_aliases \ + module_additions module_examples module_modinfo module_opts + + for currm_path in ${@} + do + currm=${currm_path//*\/} + currm=$(echo ${currm} | tr '[:lower:]' '[:upper:]') + currm_t=${currm} + while [[ -z ${currm_t//*-*} ]]; do + currm_t=${currm_t/-/_} + done + + module_docs="$(eval echo \${MODULESD_${currm_t}_DOCS})" + module_enabled="$(eval echo \${MODULESD_${currm_t}_ENABLED})" + module_aliases="$(eval echo \${#MODULESD_${currm_t}_ALIASES[*]})" + module_additions="$(eval echo \${#MODULESD_${currm_t}_ADDITIONS[*]})" + module_examples="$(eval echo \${#MODULESD_${currm_t}_EXAMPLES[*]})" + + [[ ${module_aliases} -eq 0 ]] && unset module_aliases + [[ ${module_additions} -eq 0 ]] && unset module_additions + [[ ${module_examples} -eq 0 ]] && unset module_examples + + # If we specify we dont want it, then lets exit, otherwise we assume + # that if its set, we do want it. + [[ ${module_enabled} == no ]] && return 0 + + # unset any unwanted variables. + for t in ${!module_*} + do + [[ -z ${!t} ]] && unset ${t} + done + + [[ -z ${!module_*} ]] && return 0 + + # OK so now if we have got this far, then we know we want to continue + # and generate the modprobe.d file. + module_modinfo="$(modinfo -p ${currm_path}.${KV_OBJ})" + module_config="${T}/modulesd-${currm}" + + ebegin "Preparing file for modprobe.d" + #----------------------------------------------------------------------- + echo "# modprobe.d configuration file for ${currm}" >> "${module_config}" + #----------------------------------------------------------------------- + [[ -n ${module_docs} ]] && \ + echo "# For more information please read:" >> "${module_config}" + for t in ${module_docs} + do + echo "# ${t//*\/}" >> "${module_config}" + done + echo >> "${module_config}" + + #----------------------------------------------------------------------- + if [[ ${module_aliases} -gt 0 ]] + then + echo "# Internal Aliases - Do not edit" >> "${module_config}" + echo "# ------------------------------" >> "${module_config}" + + for((t=0; t<${module_aliases}; t++)) + do + echo "alias $(eval echo \${MODULESD_${currm}_ALIASES[$t]})" \ + >> "${module_config}" + done + echo '' >> "${module_config}" + fi + + #----------------------------------------------------------------------- + if [[ -n ${module_modinfo} ]] + then + echo >> "${module_config}" + echo "# Configurable module parameters" >> "${module_config}" + echo "# ------------------------------" >> "${module_config}" + myIFS="${IFS}" + IFS="$(echo -en "\n\b")" + + for t in ${module_modinfo} + do + myVAR="$(echo ${t#*:} | grep -o "[^ ]*[0-9][ =][^ ]*" | tail -1 | grep -o "[0-9]")" + if [[ -n ${myVAR} ]] + then + module_opts="${module_opts} ${t%%:*}:${myVAR}" + fi + echo -e "# ${t%%:*}:\t${t#*:}" >> "${module_config}" + done + IFS="${myIFS}" + echo '' >> "${module_config}" + fi + + #----------------------------------------------------------------------- + if [[ $(eval echo \${MODULESD_${currm}_ALIASES[0]}) == guess ]] + then + # So lets do some guesswork eh? + if [[ -n ${module_opts} ]] + then + echo "# For Example..." >> "${module_config}" + echo "# --------------" >> "${module_config}" + for t in ${module_opts} + do + echo "# options ${currm} ${t//:*}=${t//*:}" >> "${module_config}" + done + echo '' >> "${module_config}" + fi + elif [[ ${module_examples} -gt 0 ]] + then + echo "# For Example..." >> "${module_config}" + echo "# --------------" >> "${module_config}" + for((t=0; t<${module_examples}; t++)) + do + echo "options $(eval echo \${MODULESD_${currm}_EXAMPLES[$t]})" \ + >> "${module_config}" + done + echo '' >> "${module_config}" + fi + + #----------------------------------------------------------------------- + if [[ ${module_additions} -gt 0 ]] + then + for((t=0; t<${module_additions}; t++)) + do + echo "$(eval echo \${MODULESD_${currm}_ADDITIONS[$t]})" \ + >> "${module_config}" + done + echo '' >> "${module_config}" + fi + + #----------------------------------------------------------------------- + + # then we install it + insinto /etc/modprobe.d + newins "${module_config}" "${currm_path//*\/}.conf" + + # and install any documentation we might have. + [[ -n ${module_docs} ]] && dodoc ${module_docs} + done + eend 0 + return 0 +} + +# internal function +# +# FUNCTION: find_module_params +# USAGE: A string "NAME(LIBDIR:SRCDIR:OBJDIR)" +# RETURN: The string "modulename:NAME libdir:LIBDIR srcdir:SRCDIR objdir:OBJDIR" +# DESCRIPTION: +# Analyze the specification NAME(LIBDIR:SRCDIR:OBJDIR) of one module as described in MODULE_NAMES. +find_module_params() { + debug-print-function ${FUNCNAME} $* + + local matched_offset=0 matched_opts=0 test="${@}" temp_var result + local i=0 y=0 z=0 + + for((i=0; i<=${#test}; i++)) + do + case ${test:${i}:1} in + \() matched_offset[0]=${i};; + \:) matched_opts=$((${matched_opts} + 1)); + matched_offset[${matched_opts}]="${i}";; + \)) matched_opts=$((${matched_opts} + 1)); + matched_offset[${matched_opts}]="${i}";; + esac + done + + for((i=0; i<=${matched_opts}; i++)) + do + # i = offset were working on + # y = last offset + # z = current offset - last offset + # temp_var = temporary name + case ${i} in + 0) tempvar=${test:0:${matched_offset[0]}};; + *) y=$((${matched_offset[$((${i} - 1))]} + 1)) + z=$((${matched_offset[${i}]} - ${matched_offset[$((${i} - 1))]})); + z=$((${z} - 1)) + tempvar=${test:${y}:${z}};; + esac + + case ${i} in + 0) result="${result} modulename:${tempvar}";; + 1) result="${result} libdir:${tempvar}";; + 2) result="${result} srcdir:${tempvar}";; + 3) result="${result} objdir:${tempvar}";; + esac + done + + echo ${result} +} + +# default ebuild functions +# -------------------------------- + +# @FUNCTION: linux-mod_pkg_setup +# @DESCRIPTION: +# It checks the CONFIG_CHECK options (see linux-info.eclass(5)), verifies that the kernel is +# configured, verifies that the sources are prepared, verifies that the modules support is builtin +# in the kernel and sets the object extension KV_OBJ. +linux-mod_pkg_setup() { + debug-print-function ${FUNCNAME} $* + [ -n "${MODULES_OPTIONAL_USE}" ] && use !${MODULES_OPTIONAL_USE} && return + + local is_bin="${MERGE_TYPE}" + + # If we are installing a binpkg, take a different path. + # use MERGE_TYPE if available (eapi>=4); else use non-PMS EMERGE_FROM (eapi<4) + if has ${EAPI} 0 1 2 3; then + is_bin=${EMERGE_FROM} + fi + + if [[ ${is_bin} == binary ]]; then + linux-mod_pkg_setup_binary + return + fi + + # External modules use kernel symbols (bug #591832) + CONFIG_CHECK+=" !TRIM_UNUSED_KSYMS" + + linux-info_pkg_setup; + require_configured_kernel + check_kernel_built; + strip_modulenames; + [[ -n ${MODULE_NAMES} ]] && check_modules_supported + set_kvobj; + # Commented out with permission from johnm until a fixed version for arches + # who intentionally use different kernel and userland compilers can be + # introduced - Jason Wever <weeve@gentoo.org>, 23 Oct 2005 + #check_vermagic; +} + +# @FUNCTION: linux-mod_pkg_setup_binary +# @DESCRIPTION: +# Perform all kernel option checks non-fatally, as the .config and +# /proc/config.gz might not be present. Do not do anything that requires kernel +# sources. +linux-mod_pkg_setup_binary() { + debug-print-function ${FUNCNAME} $* + local new_CONFIG_CHECK + # ~ needs always to be quoted, else bash expands it. + for config in $CONFIG_CHECK ; do + optional='~' + [[ ${config:0:1} == "~" ]] && optional='' + new_CONFIG_CHECK="${new_CONFIG_CHECK} ${optional}${config}" + done + CONFIG_CHECK="${new_CONFIG_CHECK}" + linux-info_pkg_setup; +} + +strip_modulenames() { + debug-print-function ${FUNCNAME} $* + + local i + for i in ${MODULE_IGNORE}; do + MODULE_NAMES=${MODULE_NAMES//${i}(*} + done +} + +# @FUNCTION: linux-mod_src_compile +# @DESCRIPTION: +# It compiles all the modules specified in MODULE_NAMES. For each module the econf command is +# executed only if ECONF_PARAMS is defined, the name of the target is specified by BUILD_TARGETS +# while the options are in BUILD_PARAMS (all the modules share these variables). The compilation +# happens inside ${srcdir}. +# +# Look at the description of these variables for more details. +linux-mod_src_compile() { + debug-print-function ${FUNCNAME} $* + [ -n "${MODULES_OPTIONAL_USE}" ] && use !${MODULES_OPTIONAL_USE} && return + + local modulename libdir srcdir objdir i n myABI="${ABI}" + set_arch_to_kernel + ABI="${KERNEL_ABI}" + + BUILD_TARGETS=${BUILD_TARGETS:-clean module} + strip_modulenames; + cd "${S}" + touch Module.symvers + for i in ${MODULE_NAMES} + do + unset libdir srcdir objdir + for n in $(find_module_params ${i}) + do + eval ${n/:*}=${n/*:/} + done + libdir=${libdir:-misc} + srcdir=${srcdir:-${S}} + objdir=${objdir:-${srcdir}} + + if [ ! -f "${srcdir}/.built" ]; + then + cd "${srcdir}" + ln -s "${S}"/Module.symvers Module.symvers + einfo "Preparing ${modulename} module" + if [[ -n ${ECONF_PARAMS} ]] + then + econf ${ECONF_PARAMS} || \ + die "Unable to run econf ${ECONF_PARAMS}" + fi + + # This looks messy, but it is needed to handle multiple variables + # being passed in the BUILD_* stuff where the variables also have + # spaces that must be preserved. If don't do this, then the stuff + # inside the variables gets used as targets for Make, which then + # fails. + eval "emake HOSTCC=\"$(tc-getBUILD_CC)\" \ + CROSS_COMPILE=${CHOST}- \ + LDFLAGS=\"$(get_abi_LDFLAGS)\" \ + ${BUILD_FIXES} \ + ${BUILD_PARAMS} \ + ${BUILD_TARGETS} " \ + || die "Unable to emake HOSTCC="$(tc-getBUILD_CC)" CROSS_COMPILE=${CHOST}- LDFLAGS="$(get_abi_LDFLAGS)" ${BUILD_FIXES} ${BUILD_PARAMS} ${BUILD_TARGETS}" + cd "${OLDPWD}" + touch "${srcdir}"/.built + fi + done + + set_arch_to_portage + ABI="${myABI}" +} + +# @FUNCTION: linux-mod_src_install +# @DESCRIPTION: +# It install the modules specified in MODULES_NAME. The modules should be inside the ${objdir} +# directory and they are installed inside /lib/modules/${KV_FULL}/${libdir}. +# +# The modprobe.d configuration file is automatically generated if the +# MODULESD_<modulename>_* variables are defined. The only way to stop this process is by +# setting MODULESD_<modulename>_ENABLED=no. At the end the documentation specified via +# MODULESD_<modulename>_DOCS is also installed. +# +# Look at the description of these variables for more details. +linux-mod_src_install() { + debug-print-function ${FUNCNAME} $* + [ -n "${MODULES_OPTIONAL_USE}" ] && use !${MODULES_OPTIONAL_USE} && return + + local modulename libdir srcdir objdir i n + + strip_modulenames; + for i in ${MODULE_NAMES} + do + unset libdir srcdir objdir + for n in $(find_module_params ${i}) + do + eval ${n/:*}=${n/*:/} + done + libdir=${libdir:-misc} + srcdir=${srcdir:-${S}} + objdir=${objdir:-${srcdir}} + + einfo "Installing ${modulename} module" + cd "${objdir}" || die "${objdir} does not exist" + insinto /lib/modules/${KV_FULL}/${libdir} + doins ${modulename}.${KV_OBJ} || die "doins ${modulename}.${KV_OBJ} failed" + cd "${OLDPWD}" + + generate_modulesd "${objdir}/${modulename}" + done +} + +# @FUNCTION: linux-mod_pkg_preinst +# @DESCRIPTION: +# It checks what to do after having merged the package. +linux-mod_pkg_preinst() { + debug-print-function ${FUNCNAME} $* + [ -n "${MODULES_OPTIONAL_USE}" ] && use !${MODULES_OPTIONAL_USE} && return + + [ -d "${D%/}/lib/modules" ] && UPDATE_DEPMOD=true || UPDATE_DEPMOD=false + [ -d "${D%/}/lib/modules" ] && UPDATE_MODULEDB=true || UPDATE_MODULEDB=false +} + +# @FUNCTION: linux-mod_pkg_postinst +# @DESCRIPTION: +# It executes /sbin/depmod and adds the package to the /var/lib/module-rebuild/moduledb +# database (if ${D}/lib/modules is created)" +linux-mod_pkg_postinst() { + debug-print-function ${FUNCNAME} $* + [ -n "${MODULES_OPTIONAL_USE}" ] && use !${MODULES_OPTIONAL_USE} && return + + ${UPDATE_DEPMOD} && update_depmod; + ${UPDATE_MODULEDB} && update_moduledb; +} + +# @FUNCTION: linux-mod_pkg_postrm +# @DESCRIPTION: +# It removes the package from the /var/lib/module-rebuild/moduledb database but it doens't +# call /sbin/depmod because the modules are still installed. +linux-mod_pkg_postrm() { + debug-print-function ${FUNCNAME} $* + [ -n "${MODULES_OPTIONAL_USE}" ] && use !${MODULES_OPTIONAL_USE} && return + remove_moduledb; +} |