kde-plasma/breeze-gtk: x86 stable wrt bug #613144
[gentoo.git] / eclass / eutils.eclass
1 # Copyright 1999-2017 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: eutils.eclass
5 # @MAINTAINER:
6 # base-system@gentoo.org
7 # @BLURB: many extra (but common) functions that are used in ebuilds
8 # @DESCRIPTION:
9 # The eutils eclass contains a suite of functions that complement
10 # the ones that ebuild.sh already contain.  The idea is that the functions
11 # are not required in all ebuilds but enough utilize them to have a common
12 # home rather than having multiple ebuilds implementing the same thing.
13 #
14 # Due to the nature of this eclass, some functions may have maintainers
15 # different from the overall eclass!
16
17 if [[ -z ${_EUTILS_ECLASS} ]]; then
18 _EUTILS_ECLASS=1
19
20 # implicitly inherited (now split) eclasses
21 case ${EAPI:-0} in
22 0|1|2|3|4|5|6)
23         inherit epatch estack ltprune multilib toolchain-funcs
24         ;;
25 esac
26
27 # @FUNCTION: eqawarn
28 # @USAGE: [message]
29 # @DESCRIPTION:
30 # Proxy to ewarn for package managers that don't provide eqawarn and use the PM
31 # implementation if available. Reuses PORTAGE_ELOG_CLASSES as set by the dev
32 # profile.
33 if ! declare -F eqawarn >/dev/null ; then
34         eqawarn() {
35                 has qa ${PORTAGE_ELOG_CLASSES} && ewarn "$@"
36                 :
37         }
38 fi
39
40 # @FUNCTION: ecvs_clean
41 # @USAGE: [list of dirs]
42 # @DESCRIPTION:
43 # Remove CVS directories recursiveley.  Useful when a source tarball contains
44 # internal CVS directories.  Defaults to $PWD.
45 ecvs_clean() {
46         [[ $# -eq 0 ]] && set -- .
47         find "$@" -type d -name 'CVS' -prune -print0 | xargs -0 rm -rf
48         find "$@" -type f -name '.cvs*' -print0 | xargs -0 rm -rf
49 }
50
51 # @FUNCTION: esvn_clean
52 # @USAGE: [list of dirs]
53 # @DESCRIPTION:
54 # Remove .svn directories recursiveley.  Useful when a source tarball contains
55 # internal Subversion directories.  Defaults to $PWD.
56 esvn_clean() {
57         [[ $# -eq 0 ]] && set -- .
58         find "$@" -type d -name '.svn' -prune -print0 | xargs -0 rm -rf
59 }
60
61 # @FUNCTION: egit_clean
62 # @USAGE: [list of dirs]
63 # @DESCRIPTION:
64 # Remove .git* directories/files recursiveley.  Useful when a source tarball
65 # contains internal Git directories.  Defaults to $PWD.
66 egit_clean() {
67         [[ $# -eq 0 ]] && set -- .
68         find "$@" -type d -name '.git*' -prune -print0 | xargs -0 rm -rf
69 }
70
71 # @FUNCTION: emktemp
72 # @USAGE: [temp dir]
73 # @DESCRIPTION:
74 # Cheap replacement for when debianutils (and thus mktemp)
75 # does not exist on the users system.
76 emktemp() {
77         local exe="touch"
78         [[ $1 == -d ]] && exe="mkdir" && shift
79         local topdir=$1
80
81         if [[ -z ${topdir} ]] ; then
82                 [[ -z ${T} ]] \
83                         && topdir="/tmp" \
84                         || topdir=${T}
85         fi
86
87         if ! type -P mktemp > /dev/null ; then
88                 # system lacks `mktemp` so we have to fake it
89                 local tmp=/
90                 while [[ -e ${tmp} ]] ; do
91                         tmp=${topdir}/tmp.${RANDOM}.${RANDOM}.${RANDOM}
92                 done
93                 ${exe} "${tmp}" || ${exe} -p "${tmp}"
94                 echo "${tmp}"
95         else
96                 # the args here will give slightly wierd names on BSD,
97                 # but should produce a usable file on all userlands
98                 if [[ ${exe} == "touch" ]] ; then
99                         TMPDIR="${topdir}" mktemp -t tmp.XXXXXXXXXX
100                 else
101                         TMPDIR="${topdir}" mktemp -dt tmp.XXXXXXXXXX
102                 fi
103         fi
104 }
105
106 # @FUNCTION: edos2unix
107 # @USAGE: <file> [more files ...]
108 # @DESCRIPTION:
109 # A handy replacement for dos2unix, recode, fixdos, etc...  This allows you
110 # to remove all of these text utilities from DEPEND variables because this
111 # is a script based solution.  Just give it a list of files to convert and
112 # they will all be changed from the DOS CRLF format to the UNIX LF format.
113 edos2unix() {
114         [[ $# -eq 0 ]] && return 0
115         sed -i 's/\r$//' -- "$@" || die
116 }
117
118 # @FUNCTION: make_desktop_entry
119 # @USAGE: make_desktop_entry(<command>, [name], [icon], [type], [fields])
120 # @DESCRIPTION:
121 # Make a .desktop file.
122 #
123 # @CODE
124 # binary:   what command does the app run with ?
125 # name:     the name that will show up in the menu
126 # icon:     the icon to use in the menu entry
127 #           this can be relative (to /usr/share/pixmaps) or
128 #           a full path to an icon
129 # type:     what kind of application is this?
130 #           for categories:
131 #           https://specifications.freedesktop.org/menu-spec/latest/apa.html
132 #           if unset, function tries to guess from package's category
133 # fields:       extra fields to append to the desktop file; a printf string
134 # @CODE
135 make_desktop_entry() {
136         [[ -z $1 ]] && die "make_desktop_entry: You must specify the executable"
137
138         local exec=${1}
139         local name=${2:-${PN}}
140         local icon=${3:-${PN}}
141         local type=${4}
142         local fields=${5}
143
144         if [[ -z ${type} ]] ; then
145                 local catmaj=${CATEGORY%%-*}
146                 local catmin=${CATEGORY##*-}
147                 case ${catmaj} in
148                         app)
149                                 case ${catmin} in
150                                         accessibility) type="Utility;Accessibility";;
151                                         admin)         type=System;;
152                                         antivirus)     type=System;;
153                                         arch)          type="Utility;Archiving";;
154                                         backup)        type="Utility;Archiving";;
155                                         cdr)           type="AudioVideo;DiscBurning";;
156                                         dicts)         type="Office;Dictionary";;
157                                         doc)           type=Documentation;;
158                                         editors)       type="Utility;TextEditor";;
159                                         emacs)         type="Development;TextEditor";;
160                                         emulation)     type="System;Emulator";;
161                                         laptop)        type="Settings;HardwareSettings";;
162                                         office)        type=Office;;
163                                         pda)           type="Office;PDA";;
164                                         vim)           type="Development;TextEditor";;
165                                         xemacs)        type="Development;TextEditor";;
166                                 esac
167                                 ;;
168
169                         dev)
170                                 type="Development"
171                                 ;;
172
173                         games)
174                                 case ${catmin} in
175                                         action|fps) type=ActionGame;;
176                                         arcade)     type=ArcadeGame;;
177                                         board)      type=BoardGame;;
178                                         emulation)  type=Emulator;;
179                                         kids)       type=KidsGame;;
180                                         puzzle)     type=LogicGame;;
181                                         roguelike)  type=RolePlaying;;
182                                         rpg)        type=RolePlaying;;
183                                         simulation) type=Simulation;;
184                                         sports)     type=SportsGame;;
185                                         strategy)   type=StrategyGame;;
186                                 esac
187                                 type="Game;${type}"
188                                 ;;
189
190                         gnome)
191                                 type="Gnome;GTK"
192                                 ;;
193
194                         kde)
195                                 type="KDE;Qt"
196                                 ;;
197
198                         mail)
199                                 type="Network;Email"
200                                 ;;
201
202                         media)
203                                 case ${catmin} in
204                                         gfx)
205                                                 type=Graphics
206                                                 ;;
207                                         *)
208                                                 case ${catmin} in
209                                                         radio) type=Tuner;;
210                                                         sound) type=Audio;;
211                                                         tv)    type=TV;;
212                                                         video) type=Video;;
213                                                 esac
214                                                 type="AudioVideo;${type}"
215                                                 ;;
216                                 esac
217                                 ;;
218
219                         net)
220                                 case ${catmin} in
221                                         dialup) type=Dialup;;
222                                         ftp)    type=FileTransfer;;
223                                         im)     type=InstantMessaging;;
224                                         irc)    type=IRCClient;;
225                                         mail)   type=Email;;
226                                         news)   type=News;;
227                                         nntp)   type=News;;
228                                         p2p)    type=FileTransfer;;
229                                         voip)   type=Telephony;;
230                                 esac
231                                 type="Network;${type}"
232                                 ;;
233
234                         sci)
235                                 case ${catmin} in
236                                         astro*)  type=Astronomy;;
237                                         bio*)    type=Biology;;
238                                         calc*)   type=Calculator;;
239                                         chem*)   type=Chemistry;;
240                                         elec*)   type=Electronics;;
241                                         geo*)    type=Geology;;
242                                         math*)   type=Math;;
243                                         physics) type=Physics;;
244                                         visual*) type=DataVisualization;;
245                                 esac
246                                 type="Education;Science;${type}"
247                                 ;;
248
249                         sys)
250                                 type="System"
251                                 ;;
252
253                         www)
254                                 case ${catmin} in
255                                         client) type=WebBrowser;;
256                                 esac
257                                 type="Network;${type}"
258                                 ;;
259
260                         *)
261                                 type=
262                                 ;;
263                 esac
264         fi
265         local slot=${SLOT%/*}
266         if [[ ${slot} == "0" ]] ; then
267                 local desktop_name="${PN}"
268         else
269                 local desktop_name="${PN}-${slot}"
270         fi
271         local desktop="${T}/$(echo ${exec} | sed 's:[[:space:]/:]:_:g')-${desktop_name}.desktop"
272         #local desktop=${T}/${exec%% *:-${desktop_name}}.desktop
273
274         # Don't append another ";" when a valid category value is provided.
275         type=${type%;}${type:+;}
276
277         eshopts_push -s extglob
278         if [[ -n ${icon} && ${icon} != /* ]] && [[ ${icon} == *.xpm || ${icon} == *.png || ${icon} == *.svg ]]; then
279                 ewarn "As described in the Icon Theme Specification, icon file extensions are not"
280                 ewarn "allowed in .desktop files if the value is not an absolute path."
281                 icon=${icon%.@(xpm|png|svg)}
282         fi
283         eshopts_pop
284
285         cat <<-EOF > "${desktop}"
286         [Desktop Entry]
287         Name=${name}
288         Type=Application
289         Comment=${DESCRIPTION}
290         Exec=${exec}
291         TryExec=${exec%% *}
292         Icon=${icon}
293         Categories=${type}
294         EOF
295
296         if [[ ${fields:-=} != *=* ]] ; then
297                 # 5th arg used to be value to Path=
298                 ewarn "make_desktop_entry: update your 5th arg to read Path=${fields}"
299                 fields="Path=${fields}"
300         fi
301         [[ -n ${fields} ]] && printf '%b\n' "${fields}" >> "${desktop}"
302
303         (
304                 # wrap the env here so that the 'insinto' call
305                 # doesn't corrupt the env of the caller
306                 insinto /usr/share/applications
307                 doins "${desktop}"
308         ) || die "installing desktop file failed"
309 }
310
311 # @FUNCTION: _eutils_eprefix_init
312 # @INTERNAL
313 # @DESCRIPTION:
314 # Initialized prefix variables for EAPI<3.
315 _eutils_eprefix_init() {
316         has "${EAPI:-0}" 0 1 2 && : ${ED:=${D}} ${EPREFIX:=} ${EROOT:=${ROOT}}
317 }
318
319 # @FUNCTION: validate_desktop_entries
320 # @USAGE: [directories]
321 # @DESCRIPTION:
322 # Validate desktop entries using desktop-file-utils
323 validate_desktop_entries() {
324         eqawarn "validate_desktop_entries is deprecated and should be not be used."
325         eqawarn ".desktop file validation is done implicitly by Portage now."
326
327         _eutils_eprefix_init
328         if [[ -x "${EPREFIX}"/usr/bin/desktop-file-validate ]] ; then
329                 einfo "Checking desktop entry validity"
330                 local directories=""
331                 for d in /usr/share/applications $@ ; do
332                         [[ -d ${ED}${d} ]] && directories="${directories} ${ED}${d}"
333                 done
334                 if [[ -n ${directories} ]] ; then
335                         for FILE in $(find ${directories} -name "*\.desktop" \
336                                                         -not -path '*.hidden*' | sort -u 2>/dev/null)
337                         do
338                                 local temp=$(desktop-file-validate ${FILE} | grep -v "warning:" | \
339                                                                 sed -e "s|error: ||" -e "s|${FILE}:|--|g" )
340                                 [[ -n $temp ]] && elog ${temp/--/${FILE/${ED}/}:}
341                         done
342                 fi
343                 echo ""
344         else
345                 einfo "Passing desktop entry validity check. Install dev-util/desktop-file-utils, if you want to help to improve Gentoo."
346         fi
347 }
348
349 # @FUNCTION: make_session_desktop
350 # @USAGE: <title> <command> [command args...]
351 # @DESCRIPTION:
352 # Make a GDM/KDM Session file.  The title is the file to execute to start the
353 # Window Manager.  The command is the name of the Window Manager.
354 #
355 # You can set the name of the file via the ${wm} variable.
356 make_session_desktop() {
357         [[ -z $1 ]] && eerror "$0: You must specify the title" && return 1
358         [[ -z $2 ]] && eerror "$0: You must specify the command" && return 1
359
360         local title=$1
361         local command=$2
362         local desktop=${T}/${wm:-${PN}}.desktop
363         shift 2
364
365         cat <<-EOF > "${desktop}"
366         [Desktop Entry]
367         Name=${title}
368         Comment=This session logs you into ${title}
369         Exec=${command} $*
370         TryExec=${command}
371         Type=XSession
372         EOF
373
374         (
375         # wrap the env here so that the 'insinto' call
376         # doesn't corrupt the env of the caller
377         insinto /usr/share/xsessions
378         doins "${desktop}"
379         )
380 }
381
382 # @FUNCTION: domenu
383 # @USAGE: <menus>
384 # @DESCRIPTION:
385 # Install the list of .desktop menu files into the appropriate directory
386 # (/usr/share/applications).
387 domenu() {
388         (
389         # wrap the env here so that the 'insinto' call
390         # doesn't corrupt the env of the caller
391         local i j ret=0
392         insinto /usr/share/applications
393         for i in "$@" ; do
394                 if [[ -f ${i} ]] ; then
395                         doins "${i}"
396                         ((ret+=$?))
397                 elif [[ -d ${i} ]] ; then
398                         for j in "${i}"/*.desktop ; do
399                                 doins "${j}"
400                                 ((ret+=$?))
401                         done
402                 else
403                         ((++ret))
404                 fi
405         done
406         exit ${ret}
407         )
408 }
409
410 # @FUNCTION: newmenu
411 # @USAGE: <menu> <newname>
412 # @DESCRIPTION:
413 # Like all other new* functions, install the specified menu as newname.
414 newmenu() {
415         (
416         # wrap the env here so that the 'insinto' call
417         # doesn't corrupt the env of the caller
418         insinto /usr/share/applications
419         newins "$@"
420         )
421 }
422
423 # @FUNCTION: _iconins
424 # @INTERNAL
425 # @DESCRIPTION:
426 # function for use in doicon and newicon
427 _iconins() {
428         (
429         # wrap the env here so that the 'insinto' call
430         # doesn't corrupt the env of the caller
431         local funcname=$1; shift
432         local size dir
433         local context=apps
434         local theme=hicolor
435
436         while [[ $# -gt 0 ]] ; do
437                 case $1 in
438                 -s|--size)
439                         if [[ ${2%%x*}x${2%%x*} == "$2" ]] ; then
440                                 size=${2%%x*}
441                         else
442                                 size=${2}
443                         fi
444                         case ${size} in
445                         16|22|24|32|36|48|64|72|96|128|192|256|512)
446                                 size=${size}x${size};;
447                         scalable)
448                                 ;;
449                         *)
450                                 eerror "${size} is an unsupported icon size!"
451                                 exit 1;;
452                         esac
453                         shift 2;;
454                 -t|--theme)
455                         theme=${2}
456                         shift 2;;
457                 -c|--context)
458                         context=${2}
459                         shift 2;;
460                 *)
461                         if [[ -z ${size} ]] ; then
462                                 insinto /usr/share/pixmaps
463                         else
464                                 insinto /usr/share/icons/${theme}/${size}/${context}
465                         fi
466
467                         if [[ ${funcname} == doicon ]] ; then
468                                 if [[ -f $1 ]] ; then
469                                         doins "${1}"
470                                 elif [[ -d $1 ]] ; then
471                                         shopt -s nullglob
472                                         doins "${1}"/*.{png,svg}
473                                         shopt -u nullglob
474                                 else
475                                         eerror "${1} is not a valid file/directory!"
476                                         exit 1
477                                 fi
478                         else
479                                 break
480                         fi
481                         shift 1;;
482                 esac
483         done
484         if [[ ${funcname} == newicon ]] ; then
485                 newins "$@"
486         fi
487         ) || die
488 }
489
490 # @FUNCTION: doicon
491 # @USAGE: [options] <icons>
492 # @DESCRIPTION:
493 # Install icon into the icon directory /usr/share/icons or into
494 # /usr/share/pixmaps if "--size" is not set.
495 # This is useful in conjunction with creating desktop/menu files.
496 #
497 # @CODE
498 #  options:
499 #  -s, --size
500 #    !!! must specify to install into /usr/share/icons/... !!!
501 #    size of the icon, like 48 or 48x48
502 #    supported icon sizes are:
503 #    16 22 24 32 36 48 64 72 96 128 192 256 512 scalable
504 #  -c, --context
505 #    defaults to "apps"
506 #  -t, --theme
507 #    defaults to "hicolor"
508 #
509 # icons: list of icons
510 #
511 # example 1: doicon foobar.png fuqbar.svg suckbar.png
512 # results in: insinto /usr/share/pixmaps
513 #             doins foobar.png fuqbar.svg suckbar.png
514 #
515 # example 2: doicon -s 48 foobar.png fuqbar.png blobbar.png
516 # results in: insinto /usr/share/icons/hicolor/48x48/apps
517 #             doins foobar.png fuqbar.png blobbar.png
518 # @CODE
519 doicon() {
520         _iconins ${FUNCNAME} "$@"
521 }
522
523 # @FUNCTION: newicon
524 # @USAGE: [options] <icon> <newname>
525 # @DESCRIPTION:
526 # Like doicon, install the specified icon as newname.
527 #
528 # @CODE
529 # example 1: newicon foobar.png NEWNAME.png
530 # results in: insinto /usr/share/pixmaps
531 #             newins foobar.png NEWNAME.png
532 #
533 # example 2: newicon -s 48 foobar.png NEWNAME.png
534 # results in: insinto /usr/share/icons/hicolor/48x48/apps
535 #             newins foobar.png NEWNAME.png
536 # @CODE
537 newicon() {
538         _iconins ${FUNCNAME} "$@"
539 }
540
541 # @FUNCTION: strip-linguas
542 # @USAGE: [<allow LINGUAS>|<-i|-u> <directories of .po files>]
543 # @DESCRIPTION:
544 # Make sure that LINGUAS only contains languages that
545 # a package can support.  The first form allows you to
546 # specify a list of LINGUAS.  The -i builds a list of po
547 # files found in all the directories and uses the
548 # intersection of the lists.  The -u builds a list of po
549 # files found in all the directories and uses the union
550 # of the lists.
551 strip-linguas() {
552         local ls newls nols
553         if [[ $1 == "-i" ]] || [[ $1 == "-u" ]] ; then
554                 local op=$1; shift
555                 ls=$(find "$1" -name '*.po' -exec basename {} .po ';'); shift
556                 local d f
557                 for d in "$@" ; do
558                         if [[ ${op} == "-u" ]] ; then
559                                 newls=${ls}
560                         else
561                                 newls=""
562                         fi
563                         for f in $(find "$d" -name '*.po' -exec basename {} .po ';') ; do
564                                 if [[ ${op} == "-i" ]] ; then
565                                         has ${f} ${ls} && newls="${newls} ${f}"
566                                 else
567                                         has ${f} ${ls} || newls="${newls} ${f}"
568                                 fi
569                         done
570                         ls=${newls}
571                 done
572         else
573                 ls="$@"
574         fi
575
576         nols=""
577         newls=""
578         for f in ${LINGUAS} ; do
579                 if has ${f} ${ls} ; then
580                         newls="${newls} ${f}"
581                 else
582                         nols="${nols} ${f}"
583                 fi
584         done
585         [[ -n ${nols} ]] \
586                 && einfo "Sorry, but ${PN} does not support the LINGUAS:" ${nols}
587         export LINGUAS=${newls:1}
588 }
589
590 # @FUNCTION: preserve_old_lib
591 # @USAGE: <libs to preserve> [more libs]
592 # @DESCRIPTION:
593 # These functions are useful when a lib in your package changes ABI SONAME.
594 # An example might be from libogg.so.0 to libogg.so.1.  Removing libogg.so.0
595 # would break packages that link against it.  Most people get around this
596 # by using the portage SLOT mechanism, but that is not always a relevant
597 # solution, so instead you can call this from pkg_preinst.  See also the
598 # preserve_old_lib_notify function.
599 preserve_old_lib() {
600         _eutils_eprefix_init
601         if [[ ${EBUILD_PHASE} != "preinst" ]] ; then
602                 eerror "preserve_old_lib() must be called from pkg_preinst() only"
603                 die "Invalid preserve_old_lib() usage"
604         fi
605         [[ -z $1 ]] && die "Usage: preserve_old_lib <library to preserve> [more libraries to preserve]"
606
607         # let portage worry about it
608         has preserve-libs ${FEATURES} && return 0
609
610         local lib dir
611         for lib in "$@" ; do
612                 [[ -e ${EROOT}/${lib} ]] || continue
613                 dir=${lib%/*}
614                 dodir ${dir} || die "dodir ${dir} failed"
615                 cp "${EROOT}"/${lib} "${ED}"/${lib} || die "cp ${lib} failed"
616                 touch "${ED}"/${lib}
617         done
618 }
619
620 # @FUNCTION: preserve_old_lib_notify
621 # @USAGE: <libs to notify> [more libs]
622 # @DESCRIPTION:
623 # Spit helpful messages about the libraries preserved by preserve_old_lib.
624 preserve_old_lib_notify() {
625         if [[ ${EBUILD_PHASE} != "postinst" ]] ; then
626                 eerror "preserve_old_lib_notify() must be called from pkg_postinst() only"
627                 die "Invalid preserve_old_lib_notify() usage"
628         fi
629
630         # let portage worry about it
631         has preserve-libs ${FEATURES} && return 0
632
633         _eutils_eprefix_init
634
635         local lib notice=0
636         for lib in "$@" ; do
637                 [[ -e ${EROOT}/${lib} ]] || continue
638                 if [[ ${notice} -eq 0 ]] ; then
639                         notice=1
640                         ewarn "Old versions of installed libraries were detected on your system."
641                         ewarn "In order to avoid breaking packages that depend on these old libs,"
642                         ewarn "the libraries are not being removed.  You need to run revdep-rebuild"
643                         ewarn "in order to remove these old dependencies.  If you do not have this"
644                         ewarn "helper program, simply emerge the 'gentoolkit' package."
645                         ewarn
646                 fi
647                 ewarn "  # revdep-rebuild --library '${lib}' && rm '${lib}'"
648         done
649 }
650
651 # @FUNCTION: built_with_use
652 # @USAGE: [--hidden] [--missing <action>] [-a|-o] <DEPEND ATOM> <List of USE flags>
653 # @DESCRIPTION:
654 #
655 # Deprecated: Use EAPI 2 use deps in DEPEND|RDEPEND and with has_version calls.
656 #
657 # A temporary hack until portage properly supports DEPENDing on USE
658 # flags being enabled in packages.  This will check to see if the specified
659 # DEPEND atom was built with the specified list of USE flags.  The
660 # --missing option controls the behavior if called on a package that does
661 # not actually support the defined USE flags (aka listed in IUSE).
662 # The default is to abort (call die).  The -a and -o flags control
663 # the requirements of the USE flags.  They correspond to "and" and "or"
664 # logic.  So the -a flag means all listed USE flags must be enabled
665 # while the -o flag means at least one of the listed IUSE flags must be
666 # enabled.  The --hidden option is really for internal use only as it
667 # means the USE flag we're checking is hidden expanded, so it won't be found
668 # in IUSE like normal USE flags.
669 #
670 # Remember that this function isn't terribly intelligent so order of optional
671 # flags matter.
672 built_with_use() {
673         _eutils_eprefix_init
674         local hidden="no"
675         if [[ $1 == "--hidden" ]] ; then
676                 hidden="yes"
677                 shift
678         fi
679
680         local missing_action="die"
681         if [[ $1 == "--missing" ]] ; then
682                 missing_action=$2
683                 shift ; shift
684                 case ${missing_action} in
685                         true|false|die) ;;
686                         *) die "unknown action '${missing_action}'";;
687                 esac
688         fi
689
690         local opt=$1
691         [[ ${opt:0:1} = "-" ]] && shift || opt="-a"
692
693         local PKG=$(best_version $1)
694         [[ -z ${PKG} ]] && die "Unable to resolve $1 to an installed package"
695         shift
696
697         local USEFILE=${EROOT}/var/db/pkg/${PKG}/USE
698         local IUSEFILE=${EROOT}/var/db/pkg/${PKG}/IUSE
699
700         # if the IUSE file doesn't exist, the read will error out, we need to handle
701         # this gracefully
702         if [[ ! -e ${USEFILE} ]] || [[ ! -e ${IUSEFILE} && ${hidden} == "no" ]] ; then
703                 case ${missing_action} in
704                         true)   return 0;;
705                         false)  return 1;;
706                         die)    die "Unable to determine what USE flags $PKG was built with";;
707                 esac
708         fi
709
710         if [[ ${hidden} == "no" ]] ; then
711                 local IUSE_BUILT=( $(<"${IUSEFILE}") )
712                 # Don't check USE_EXPAND #147237
713                 local expand
714                 for expand in $(echo ${USE_EXPAND} | tr '[:upper:]' '[:lower:]') ; do
715                         if [[ $1 == ${expand}_* ]] ; then
716                                 expand=""
717                                 break
718                         fi
719                 done
720                 if [[ -n ${expand} ]] ; then
721                         if ! has $1 ${IUSE_BUILT[@]#[-+]} ; then
722                                 case ${missing_action} in
723                                         true)  return 0;;
724                                         false) return 1;;
725                                         die)   die "$PKG does not actually support the $1 USE flag!";;
726                                 esac
727                         fi
728                 fi
729         fi
730
731         local USE_BUILT=$(<${USEFILE})
732         while [[ $# -gt 0 ]] ; do
733                 if [[ ${opt} = "-o" ]] ; then
734                         has $1 ${USE_BUILT} && return 0
735                 else
736                         has $1 ${USE_BUILT} || return 1
737                 fi
738                 shift
739         done
740         [[ ${opt} = "-a" ]]
741 }
742
743 # If an overlay has eclass overrides, but doesn't actually override the
744 # libtool.eclass, we'll have ECLASSDIR pointing to the active overlay's
745 # eclass/ dir, but libtool.eclass is still in the main Gentoo tree.  So
746 # add a check to locate the ELT-patches/ regardless of what's going on.
747 # Note: Duplicated in libtool.eclass.
748 _EUTILS_ECLASSDIR_LOCAL=${BASH_SOURCE[0]%/*}
749 eutils_elt_patch_dir() {
750         local d="${ECLASSDIR}/ELT-patches"
751         if [[ ! -d ${d} ]] ; then
752                 d="${_EUTILS_ECLASSDIR_LOCAL}/ELT-patches"
753         fi
754         echo "${d}"
755 }
756
757 # @FUNCTION: epunt_cxx
758 # @USAGE: [dir to scan]
759 # @DESCRIPTION:
760 # Many configure scripts wrongly bail when a C++ compiler could not be
761 # detected.  If dir is not specified, then it defaults to ${S}.
762 #
763 # https://bugs.gentoo.org/73450
764 epunt_cxx() {
765         local dir=$1
766         [[ -z ${dir} ]] && dir=${S}
767         ebegin "Removing useless C++ checks"
768         local f p any_found
769         while IFS= read -r -d '' f; do
770                 for p in "$(eutils_elt_patch_dir)"/nocxx/*.patch ; do
771                         if patch --no-backup-if-mismatch -p1 "${f}" "${p}" >/dev/null ; then
772                                 any_found=1
773                                 break
774                         fi
775                 done
776         done < <(find "${dir}" -name configure -print0)
777
778         if [[ -z ${any_found} ]]; then
779                 eqawarn "epunt_cxx called unnecessarily (no C++ checks to punt)."
780         fi
781         eend 0
782 }
783
784 # @FUNCTION: make_wrapper
785 # @USAGE: <wrapper> <target> [chdir] [libpaths] [installpath]
786 # @DESCRIPTION:
787 # Create a shell wrapper script named wrapper in installpath
788 # (defaults to the bindir) to execute target (default of wrapper) by
789 # first optionally setting LD_LIBRARY_PATH to the colon-delimited
790 # libpaths followed by optionally changing directory to chdir.
791 make_wrapper() {
792         _eutils_eprefix_init
793         local wrapper=$1 bin=$2 chdir=$3 libdir=$4 path=$5
794         local tmpwrapper=$(emktemp)
795
796         (
797         echo '#!/bin/sh'
798         [[ -n ${chdir} ]] && printf 'cd "%s"\n' "${EPREFIX}${chdir}"
799         if [[ -n ${libdir} ]] ; then
800                 local var
801                 if [[ ${CHOST} == *-darwin* ]] ; then
802                         var=DYLD_LIBRARY_PATH
803                 else
804                         var=LD_LIBRARY_PATH
805                 fi
806                 cat <<-EOF
807                         if [ "\${${var}+set}" = "set" ] ; then
808                                 export ${var}="\${${var}}:${EPREFIX}${libdir}"
809                         else
810                                 export ${var}="${EPREFIX}${libdir}"
811                         fi
812                 EOF
813         fi
814         # We don't want to quote ${bin} so that people can pass complex
815         # things as ${bin} ... "./someprog --args"
816         printf 'exec %s "$@"\n' "${bin/#\//${EPREFIX}/}"
817         ) > "${tmpwrapper}"
818         chmod go+rx "${tmpwrapper}"
819
820         if [[ -n ${path} ]] ; then
821                 (
822                 exeinto "${path}"
823                 newexe "${tmpwrapper}" "${wrapper}"
824                 ) || die
825         else
826                 newbin "${tmpwrapper}" "${wrapper}" || die
827         fi
828 }
829
830 # @FUNCTION: path_exists
831 # @USAGE: [-a|-o] <paths>
832 # @DESCRIPTION:
833 # Check if the specified paths exist.  Works for all types of paths
834 # (files/dirs/etc...).  The -a and -o flags control the requirements
835 # of the paths.  They correspond to "and" and "or" logic.  So the -a
836 # flag means all the paths must exist while the -o flag means at least
837 # one of the paths must exist.  The default behavior is "and".  If no
838 # paths are specified, then the return value is "false".
839 path_exists() {
840         local opt=$1
841         [[ ${opt} == -[ao] ]] && shift || opt="-a"
842
843         # no paths -> return false
844         # same behavior as: [[ -e "" ]]
845         [[ $# -eq 0 ]] && return 1
846
847         local p r=0
848         for p in "$@" ; do
849                 [[ -e ${p} ]]
850                 : $(( r += $? ))
851         done
852
853         case ${opt} in
854                 -a) return $(( r != 0 )) ;;
855                 -o) return $(( r == $# )) ;;
856         esac
857 }
858
859 # @FUNCTION: use_if_iuse
860 # @USAGE: <flag>
861 # @DESCRIPTION:
862 # Return true if the given flag is in USE and IUSE.
863 #
864 # Note that this function should not be used in the global scope.
865 use_if_iuse() {
866         in_iuse $1 || return 1
867         use $1
868 }
869
870 # @FUNCTION: optfeature
871 # @USAGE: <short description> <package atom to match> [other atoms]
872 # @DESCRIPTION:
873 # Print out a message suggesting an optional package (or packages) which
874 # provide the described functionality
875 #
876 # The following snippet would suggest app-misc/foo for optional foo support,
877 # app-misc/bar or app-misc/baz[bar] for optional bar support
878 # and either both app-misc/a and app-misc/b or app-misc/c for alphabet support.
879 # @CODE
880 #       optfeature "foo support" app-misc/foo
881 #       optfeature "bar support" app-misc/bar app-misc/baz[bar]
882 #       optfeature "alphabet support" "app-misc/a app-misc/b" app-misc/c
883 # @CODE
884 optfeature() {
885         debug-print-function ${FUNCNAME} "$@"
886         local i j msg
887         local desc=$1
888         local flag=0
889         shift
890         for i; do
891                 for j in ${i}; do
892                         if has_version "${j}"; then
893                                 flag=1
894                         else
895                                 flag=0
896                                 break
897                         fi
898                 done
899                 if [[ ${flag} -eq 1 ]]; then
900                         break
901                 fi
902         done
903         if [[ ${flag} -eq 0 ]]; then
904                 for i; do
905                         msg=" "
906                         for j in ${i}; do
907                                 msg+=" ${j} and"
908                         done
909                         msg="${msg:0: -4} for ${desc}"
910                         elog "${msg}"
911                 done
912         fi
913 }
914
915 check_license() {
916         die "you no longer need this as portage supports ACCEPT_LICENSE itself"
917 }
918
919 case ${EAPI:-0} in
920 0|1|2)
921
922 # @FUNCTION: epause
923 # @USAGE: [seconds]
924 # @DESCRIPTION:
925 # Sleep for the specified number of seconds (default of 5 seconds).  Useful when
926 # printing a message the user should probably be reading and often used in
927 # conjunction with the ebeep function.  If the EPAUSE_IGNORE env var is set,
928 # don't wait at all. Defined in EAPIs 0 1 and 2.
929 epause() {
930         [[ -z ${EPAUSE_IGNORE} ]] && sleep ${1:-5}
931 }
932
933 # @FUNCTION: ebeep
934 # @USAGE: [number of beeps]
935 # @DESCRIPTION:
936 # Issue the specified number of beeps (default of 5 beeps).  Useful when
937 # printing a message the user should probably be reading and often used in
938 # conjunction with the epause function.  If the EBEEP_IGNORE env var is set,
939 # don't beep at all. Defined in EAPIs 0 1 and 2.
940 ebeep() {
941         local n
942         if [[ -z ${EBEEP_IGNORE} ]] ; then
943                 for ((n=1 ; n <= ${1:-5} ; n++)) ; do
944                         echo -ne "\a"
945                         sleep 0.1 &>/dev/null ; sleep 0,1 &>/dev/null
946                         echo -ne "\a"
947                         sleep 1
948                 done
949         fi
950 }
951
952 ;;
953 *)
954
955 ebeep() {
956         ewarn "QA Notice: ebeep is not defined in EAPI=${EAPI}, please file a bug at https://bugs.gentoo.org"
957 }
958
959 epause() {
960         ewarn "QA Notice: epause is not defined in EAPI=${EAPI}, please file a bug at https://bugs.gentoo.org"
961 }
962
963 ;;
964 esac
965
966 case ${EAPI:-0} in
967 0|1|2|3|4)
968
969 # @FUNCTION: usex
970 # @USAGE: <USE flag> [true output] [false output] [true suffix] [false suffix]
971 # @DESCRIPTION:
972 # Proxy to declare usex for package managers or EAPIs that do not provide it
973 # and use the package manager implementation when available (i.e. EAPI >= 5).
974 # If USE flag is set, echo [true output][true suffix] (defaults to "yes"),
975 # otherwise echo [false output][false suffix] (defaults to "no").
976 usex() { use "$1" && echo "${2-yes}$4" || echo "${3-no}$5" ; } #382963
977
978 ;;
979 esac
980
981 case ${EAPI:-0} in
982 0|1|2|3|4|5)
983
984 # @FUNCTION: einstalldocs
985 # @DESCRIPTION:
986 # Install documentation using DOCS and HTML_DOCS.
987 #
988 # If DOCS is declared and non-empty, all files listed in it are
989 # installed. The files must exist, otherwise the function will fail.
990 # In EAPI 4 and subsequent EAPIs DOCS may specify directories as well,
991 # in other EAPIs using directories is unsupported.
992 #
993 # If DOCS is not declared, the files matching patterns given
994 # in the default EAPI implementation of src_install will be installed.
995 # If this is undesired, DOCS can be set to empty value to prevent any
996 # documentation from being installed.
997 #
998 # If HTML_DOCS is declared and non-empty, all files and/or directories
999 # listed in it are installed as HTML docs (using dohtml).
1000 #
1001 # Both DOCS and HTML_DOCS can either be an array or a whitespace-
1002 # separated list. Whenever directories are allowed, '<directory>/.' may
1003 # be specified in order to install all files within the directory
1004 # without creating a sub-directory in docdir.
1005 #
1006 # Passing additional options to dodoc and dohtml is not supported.
1007 # If you needed such a thing, you need to call those helpers explicitly.
1008 einstalldocs() {
1009         debug-print-function ${FUNCNAME} "${@}"
1010
1011         local dodoc_opts=-r
1012         has ${EAPI} 0 1 2 3 && dodoc_opts=
1013
1014         if ! declare -p DOCS &>/dev/null ; then
1015                 local d
1016                 for d in README* ChangeLog AUTHORS NEWS TODO CHANGES \
1017                                 THANKS BUGS FAQ CREDITS CHANGELOG ; do
1018                         if [[ -s ${d} ]] ; then
1019                                 dodoc "${d}" || die
1020                         fi
1021                 done
1022         elif [[ $(declare -p DOCS) == "declare -a"* ]] ; then
1023                 if [[ ${DOCS[@]} ]] ; then
1024                         dodoc ${dodoc_opts} "${DOCS[@]}" || die
1025                 fi
1026         else
1027                 if [[ ${DOCS} ]] ; then
1028                         dodoc ${dodoc_opts} ${DOCS} || die
1029                 fi
1030         fi
1031
1032         if [[ $(declare -p HTML_DOCS 2>/dev/null) == "declare -a"* ]] ; then
1033                 if [[ ${HTML_DOCS[@]} ]] ; then
1034                         dohtml -r "${HTML_DOCS[@]}" || die
1035                 fi
1036         else
1037                 if [[ ${HTML_DOCS} ]] ; then
1038                         dohtml -r ${HTML_DOCS} || die
1039                 fi
1040         fi
1041
1042         return 0
1043 }
1044
1045 # @FUNCTION: in_iuse
1046 # @USAGE: <flag>
1047 # @DESCRIPTION:
1048 # Determines whether the given flag is in IUSE. Strips IUSE default prefixes
1049 # as necessary.
1050 #
1051 # Note that this function should not be used in the global scope.
1052 in_iuse() {
1053         debug-print-function ${FUNCNAME} "${@}"
1054         [[ ${#} -eq 1 ]] || die "Invalid args to ${FUNCNAME}()"
1055
1056         local flag=${1}
1057         local liuse=( ${IUSE} )
1058
1059         has "${flag}" "${liuse[@]#[+-]}"
1060 }
1061
1062 ;;
1063 esac
1064
1065 fi