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