diff options
author | V3n3RiX <venerix@redcorelinux.org> | 2017-10-09 18:53:29 +0100 |
---|---|---|
committer | V3n3RiX <venerix@redcorelinux.org> | 2017-10-09 18:53:29 +0100 |
commit | 4f2d7949f03e1c198bc888f2d05f421d35c57e21 (patch) | |
tree | ba5f07bf3f9d22d82e54a462313f5d244036c768 /eclass/perl-functions.eclass |
reinit the tree, so we can have metadata
Diffstat (limited to 'eclass/perl-functions.eclass')
-rw-r--r-- | eclass/perl-functions.eclass | 587 |
1 files changed, 587 insertions, 0 deletions
diff --git a/eclass/perl-functions.eclass b/eclass/perl-functions.eclass new file mode 100644 index 000000000000..96e9a59e8904 --- /dev/null +++ b/eclass/perl-functions.eclass @@ -0,0 +1,587 @@ +# Copyright 1999-2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: perl-functions.eclass +# @MAINTAINER: +# perl@gentoo.org +# @AUTHOR: +# Seemant Kulleen <seemant@gentoo.org> +# Andreas K. Huettel <dilfridge@gentoo.org> +# Kent Fredric <kentnl@gentoo.org> +# @BLURB: helper functions eclass for perl modules +# @DESCRIPTION: +# The perl-functions eclass is designed to allow easier installation of perl +# modules, and their incorporation into the Gentoo Linux system. +# It provides helper functions, no phases or variable manipulation in +# global scope. + +[[ ${CATEGORY} == "perl-core" ]] && inherit alternatives + +case "${EAPI:-0}" in + 5|6) + ;; + *) + die "EAPI=${EAPI} is not supported by perl-functions.eclass" + ;; +esac + +perlinfo_done=false + +# @FUNCTION: perl_set_version +# @DESCRIPTION: +# Extract version information and installation paths from the current Perl +# interpreter. +# +# This sets the following variables: PERL_VERSION, SITE_ARCH, SITE_LIB, +# ARCH_LIB, VENDOR_LIB, VENDOR_ARCH +# +# This function used to be called perlinfo as well. +# +# Example: +# @CODE +# perl_set_version +# echo $PERL_VERSION +# @CODE +perl_set_version() { + debug-print-function $FUNCNAME "$@" + debug-print "$FUNCNAME: perlinfo_done=${perlinfo_done}" + ${perlinfo_done} && return 0 + perlinfo_done=true + + local f version install{{site,vendor}{arch,lib},archlib} + eval "$(perl -V:{version,install{{site,vendor}{arch,lib},archlib}} )" + PERL_VERSION=${version} + SITE_ARCH=${installsitearch} + SITE_LIB=${installsitelib} + ARCH_LIB=${installarchlib} + VENDOR_LIB=${installvendorlib} + VENDOR_ARCH=${installvendorarch} +} + +# @FUNCTION: perl_delete_localpod +# @DESCRIPTION: +# Remove stray perllocal.pod files in the temporary install directory D. +# +# This function used to be called fixlocalpod as well. +perl_delete_localpod() { + debug-print-function $FUNCNAME "$@" + + find "${D}" -type f -name perllocal.pod -delete + find "${D}" -depth -mindepth 1 -type d -empty -delete +} + +# @FUNCTION: perl_fix_osx_extra +# @DESCRIPTION: +# Look through ${S} for AppleDouble encoded files and get rid of them. +perl_fix_osx_extra() { + debug-print-function $FUNCNAME "$@" + + local f + find "${S}" -type f -name "._*" -print0 | while read -rd '' f ; do + einfo "Removing AppleDouble encoded Macintosh file: ${f#${S}/}" + rm -f "${f}" + f=${f#${S}/} + grep -q "${f}" "${S}"/MANIFEST && \ + elog "AppleDouble encoded Macintosh file in MANIFEST: ${f#${S}/}" + done +} + +# @FUNCTION: perl_delete_module_manpages +# @DESCRIPTION: +# Bump off manpages installed by the current module such as *.3pm files as well +# as empty directories. +perl_delete_module_manpages() { + debug-print-function $FUNCNAME "$@" + + if [[ -d "${ED}"/usr/share/man ]] ; then + find "${ED}"/usr/share/man -type f -name "*.3pm" -delete + find "${ED}"/usr/share/man -depth -type d -empty -delete + fi +} + +# @FUNCTION: perl_delete_packlist +# @DESCRIPTION: +# Look through ${D} for .packlist files, empty .bs files and empty directories, +# and get rid of items found. +perl_delete_packlist() { + debug-print-function $FUNCNAME "$@" + perl_set_version + if [[ -d ${D}/${VENDOR_ARCH} ]] ; then + find "${D}/${VENDOR_ARCH}" -type f -a -name .packlist -delete + perl_delete_emptybsdir + fi +} + +# @FUNCTION: perl_delete_emptybsdir +# @DESCRIPTION: +# Look through ${D} for empty .bs files and empty directories, +# and get rid of items found. +perl_delete_emptybsdir() { + debug-print-function $FUNCNAME "$@" + perl_set_version + if [[ -d ${D}/${VENDOR_ARCH} ]] ; then + find "${D}/${VENDOR_ARCH}" -type f \ + -a -name '*.bs' -a -empty -delete + find "${D}" -depth -mindepth 1 -type d -empty -delete + fi +} + +# @FUNCTION: perl_fix_packlist +# @DESCRIPTION: +# Look through ${D} for .packlist text files containing the temporary installation +# folder (i.e. ${D}). If the pattern is found, silently replace it with `/'. +# Remove duplicate entries; then validate all entries in the packlist against ${D} +# and prune entries that do not correspond to installed files. +perl_fix_packlist() { + debug-print-function $FUNCNAME "$@" + + local packlist_temp="${T}/.gentoo_packlist_temp" + find "${D}" -type f -name '.packlist' -print0 | while read -rd '' f ; do + if file "${f}" | grep -q -i " text" ; then + einfo "Fixing packlist file /${f#${D}}" + + # remove the temporary build dir path + sed -i -e "s:${D}:/:g" "${f}" + + # remove duplicate entries + sort -u "${f}" > "${packlist_temp}" + mv "${packlist_temp}" "${f}" + + # remove files that dont exist + cat "${f}" | while read -r entry; do + if [ ! -e "${D}/${entry}" ]; then + einfo "Pruning surplus packlist entry ${entry}" + grep -v -x -F "${entry}" "${f}" > "${packlist_temp}" + mv "${packlist_temp}" "${f}" + fi + done + fi + done +} + +# @FUNCTION: perl_remove_temppath +# @DESCRIPTION: +# Look through ${D} for text files containing the temporary installation +# folder (i.e. ${D}). If the pattern is found, replace it with `/' and warn. +perl_remove_temppath() { + debug-print-function $FUNCNAME "$@" + + find "${D}" -type f -not -name '*.so' -print0 | while read -rd '' f ; do + if file "${f}" | grep -q -i " text" ; then + grep -q "${D}" "${f}" && ewarn "QA: File contains a temporary path ${f}" + sed -i -e "s:${D}:/:g" "${f}" + fi + done +} + +# @FUNCTION: perl_rm_files +# @USAGE: <list of files> +# @DESCRIPTION: +# Remove certain files from a Perl release and remove them from the MANIFEST +# while we're there. +# +# Most useful in src_prepare for nuking bad tests, and is highly recommended +# for any tests like 'pod.t', 'pod-coverage.t' or 'kwalitee.t', as what they +# test is completely irrelevant to end users, and frequently fail simply +# because the authors of Test::Pod... changed their recommendations, and thus +# failures are only useful feedback to Authors, not users. +# +# Removing from MANIFEST also avoids needless log messages warning +# users about files "missing from their kit". +# +# Example: +# @CODE +# src_test() { +# perl_rm_files t/pod{,-coverage}.t +# perl-module_src_test +# } +# @CODE +perl_rm_files() { + debug-print-function $FUNCNAME "$@" + local skipfile="${T}/.gentoo_makefile_skip" + local manifile="${S}/MANIFEST" + local manitemp="${T}/.gentoo_manifest_temp" + oldifs="$IFS" + IFS="\n" + for filename in "$@"; do + einfo "Removing un-needed ${filename}"; + # Remove the file + rm -f "${S}/${filename}" + [[ -e "${manifile}" ]] && echo "${filename}" >> "${skipfile}" + done + if [[ -e "${manifile}" && -e "${skipfile}" ]]; then + einfo "Fixing Manifest" + grep -v -F -f "${skipfile}" "${manifile}" > "${manitemp}" + mv -f -- "${manitemp}" "${manifile}" + rm -- "${skipfile}"; + fi + IFS="$oldifs" +} + +# @FUNCTION: perl_link_duallife_scripts +# @DESCRIPTION: +# Moves files and generates symlinks so dual-life packages installing scripts do not +# lead to file collisions. Mainly for use in pkg_postinst and pkg_postrm, and makes +# only sense for perl-core packages. +perl_link_duallife_scripts() { + debug-print-function $FUNCNAME "$@" + if [[ ${CATEGORY} != perl-core ]] || ! has_version ">=dev-lang/perl-5.8.8-r8" ; then + return 0 + fi + + local i ff + if has "${EBUILD_PHASE:-none}" "postinst" "postrm" ; then + for i in "${DUALLIFESCRIPTS[@]}" ; do + alternatives_auto_makesym "/${i}" "/${i}-[0-9]*" + done + for i in "${DUALLIFEMAN[@]}" ; do + ff=`echo "${EROOT}"/${i%.1}-${PV}-${P}.1*` + ff=${ff##*.1} + alternatives_auto_makesym "/${i}${ff}" "/${i%.1}-[0-9]*" + done + else + pushd "${ED}" > /dev/null + for i in $(find usr/bin -maxdepth 1 -type f 2>/dev/null) ; do + mv ${i}{,-${PV}-${P}} || die + #DUALLIFESCRIPTS[${#DUALLIFESCRIPTS[*]}]=${i##*/} + DUALLIFESCRIPTS[${#DUALLIFESCRIPTS[*]}]=${i} + done + for i in $(find usr/share/man/man1 -maxdepth 1 -type f 2>/dev/null) ; do + mv ${i} ${i%.1}-${PV}-${P}.1 || die + DUALLIFEMAN[${#DUALLIFEMAN[*]}]=${i} + done + popd > /dev/null + fi +} + +# @FUNCTION: perl_check_env +# @DESCRIPTION: +# Checks a blacklist of known-suspect ENV values that can be accidentally set by users +# doing personal perl work, which may accidentally leak into portage and break the +# system perl installaton. +# Dies if any of the suspect fields are found, and tell the user what needs to be unset. +# There's a workaround, but you'll have to read the code for it. +perl_check_env() { + local errored value; + + for i in PERL_MM_OPT PERL5LIB PERL5OPT PERL_MB_OPT PERL_CORE PERLPREFIX; do + # Next unless match + [ -v $i ] || continue; + + # Warn only once, and warn only when one of the bad values are set. + # record failure here. + if [ ${errored:-0} == 0 ]; then + if [ -n "${I_KNOW_WHAT_I_AM_DOING}" ]; then + elog "perl-module.eclass: Suspicious environment values found."; + else + eerror "perl-module.eclass: Suspicious environment values found."; + fi + fi + errored=1 + + # Read ENV Value + value=${!i}; + + # Print ENV name/value pair + if [ -n "${I_KNOW_WHAT_I_AM_DOING}" ]; then + elog " $i=\"$value\""; + else + eerror " $i=\"$value\""; + fi + done + + # Return if there were no failures + [ ${errored:-0} == 0 ] && return; + + # Return if user knows what they're doing + if [ -n "${I_KNOW_WHAT_I_AM_DOING}" ]; then + elog "Continuing anyway, seems you know what you're doing." + return + fi + + eerror "Your environment settings may lead to undefined behavior and/or build failures." + die "Please fix your environment ( ~/.bashrc, package.env, ... ), see above for details." +} + +# @FUNCTION: perl_doexamples +# @USAGE: <list of files or globs> +# @DESCRIPTION: +# Install example files ready-to-run. +# Is called under certain circumstances in perl-module.eclass src_install +# (see the documentation there). +# +# Example: +# @CODE +# src_install() { +# perl-module_src_install +# use examples && perl_doexamples "eg/*" +# } +# @CODE +perl_doexamples() { + debug-print-function $FUNCNAME "$@" + + einfo "Installing examples into /usr/share/doc/${PF}/examples" + + # no compression since we want ready-to-run scripts + docompress -x /usr/share/doc/${PF}/examples + + docinto examples/ + # Lack of quoting here is important in order to support glob expansion + # in DIST_EXAMPLES=( ), which is defined before source extraction occurs + dodoc -r $@ + + # is there a way to undo "docinto" ? +} + +# @FUNCTION: perl_has_module +# @USAGE: <module name> +# @RETURN: 0 if available, non-zero otherwise +# @DESCRIPTION: +# Query the installed system Perl to see if a given module is installed. +# This does **not** load the module in question, only anticipates if it *might* load. +# +# This is primarily for the purposes of dependency weakening so that conditional +# behaviour can be triggered without adding dependencies to portage which would confuse +# a dependency resolver. +# +# returns 'true' if the module is available, returns error if the module is not available +# +# Example: +# @CODE +# perl_has_module "Test::Tester" && echo "Test::Tester installed" +# @CODE + +perl_has_module() { + debug-print-function $FUNCNAME "$@" + + [[ $# -gt 0 ]] || die "${FUNCNAME}: No module name provided" + [[ $# -lt 2 ]] || die "${FUNCNAME}: Too many parameters ($#)" + + perl -we 'my $mn = $ARGV[0]; + $mn =~ s{(::|\x{27})}{/}g; + for(@INC){ + next if ref $_; + exit 0 if -r $_ . q[/] . $mn . q[.pm] + } + exit 1' "$@"; +} + +# @FUNCTION: perl_has_module_version +# @USAGE: <module name> <minimum upstream version> +# @RETURN: 0 if satisfied, non-zero otherwise +# @DESCRIPTION: +# Query the installed system Perl to see if a given module is installed +# and is at least a given version. +# +# This requires more caution to use than perl_has_module as it requires +# loading the module in question to determine version compatibility, +# which can be SLOW, and can have side effects (ie: compilation fails in +# require due to some dependency, resulting in a "Fail") +# +# Also take care to note the module version is a *minimum*, *must* be +# written in upstream versions format and should be a a legal upstream version +# +# returns a true exit code if the module is both available and is at least +# the specified version +# +# Example: +# @CODE +# perl_has_module_version "Test::Tester" "0.017" \ +# && echo "Test::Tester 0.017 or greater installed" +# @CODE +perl_has_module_version() { + debug-print-function $FUNCNAME "$@" + + [[ $# -gt 0 ]] || die "${FUNCNAME}: No module name provided" + [[ $# -gt 1 ]] || die "${FUNCNAME}: No module version provided" + [[ $# -lt 3 ]] || die "${FUNCNAME}: Too many parameters ($#)" + + perl -we 'my $mn = $ARGV[0]; + $mn =~ s{(::|\x{27})}{/}g; + exit ( eval { + require qq[${mn}.pm]; + $ARGV[0]->VERSION($ARGV[1]); + 1 + } ? 0 : 1 )' "$@" +} + +# @FUNCTION: perl_get_module_version +# @USAGE: <module name> +# @RETURN: 0 if module available, non-zero if error +# @DESCRIPTION: +# Query the installed system perl to report the version of the installed +# module. +# +# Note this should be strictly for diagnostic purposes to the end user, +# and may be of selective use in pkg_info to enhance +# emerge --info reports. +# +# Anything that does version comparisons **must not** use the return value +# from this function +# +# Also note that this **must** at least attempt load the module in +# question as part of its operation, and is subsequently prone to SLOWness. +# +# Return codes return error in both compilation-failure and not-installed cases. +# +# Example: +# @CODE +# MODVER=$(perl_get_module_version "Test::Simple") \ +# || die "Test::Simple not installed: $MODVER" +# @CODE + +perl_get_module_version() { + debug-print-function $FUNCNAME "$@" + + [[ $# -gt 0 ]] || die "${FUNCNAME}: No module name provided" + [[ $# -lt 2 ]] || die "${FUNCNAME}: Too many parameters ($#)" + + if ! perl_has_module "$@" ; then + echo "(Not Installed)"; + return 1; + fi + + # Todo: What do we do if require fails? spew to stderr + # or stay silent? + + perl -we 'my $mn = $ARGV[0]; + $mn =~ s{(::|\x{27})}{/}g; + local $@; + eval { require qq[${mn}.pm]; 1 } or do { + print q[(Compilation failed in require)]; + exit 1; + }; + my $stash = \%{ $ARGV[0] . q[::] }; + if ( not exists $stash->{VERSION} ) { + print q[(No VERSION property)]; + exit 0; + } + if ( not defined ${$stash->{VERSION}} ) { + print q[(undef)]; + exit 0; + } + print ${$stash->{VERSION}}; + exit 0; ' "$@" +} + +# @FUNCTION: perl_get_raw_vendorlib +# @DESCRIPTION: +# Convenience function to optimise for a common case without double-handling +# variables everywhere. +# +# Note: Will include EPREFIX where relevant +# +# Example: +# @CODE +# my_raw_vendorlib="$(perl_get_raw_vendorlib)" +# @CODE + +perl_get_raw_vendorlib() { + debug-print-function $FUNCNAME "$@" + + [[ $# -lt 1 ]] || die "${FUNCNAME}: Too many parameters ($#)" + + perl -MConfig \ + -e'exists $Config{$ARGV[0]} || die qq{No such Config key "$ARGV[0]"}; + print $Config{$ARGV[0]}; + exit 0' -- "installvendorlib" || die "Can't extract installvendorlib from Perl Configuration" +} + +# @FUNCTION: perl_get_vendorlib +# @DESCRIPTION: +# Convenience helper for returning Perls' vendor install root +# without EPREFIXing. +# +# Example: +# @CODE +# my_vendorlib="$(perl_get_vendorlib)" +# @CODE + +perl_get_vendorlib() { + debug-print-function $FUNCNAME "$@" + + [[ $# -lt 1 ]] || die "${FUNCNAME}: Too many parameters ($#)" + + # Requires perl 5.14 for /r attribute of s/// + # Just in case somebody out there is stuck in a time warp: upgrade perl first + perl -M5.014 -MConfig \ + -e'exists $Config{$ARGV[0]} || die qq{No such Config key "$ARGV[0]"}; + print $Config{$ARGV[0]} =~ s{\A\Q$ARGV[1]\E}{}r; + exit 0' -- "installvendorlib" "$EPREFIX" || die "Can't extract installvendorlib from Perl Configuration" +} + +# @FUNCTION: perl_domodule +# @USAGE: [-C <target>] [-r] <files> +# @DESCRIPTION: +# Installs files in paths where they can be found in the default +# Perl runtime. +# +# Note: Should only be used in src_install or pkg_preinst +# anywhere else will do the wrong thing or die. +# +# The contents of the <files> list are copied into Perls Vendor library path +# as follows: +# @CODE +# # install perl/File.pm as Samba::File +# pushd perl/ +# perl_domodule -C Samba File.pm +# +# # install perl/ recursively under VENDORLIB/Samba/ +# pushd perl/ +# perl_domodule -C Samba -r . +# @CODE +# +# @CODE +# options: +# -C Target/Name +# The subdirectory relative to the Perl VENDOR_LIB +# to install into. +# +# defaults to "" +# -r +# Install directories recursively ( see doins ) +# files: +# list of .pm files to install to VENDORLIB +# @CODE + +perl_domodule() { + local target_prefix="" + local files=() + local doins_opts=() + + local recursive="false" + local target + local file + + while [[ $# -gt 0 ]] ; do + case $1 in + -C|--target-prefix) + [[ -z "${2}" || "${2:0:1}" == "-" ]] && die "${FUNCNAME}: -C|--target-prefix expects an argument, got \"$2\"!" + target_prefix="${2}"; + shift 2;; + -r) + recursive="true" + shift;; + *) + [[ -z "${1}" || "${1:0:1}" == "-" ]] && die "${FUNCNAME}: Unknown argument \"${1}\"!" + files+=( "${1}" ) + shift 1;; + esac + done + + if [[ "true" == $recursive ]]; then + doins_opts+=( "-r" ) + fi + for file in "${files[@]}"; do + [[ -e "${file}" ]] || die "$FUNCNAME: Argument \"${file}\" is not an existing file" + [[ "false" == ${recursive} && -d "${file}" ]] && die "$FUNCNAME: Argument \"${file}\" is a directory ( needs -r parameter )" + done + + target="$(perl_get_vendorlib)" + + # Extend target if target_prefix is set + [[ -z "${target_prefix}" ]] || target="${target%/}/${target_prefix#/}" + + insinto "/${target#/}" + doins "${doins_opts[@]}" "${files[@]}" +} |