kde-apps/ksirk: x86 stable (bug #661810)
[gentoo.git] / eclass / perl-functions.eclass
1 # Copyright 1999-2015 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: perl-functions.eclass
5 # @MAINTAINER:
6 # perl@gentoo.org
7 # @AUTHOR:
8 # Seemant Kulleen <seemant@gentoo.org>
9 # Andreas K. Huettel <dilfridge@gentoo.org>
10 # Kent Fredric <kentnl@gentoo.org>
11 # @BLURB: helper functions eclass for perl modules
12 # @DESCRIPTION:
13 # The perl-functions eclass is designed to allow easier installation of perl
14 # modules, and their incorporation into the Gentoo Linux system.
15 # It provides helper functions, no phases or variable manipulation in
16 # global scope.
17
18 [[ ${CATEGORY} == "perl-core" ]] && inherit alternatives
19
20 case "${EAPI:-0}" in
21         5|6)
22                 ;;
23         *)
24                 die "EAPI=${EAPI} is not supported by perl-functions.eclass"
25                 ;;
26 esac
27
28 perlinfo_done=false
29
30 # @FUNCTION: perl_set_version
31 # @DESCRIPTION:
32 # Extract version information and installation paths from the current Perl
33 # interpreter.
34 #
35 # This sets the following variables: PERL_VERSION, SITE_ARCH, SITE_LIB,
36 # ARCH_LIB, VENDOR_LIB, VENDOR_ARCH
37 #
38 # This function used to be called perlinfo as well.
39 #
40 # Example:
41 # @CODE
42 # perl_set_version
43 # echo $PERL_VERSION
44 # @CODE
45 perl_set_version() {
46         debug-print-function $FUNCNAME "$@"
47         debug-print "$FUNCNAME: perlinfo_done=${perlinfo_done}"
48         ${perlinfo_done} && return 0
49         perlinfo_done=true
50
51         local f version install{{site,vendor}{arch,lib},archlib}
52         eval "$(perl -V:{version,install{{site,vendor}{arch,lib},archlib}} )"
53         PERL_VERSION=${version}
54         SITE_ARCH=${installsitearch}
55         SITE_LIB=${installsitelib}
56         ARCH_LIB=${installarchlib}
57         VENDOR_LIB=${installvendorlib}
58         VENDOR_ARCH=${installvendorarch}
59 }
60
61 # @FUNCTION: perl_delete_localpod
62 # @DESCRIPTION:
63 # Remove stray perllocal.pod files in the temporary install directory D.
64 #
65 # This function used to be called fixlocalpod as well.
66 perl_delete_localpod() {
67         debug-print-function $FUNCNAME "$@"
68
69         find "${D}" -type f -name perllocal.pod -delete
70         find "${D}" -depth -mindepth 1 -type d -empty -delete
71 }
72
73 # @FUNCTION: perl_fix_osx_extra
74 # @DESCRIPTION:
75 # Look through ${S} for AppleDouble encoded files and get rid of them.
76 perl_fix_osx_extra() {
77         debug-print-function $FUNCNAME "$@"
78
79         local f
80         find "${S}" -type f -name "._*" -print0 | while read -rd '' f ; do
81                 einfo "Removing AppleDouble encoded Macintosh file: ${f#${S}/}"
82                 rm -f "${f}"
83                 f=${f#${S}/}
84                 grep -q "${f}" "${S}"/MANIFEST && \
85                         elog "AppleDouble encoded Macintosh file in MANIFEST: ${f#${S}/}"
86         done
87 }
88
89 # @FUNCTION: perl_delete_module_manpages
90 # @DESCRIPTION:
91 # Bump off manpages installed by the current module such as *.3pm files as well
92 # as empty directories.
93 perl_delete_module_manpages() {
94         debug-print-function $FUNCNAME "$@"
95
96         if [[ -d "${ED}"/usr/share/man ]] ; then
97                 find "${ED}"/usr/share/man -type f -name "*.3pm" -delete
98                 find "${ED}"/usr/share/man -depth -type d -empty -delete
99         fi
100 }
101
102 # @FUNCTION: perl_delete_packlist
103 # @DESCRIPTION:
104 # Look through ${D} for .packlist files, empty .bs files and empty directories,
105 # and get rid of items found.
106 perl_delete_packlist() {
107         debug-print-function $FUNCNAME "$@"
108         perl_set_version
109         if [[ -d ${D}/${VENDOR_ARCH} ]] ; then
110                 find "${D}/${VENDOR_ARCH}" -type f -a -name .packlist -delete
111                 perl_delete_emptybsdir
112         fi
113 }
114
115 # @FUNCTION: perl_delete_emptybsdir
116 # @DESCRIPTION:
117 # Look through ${D} for empty .bs files and empty directories,
118 # and get rid of items found.
119 perl_delete_emptybsdir() {
120         debug-print-function $FUNCNAME "$@"
121         perl_set_version
122         if [[ -d ${D}/${VENDOR_ARCH} ]] ; then
123                 find "${D}/${VENDOR_ARCH}" -type f \
124                         -a -name '*.bs' -a -empty -delete
125                 find "${D}" -depth -mindepth 1 -type d -empty -delete
126         fi
127 }
128
129 # @FUNCTION: perl_fix_packlist
130 # @DESCRIPTION:
131 # Look through ${D} for .packlist text files containing the temporary installation
132 # folder (i.e. ${D}). If the pattern is found, silently replace it with `/'.
133 # Remove duplicate entries; then validate all entries in the packlist against ${D}
134 # and prune entries that do not correspond to installed files.
135 perl_fix_packlist() {
136         debug-print-function $FUNCNAME "$@"
137
138         local packlist_temp="${T}/.gentoo_packlist_temp"
139         find "${D}" -type f -name '.packlist' -print0 | while read -rd '' f ; do
140                 if file "${f}" | grep -q -i " text" ; then
141                         einfo "Fixing packlist file /${f#${D}}"
142
143                         # remove the temporary build dir path
144                         sed -i -e "s:${D}:/:g" "${f}"
145
146                         # remove duplicate entries
147                         sort -u "${f}" > "${packlist_temp}"
148                         mv "${packlist_temp}" "${f}"
149
150                         # remove files that dont exist
151                         cat "${f}" | while read -r entry; do
152                                 if [ ! -e "${D}/${entry}" ]; then
153                                         einfo "Pruning surplus packlist entry ${entry}"
154                                         grep -v -x -F "${entry}" "${f}" > "${packlist_temp}"
155                                         mv "${packlist_temp}" "${f}"
156                                 fi
157                         done
158                 fi
159         done
160 }
161
162 # @FUNCTION: perl_remove_temppath
163 # @DESCRIPTION:
164 # Look through ${D} for text files containing the temporary installation
165 # folder (i.e. ${D}). If the pattern is found, replace it with `/' and warn.
166 perl_remove_temppath() {
167         debug-print-function $FUNCNAME "$@"
168
169         find "${D}" -type f -not -name '*.so' -print0 | while read -rd '' f ; do
170                 if file "${f}" | grep -q -i " text" ; then
171                         grep -q "${D}" "${f}" && ewarn "QA: File contains a temporary path ${f}"
172                         sed -i -e "s:${D}:/:g" "${f}"
173                 fi
174         done
175 }
176
177 # @FUNCTION: perl_rm_files
178 # @USAGE: <list of files>
179 # @DESCRIPTION:
180 # Remove certain files from a Perl release and remove them from the MANIFEST
181 # while we're there.
182 #
183 # Most useful in src_prepare for nuking bad tests, and is highly recommended
184 # for any tests like 'pod.t', 'pod-coverage.t' or 'kwalitee.t', as what they
185 # test is completely irrelevant to end users, and frequently fail simply
186 # because the authors of Test::Pod... changed their recommendations, and thus
187 # failures are only useful feedback to Authors, not users.
188 #
189 # Removing from MANIFEST also avoids needless log messages warning
190 # users about files "missing from their kit".
191 #
192 # Example:
193 # @CODE
194 # src_test() {
195 #   perl_rm_files t/pod{,-coverage}.t
196 #   perl-module_src_test
197 # }
198 # @CODE
199 perl_rm_files() {
200         debug-print-function $FUNCNAME "$@"
201         local skipfile="${T}/.gentoo_makefile_skip"
202         local manifile="${S}/MANIFEST"
203         local manitemp="${T}/.gentoo_manifest_temp"
204         oldifs="$IFS"
205         IFS="\n"
206         for filename in "$@"; do
207                 einfo "Removing un-needed ${filename}";
208                 # Remove the file
209                 rm -f "${S}/${filename}"
210                 [[ -e "${manifile}" ]] && echo "${filename}" >> "${skipfile}"
211         done
212         if [[ -e "${manifile}" && -e "${skipfile}" ]]; then
213                 einfo "Fixing Manifest"
214                 grep -v -F -f "${skipfile}" "${manifile}" > "${manitemp}"
215                 mv -f -- "${manitemp}" "${manifile}"
216                 rm -- "${skipfile}";
217         fi
218         IFS="$oldifs"
219 }
220
221 # @FUNCTION: perl_link_duallife_scripts
222 # @DESCRIPTION:
223 # Moves files and generates symlinks so dual-life packages installing scripts do not
224 # lead to file collisions. Mainly for use in pkg_postinst and pkg_postrm, and makes
225 # only sense for perl-core packages.
226 perl_link_duallife_scripts() {
227         debug-print-function $FUNCNAME "$@"
228         if [[ ${CATEGORY} != perl-core ]] || ! has_version ">=dev-lang/perl-5.8.8-r8" ; then
229                 return 0
230         fi
231
232         local i ff
233         if has "${EBUILD_PHASE:-none}" "postinst" "postrm" ; then
234                 for i in "${DUALLIFESCRIPTS[@]}" ; do
235                         alternatives_auto_makesym "/${i}" "/${i}-[0-9]*"
236                 done
237                 for i in "${DUALLIFEMAN[@]}" ; do
238                         ff=`echo "${EROOT}"/${i%.1}-${PV}-${P}.1*`
239                         ff=${ff##*.1}
240                         alternatives_auto_makesym "/${i}${ff}" "/${i%.1}-[0-9]*"
241                 done
242         else
243                 pushd "${ED}" > /dev/null
244                 for i in $(find usr/bin -maxdepth 1 -type f 2>/dev/null) ; do
245                         mv ${i}{,-${PV}-${P}} || die
246                         #DUALLIFESCRIPTS[${#DUALLIFESCRIPTS[*]}]=${i##*/}
247                         DUALLIFESCRIPTS[${#DUALLIFESCRIPTS[*]}]=${i}
248                 done
249                 for i in $(find usr/share/man/man1 -maxdepth 1 -type f 2>/dev/null) ; do
250                         mv ${i} ${i%.1}-${PV}-${P}.1 || die
251                         DUALLIFEMAN[${#DUALLIFEMAN[*]}]=${i}
252                 done
253                 popd > /dev/null
254         fi
255 }
256
257 # @FUNCTION: perl_check_env
258 # @DESCRIPTION:
259 # Checks a blacklist of known-suspect ENV values that can be accidentally set by users
260 # doing personal perl work, which may accidentally leak into portage and break the
261 # system perl installaton.
262 # Dies if any of the suspect fields are found, and tell the user what needs to be unset.
263 # There's a workaround, but you'll have to read the code for it.
264 perl_check_env() {
265         local errored value;
266
267         for i in PERL_MM_OPT PERL5LIB PERL5OPT PERL_MB_OPT PERL_CORE PERLPREFIX; do
268                 # Next unless match
269                 [ -v $i ] || continue;
270
271                 # Warn only once, and warn only when one of the bad values are set.
272                 # record failure here.
273                 if [ ${errored:-0} == 0 ]; then
274                         if [ -n "${I_KNOW_WHAT_I_AM_DOING}" ]; then
275                                 elog "perl-module.eclass: Suspicious environment values found.";
276                         else
277                                 eerror "perl-module.eclass: Suspicious environment values found.";
278                         fi
279                 fi
280                 errored=1
281
282                 # Read ENV Value
283                 value=${!i};
284
285                 # Print ENV name/value pair
286                 if [ -n "${I_KNOW_WHAT_I_AM_DOING}" ]; then
287                         elog "    $i=\"$value\"";
288                 else
289                         eerror "    $i=\"$value\"";
290                 fi
291         done
292
293         # Return if there were no failures
294         [ ${errored:-0} == 0 ] && return;
295
296         # Return if user knows what they're doing
297         if [ -n "${I_KNOW_WHAT_I_AM_DOING}" ]; then
298                 elog "Continuing anyway, seems you know what you're doing."
299                 return
300         fi
301
302         eerror "Your environment settings may lead to undefined behavior and/or build failures."
303         die "Please fix your environment ( ~/.bashrc, package.env, ... ), see above for details."
304 }
305
306 # @FUNCTION: perl_doexamples
307 # @USAGE: <list of files or globs>
308 # @DESCRIPTION:
309 # Install example files ready-to-run.
310 # Is called under certain circumstances in perl-module.eclass src_install
311 # (see the documentation there).
312 #
313 # Example:
314 # @CODE
315 # src_install() {
316 #   perl-module_src_install
317 #   use examples && perl_doexamples "eg/*"
318 # }
319 # @CODE
320 perl_doexamples() {
321         debug-print-function $FUNCNAME "$@"
322
323         einfo "Installing examples into /usr/share/doc/${PF}/examples"
324
325         # no compression since we want ready-to-run scripts
326         docompress -x /usr/share/doc/${PF}/examples
327
328         docinto examples/
329         # Lack of quoting here is important in order to support glob expansion
330         # in DIST_EXAMPLES=( ), which is defined before source extraction occurs
331         dodoc -r $@
332
333         # is there a way to undo "docinto" ?
334 }
335
336 # @FUNCTION: perl_has_module
337 # @USAGE: <module name>
338 # @RETURN: 0 if available, non-zero otherwise
339 # @DESCRIPTION:
340 # Query the installed system Perl to see if a given module is installed.
341 # This does **not** load the module in question, only anticipates if it *might* load.
342 #
343 # This is primarily for the purposes of dependency weakening so that conditional
344 # behaviour can be triggered without adding dependencies to portage which would confuse
345 # a dependency resolver.
346 #
347 # returns 'true' if the module is available, returns error if the module is not available
348 #
349 # Example:
350 # @CODE
351 # perl_has_module "Test::Tester" && echo "Test::Tester installed"
352 # @CODE
353
354 perl_has_module() {
355         debug-print-function $FUNCNAME "$@"
356
357         [[ $# -gt 0 ]] || die "${FUNCNAME}: No module name provided"
358         [[ $# -lt 2 ]] || die "${FUNCNAME}: Too many parameters ($#)"
359
360         perl -we 'my $mn = $ARGV[0];
361                 $mn =~ s{(::|\x{27})}{/}g;
362                 for(@INC){
363                         next if ref $_;
364                         exit 0 if -r $_ . q[/] . $mn . q[.pm]
365                 }
366                 exit 1' "$@";
367 }
368
369 # @FUNCTION: perl_has_module_version
370 # @USAGE: <module name> <minimum upstream version>
371 # @RETURN: 0 if satisfied, non-zero otherwise
372 # @DESCRIPTION:
373 # Query the installed system Perl to see if a given module is installed
374 # and is at least a given version.
375 #
376 # This requires more caution to use than perl_has_module as it requires
377 # loading the module in question to determine version compatibility,
378 # which can be SLOW, and can have side effects (ie: compilation fails in
379 # require due to some dependency, resulting in a "Fail")
380 #
381 # Also take care to note the module version is a *minimum*, *must* be
382 # written in upstream versions format and should be a a legal upstream version
383 #
384 # returns a true exit code if the module is both available and is at least
385 # the specified version
386 #
387 # Example:
388 # @CODE
389 # perl_has_module_version "Test::Tester" "0.017" \
390 #       && echo "Test::Tester 0.017 or greater installed"
391 # @CODE
392 perl_has_module_version() {
393         debug-print-function $FUNCNAME "$@"
394
395         [[ $# -gt 0 ]] || die "${FUNCNAME}: No module name provided"
396         [[ $# -gt 1 ]] || die "${FUNCNAME}: No module version provided"
397         [[ $# -lt 3 ]] || die "${FUNCNAME}: Too many parameters ($#)"
398
399         perl -we 'my $mn = $ARGV[0];
400                 $mn =~ s{(::|\x{27})}{/}g;
401                 exit ( eval {
402                         require qq[${mn}.pm];
403                         $ARGV[0]->VERSION($ARGV[1]);
404                         1
405                 } ? 0 : 1 )' "$@"
406 }
407
408 # @FUNCTION: perl_get_module_version
409 # @USAGE: <module name>
410 # @RETURN: 0 if module available, non-zero if error
411 # @DESCRIPTION:
412 # Query the installed system perl to report the version of the installed
413 # module.
414 #
415 # Note this should be strictly for diagnostic purposes to the end user,
416 # and may be of selective use in pkg_info to enhance
417 # emerge --info reports.
418 #
419 # Anything that does version comparisons **must not** use the return value
420 # from this function
421 #
422 # Also note that this **must** at least attempt load the module in
423 # question as part of its operation, and is subsequently prone to SLOWness.
424 #
425 # Return codes return error in both compilation-failure and not-installed cases.
426 #
427 # Example:
428 # @CODE
429 # MODVER=$(perl_get_module_version "Test::Simple") \
430 #       || die "Test::Simple not installed: $MODVER"
431 # @CODE
432
433 perl_get_module_version() {
434         debug-print-function $FUNCNAME "$@"
435
436         [[ $# -gt 0 ]] || die "${FUNCNAME}: No module name provided"
437         [[ $# -lt 2 ]] || die "${FUNCNAME}: Too many parameters ($#)"
438
439         if ! perl_has_module "$@" ; then
440                 echo "(Not Installed)";
441                 return 1;
442         fi
443
444         # Todo: What do we do if require fails? spew to stderr
445         # or stay silent?
446
447         perl -we 'my $mn = $ARGV[0];
448                 $mn =~ s{(::|\x{27})}{/}g;
449                 local $@;
450                 eval { require qq[${mn}.pm]; 1 } or do {
451                         print q[(Compilation failed in require)];
452                         exit 1;
453                 };
454                 my $stash = \%{ $ARGV[0] . q[::] };
455                 if ( not exists $stash->{VERSION} ) {
456                         print q[(No VERSION property)];
457                         exit 0;
458                 }
459                 if ( not defined ${$stash->{VERSION}} ) {
460                         print q[(undef)];
461                         exit 0;
462                 }
463                 print ${$stash->{VERSION}};
464                 exit 0; ' "$@"
465 }
466
467 # @FUNCTION: perl_get_raw_vendorlib
468 # @DESCRIPTION:
469 # Convenience function to optimise for a common case without double-handling
470 # variables everywhere.
471 #
472 # Note: Will include EPREFIX where relevant
473 #
474 # Example:
475 # @CODE
476 # my_raw_vendorlib="$(perl_get_raw_vendorlib)"
477 # @CODE
478
479 perl_get_raw_vendorlib() {
480         debug-print-function $FUNCNAME "$@"
481
482         [[ $# -lt 1 ]] || die "${FUNCNAME}: Too many parameters ($#)"
483
484         perl -MConfig \
485                 -e'exists $Config{$ARGV[0]} || die qq{No such Config key "$ARGV[0]"};
486                    print $Config{$ARGV[0]};
487                    exit 0' -- "installvendorlib" || die "Can't extract installvendorlib from Perl Configuration"
488 }
489
490 # @FUNCTION: perl_get_vendorlib
491 # @DESCRIPTION:
492 # Convenience helper for returning Perls' vendor install root
493 # without EPREFIXing.
494 #
495 # Example:
496 # @CODE
497 # my_vendorlib="$(perl_get_vendorlib)"
498 # @CODE
499
500 perl_get_vendorlib() {
501         debug-print-function $FUNCNAME "$@"
502
503         [[ $# -lt 1 ]] || die "${FUNCNAME}: Too many parameters ($#)"
504
505         # Requires perl 5.14 for /r attribute of s///
506         # Just in case somebody out there is stuck in a time warp: upgrade perl first
507         perl -M5.014 -MConfig \
508                 -e'exists $Config{$ARGV[0]} || die qq{No such Config key "$ARGV[0]"};
509                    print $Config{$ARGV[0]} =~ s{\A\Q$ARGV[1]\E}{}r;
510                    exit 0' -- "installvendorlib" "$EPREFIX" || die "Can't extract installvendorlib from Perl Configuration"
511 }
512
513 # @FUNCTION: perl_domodule
514 # @USAGE: [-C <target>] [-r] <files>
515 # @DESCRIPTION:
516 # Installs files in paths where they can be found in the default
517 # Perl runtime.
518 #
519 # Note: Should only be used in src_install or pkg_preinst
520 # anywhere else will do the wrong thing or die.
521 #
522 # The contents of the <files> list are copied into Perls Vendor library path
523 # as follows:
524 # @CODE
525 #   # install perl/File.pm as Samba::File
526 #   pushd perl/
527 #   perl_domodule -C Samba File.pm
528 #
529 #   # install perl/ recursively under VENDORLIB/Samba/
530 #   pushd perl/
531 #   perl_domodule -C Samba -r .
532 # @CODE
533 #
534 # @CODE
535 #   options:
536 #       -C Target/Name
537 #          The subdirectory relative to the Perl VENDOR_LIB
538 #          to install into.
539 #
540 #          defaults to ""
541 #       -r
542 #          Install directories recursively ( see doins )
543 #          files:
544 #          list of .pm files to install to VENDORLIB
545 # @CODE
546
547 perl_domodule() {
548         local target_prefix=""
549         local files=()
550         local doins_opts=()
551
552         local recursive="false"
553         local target
554         local file
555
556         while [[ $# -gt 0 ]] ; do
557                 case $1 in
558                         -C|--target-prefix)
559                                 [[ -z "${2}" || "${2:0:1}" == "-" ]] && die "${FUNCNAME}: -C|--target-prefix expects an argument, got \"$2\"!"
560                                 target_prefix="${2}";
561                                 shift 2;;
562                         -r)
563                                 recursive="true"
564                                 shift;;
565                         *)
566                                 [[ -z "${1}" || "${1:0:1}" == "-" ]] && die "${FUNCNAME}: Unknown argument \"${1}\"!"
567                                 files+=( "${1}" )
568                                 shift 1;;
569                 esac
570         done
571
572         if [[ "true" == $recursive ]]; then
573                 doins_opts+=( "-r" )
574         fi
575         for file in "${files[@]}"; do
576                 [[ -e "${file}" ]] || die "$FUNCNAME: Argument \"${file}\" is not an existing file"
577                 [[ "false" == ${recursive} && -d "${file}" ]] && die "$FUNCNAME: Argument \"${file}\" is a directory ( needs -r parameter )"
578         done
579
580         target="$(perl_get_vendorlib)"
581
582         # Extend target if target_prefix is set
583         [[ -z "${target_prefix}" ]] || target="${target%/}/${target_prefix#/}"
584
585         insinto "/${target#/}"
586         doins "${doins_opts[@]}" "${files[@]}"
587 }