#!/bin/bash # Copyright 1999-2017 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 export DESTTREE=/usr export INSDESTTREE="" export _E_EXEDESTTREE_="" export _E_DOCDESTTREE_="" export INSOPTIONS="-m0644" export EXEOPTIONS="-m0755" export LIBOPTIONS="-m0644" export DIROPTIONS="-m0755" export MOPREFIX=$(PN) # Do not compress files which are smaller than this (in bytes). #169260 export PORTAGE_DOCOMPRESS_SIZE_LIMIT="128" declare -a PORTAGE_DOCOMPRESS=( /usr/share/{doc,info,man} ) declare -a PORTAGE_DOCOMPRESS_SKIP=( /usr/share/doc/${PF}/html ) proc into { if test $1 == "/" { export DESTTREE="" } else { export DESTTREE=$1 if ! ___eapi_has_prefix_variables { local ED=$(D) } if test ! -d "$(ED)$(DESTTREE)" { install -d "$(ED)$(DESTTREE)" local ret=$Status if [[ $ret -ne 0 ]] { __helpers_die "$(FUNCNAME[0]) failed" return $ret } } } } proc insinto { if test $1 == "/" { export INSDESTTREE="" } else { export INSDESTTREE=$1 if ! ___eapi_has_prefix_variables { local ED=$(D) } if test ! -d "$(ED)$(INSDESTTREE)" { install -d "$(ED)$(INSDESTTREE)" local ret=$Status if [[ $ret -ne 0 ]] { __helpers_die "$(FUNCNAME[0]) failed" return $ret } } } } proc exeinto { if test $1 == "/" { export _E_EXEDESTTREE_="" } else { export _E_EXEDESTTREE_="$1" if ! ___eapi_has_prefix_variables { local ED=$(D) } if test ! -d "$(ED)$(_E_EXEDESTTREE_)" { install -d "$(ED)$(_E_EXEDESTTREE_)" local ret=$Status if [[ $ret -ne 0 ]] { __helpers_die "$(FUNCNAME[0]) failed" return $ret } } } } proc docinto { if test $1 == "/" { export _E_DOCDESTTREE_="" } else { export _E_DOCDESTTREE_="$1" if ! ___eapi_has_prefix_variables { local ED=$(D) } if test ! -d "$(ED)usr/share/doc/$(PF)/$(_E_DOCDESTTREE_)" { install -d "$(ED)usr/share/doc/$(PF)/$(_E_DOCDESTTREE_)" local ret=$Status if [[ $ret -ne 0 ]] { __helpers_die "$(FUNCNAME[0]) failed" return $ret } } } } proc insopts { export INSOPTIONS="$ifsjoin(Argv)" # `install` should never be called with '-s' ... has -s $(INSOPTIONS) && die "Never call insopts() with -s" } proc diropts { export DIROPTIONS="$ifsjoin(Argv)" } proc exeopts { export EXEOPTIONS="$ifsjoin(Argv)" # `install` should never be called with '-s' ... has -s $(EXEOPTIONS) && die "Never call exeopts() with -s" } proc libopts { export LIBOPTIONS="$ifsjoin(Argv)" # `install` should never be called with '-s' ... has -s $(LIBOPTIONS) && die "Never call libopts() with -s" } proc docompress { ___eapi_has_docompress || die "'docompress' not supported in this EAPI" local f g if [[ $1 = "-x" ]] { shiftfor f in @Argv { setglobal f = $[__strip_duplicate_slashes $(f)]; setglobal f = $(f%/) [[ ${f:0:1} = / ]] || setglobal f = ""/$(f)"" for g in [$(PORTAGE_DOCOMPRESS_SKIP[@])] { [[ ${f} = "${g}" ]] && continue 2 } compat array-assign PORTAGE_DOCOMPRESS_SKIP '${#PORTAGE_DOCOMPRESS_SKIP[@]}' $(f) } } else {for f in @Argv { setglobal f = $[__strip_duplicate_slashes $(f)]; setglobal f = $(f%/) [[ ${f:0:1} = / ]] || setglobal f = ""/$(f)"" for g in [$(PORTAGE_DOCOMPRESS[@])] { [[ ${f} = "${g}" ]] && continue 2 } compat array-assign PORTAGE_DOCOMPRESS '${#PORTAGE_DOCOMPRESS[@]}' $(f) } } } proc useq { has $EBUILD_PHASE prerm postrm || eqawarn \ "QA Notice: The 'useq' function is deprecated (replaced by 'use')" use $(1) } proc usev { if use $(1) { echo $(1#!) return 0 } return 1 } if ___eapi_has_usex { proc usex { if use $1 { echo "$(2-yes)$4" } else { echo "$(3-no)$5" } return 0 } } proc use { local u=$1 local found=0 # if we got something like '!flag', then invert the return value if [[ ${u:0:1} == "!" ]] { setglobal u = $(u:1) setglobal found = '1' } if [[ $EBUILD_PHASE = depend ]] { # TODO: Add a registration interface for eclasses to register # any number of phase hooks, so that global scope eclass # initialization can by migrated to phase hooks in new EAPIs. # Example: add_phase_hook before pkg_setup $ECLASS_pre_pkg_setup #if [[ -n $EAPI ]] && ! has "$EAPI" 0 1 2 3 ; then # die "use() called during invalid phase: $EBUILD_PHASE" #fi true # Make sure we have this USE flag in IUSE, but exempt binary # packages for API consumers like Entropy which do not require # a full profile with IUSE_IMPLICIT and stuff (see bug #456830). } elif [[ -n $PORTAGE_IUSE && -n $EBUILD_PHASE && -n $PORTAGE_INTERNAL_CALLER ]] { if [[ ! $u =~ $PORTAGE_IUSE ]] { if [[ ! ${EAPI} =~ ^(0|1|2|3|4|4-python|4-slot-abi)$ ]] { # This is only strict starting with EAPI 5, since implicit IUSE # is not well defined for earlier EAPIs (see bug #449708). die "USE Flag '$(u)' not in IUSE for $(CATEGORY)/$(PF)" } eqawarn "QA Notice: USE Flag '$(u)' not" \ "in IUSE for $(CATEGORY)/$(PF)" } } local IFS=$' \t\n' prev_shopts=$Flags ret set -f if has $(u) $(USE) { setglobal ret = $(found) } else { setglobal ret = $shExpr('!found') } [[ ${prev_shopts} == *f* ]] || set +f return ${ret} } proc use_with { if test -z $1 { echo "!!! use_with() called without a parameter." > !2 echo "!!! use_with [ [value]]" > !2 return 1 } if ___eapi_use_enable_and_use_with_support_empty_third_argument { local UW_SUFFIX=$(3+=$3) } else { local UW_SUFFIX=$(3:+=$3) } local UWORD=$(2:-$1) if use $1 { echo "--with-$(UWORD)$(UW_SUFFIX)" } else { echo "--without-$(UWORD)" } return 0 } proc use_enable { if test -z $1 { echo "!!! use_enable() called without a parameter." > !2 echo "!!! use_enable [ [value]]" > !2 return 1 } if ___eapi_use_enable_and_use_with_support_empty_third_argument { local UE_SUFFIX=$(3+=$3) } else { local UE_SUFFIX=$(3:+=$3) } local UWORD=$(2:-$1) if use $1 { echo "--enable-$(UWORD)$(UE_SUFFIX)" } else { echo "--disable-$(UWORD)" } return 0 } proc unpack { local srcdir local x local y y_insensitive local suffix suffix_insensitive local myfail local eapi=$(EAPI:-0) test -z "$ifsjoin(Argv)" && die "Nothing passed to the 'unpack' command" for x in [@Argv] { __vecho ">>> Unpacking $(x) to $(PWD)" setglobal suffix = $(x##*.) setglobal suffix_insensitive = $[env LC_ALL=C tr "[:upper:]" "[:lower:]" <<< $(suffix)] setglobal y = $(x%.*) setglobal y = $(y##*.) setglobal y_insensitive = $[env LC_ALL=C tr "[:upper:]" "[:lower:]" <<< $(y)] # wrt PMS 11.3.3.13 Misc Commands if [[ ${x} != */* ]] { # filename without path of any kind setglobal srcdir = "$(DISTDIR)/" } elif [[ ${x} == ./* ]] { # relative path starting with './' setglobal srcdir = '' } else { # non-'./' filename with path of some kind if ___eapi_unpack_supports_absolute_paths { # EAPI 6 allows absolute and deep relative paths setglobal srcdir = '' if [[ ${x} == ${DISTDIR%/}/* ]] { eqawarn "QA Notice: unpack called with redundant \${DISTDIR} in path" } } elif [[ ${x} == ${DISTDIR%/}/* ]] { die "Arguments to unpack() cannot begin with \${DISTDIR} in EAPI $(EAPI)" } elif [[ ${x} == /* ]] { die "Arguments to unpack() cannot be absolute in EAPI $(EAPI)" } else { die "Relative paths to unpack() must be prefixed with './' in EAPI $(EAPI)" } } if [[ ! -s ${srcdir}${x} ]] { __helpers_die "unpack: $(x) does not exist" return 1 } proc __unpack_tar { if [[ ${y_insensitive} == tar ]] { if ___eapi_unpack_is_case_sensitive && \ [[ tar != ${y} ]] { eqawarn "QA Notice: unpack called with" \ "secondary suffix '$(y)' which is unofficially" \ "supported with EAPI '$(EAPI)'. Instead use 'tar'." } $1 -c -- "$srcdir$x" | tar xof - __assert_sigpipe_ok $myfail || return 1 } else { local cwd_dest=$(x##*/) setglobal cwd_dest = $(cwd_dest%.*) if ! $1 -c -- "$(srcdir)$(x)" > $(cwd_dest) { __helpers_die $myfail return 1 } } } setglobal myfail = ""unpack: failure unpacking $(x)"" match $(suffix_insensitive) { with tar if ___eapi_unpack_is_case_sensitive && \ [[ tar != ${suffix} ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'. Instead use 'tar'." } if ! tar xof "$srcdir$x" { __helpers_die $myfail return 1 } with tgz if ___eapi_unpack_is_case_sensitive && \ [[ tgz != ${suffix} ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'. Instead use 'tgz'." } if ! tar xozf "$srcdir$x" { __helpers_die $myfail return 1 } with tbz|tbz2 if ___eapi_unpack_is_case_sensitive && \ [[ " tbz tbz2 " != *" ${suffix} "* ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'. Instead use 'tbz' or 'tbz2'." } $(PORTAGE_BUNZIP2_COMMAND:-${PORTAGE_BZIP2_COMMAND} -d) -c -- "$srcdir$x" | tar xof - __assert_sigpipe_ok $myfail || return 1 with zip|jar if ___eapi_unpack_is_case_sensitive && \ [[ " ZIP zip jar " != *" ${suffix} "* ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'." \ "Instead use 'ZIP', 'zip', or 'jar'." } # unzip will interactively prompt under some error conditions, # as reported in bug #336285 if ! unzip -qo "$(srcdir)$(x)" { __helpers_die $myfail return 1 } < <(set +x ; while true ; do echo n || break ; done) with gz|z if ___eapi_unpack_is_case_sensitive && \ [[ " gz z Z " != *" ${suffix} "* ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'. Instead use 'gz', 'z', or 'Z'." } __unpack_tar "gzip -d" || return 1 with bz2|bz if ___eapi_unpack_is_case_sensitive && \ [[ " bz bz2 " != *" ${suffix} "* ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'. Instead use 'bz' or 'bz2'." } __unpack_tar $(PORTAGE_BUNZIP2_COMMAND:-${PORTAGE_BZIP2_COMMAND} -d) \ || return 1 with 7z local my_output setglobal my_output = $[7z x -y "$(srcdir)$(x)] if test $Status -ne 0 { echo $(my_output) > !2 die $myfail } with rar if ___eapi_unpack_is_case_sensitive && \ [[ " rar RAR " != *" ${suffix} "* ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'. Instead use 'rar' or 'RAR'." } if ! unrar x -idq -o+ "$(srcdir)$(x)" { __helpers_die $myfail return 1 } with lha|lzh if ___eapi_unpack_is_case_sensitive && \ [[ " LHA LHa lha lzh " != *" ${suffix} "* ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'." \ "Instead use 'LHA', 'LHa', 'lha', or 'lzh'." } if ! lha xfq "$(srcdir)$(x)" { __helpers_die $myfail return 1 } with a if ___eapi_unpack_is_case_sensitive && \ [[ " a " != *" ${suffix} "* ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'. Instead use 'a'." } if ! ar x "$(srcdir)$(x)" { __helpers_die $myfail return 1 } with deb if ___eapi_unpack_is_case_sensitive && \ [[ " deb " != *" ${suffix} "* ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'. Instead use 'deb'." } # Unpacking .deb archives can not always be done with # `ar`. For instance on AIX this doesn't work out. # If `ar` is not the GNU binutils version and we have # `deb2targz` installed, prefer it over `ar` for that # reason. We just make sure on AIX `deb2targz` is # installed. if [[ $(ar --version 2>/dev/null) != "GNU ar"* ]] && \ type -P deb2targz > /dev/null { setglobal y = $(x##*/) local created_symlink=0 if test ! "$srcdir$x" -ef $y { # deb2targz always extracts into the same directory as # the source file, so create a symlink in the current # working directory if necessary. if ! ln -sf "$srcdir$x" $y { __helpers_die $myfail return 1 } setglobal created_symlink = '1' } if ! deb2targz $y { __helpers_die $myfail return 1 } if test $created_symlink = 1 { # Clean up the symlink so the ebuild # doesn't inadvertently install it. rm -f $y } if ! mv -f "$(y%.deb)".tar.gz data.tar.gz { if ! mv -f "$(y%.deb)".tar.xz data.tar.xz { __helpers_die $myfail return 1 } } } else { if ! ar x "$srcdir$x" { __helpers_die $myfail return 1 } } with lzma if ___eapi_unpack_is_case_sensitive && \ [[ " lzma " != *" ${suffix} "* ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'. Instead use 'lzma'." } __unpack_tar "lzma -d" || return 1 with xz if ___eapi_unpack_is_case_sensitive && \ [[ " xz " != *" ${suffix} "* ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'. Instead use 'xz'." } if ___eapi_unpack_supports_xz { __unpack_tar "xz -d" || return 1 } else { __vecho "unpack $(x): file format not recognized. Ignoring." } with txz if ___eapi_unpack_is_case_sensitive && \ [[ " txz " != *" ${suffix} "* ]] { eqawarn "QA Notice: unpack called with" \ "suffix '$(suffix)' which is unofficially supported" \ "with EAPI '$(EAPI)'. Instead use 'txz'." } if ___eapi_unpack_supports_txz { if ! tar xof "$srcdir$x" { __helpers_die $myfail return 1 } } else { __vecho "unpack $(x): file format not recognized. Ignoring." } with * __vecho "unpack $(x): file format not recognized. Ignoring." } } # Do not chmod '.' since it's probably ${WORKDIR} and PORTAGE_WORKDIR_MODE # should be preserved. find . -mindepth 1 -maxdepth 1 ! -type l -print0 | \ $(XARGS) -0 "$(PORTAGE_BIN_PATH)/chmod-lite" } proc econf { local x local pid=$(BASHPID:-$(__bashpid)) if ! ___eapi_has_prefix_variables { local EPREFIX= } proc __hasg { local x s=$1 shiftfor x in @Argv { [[ ${x} == ${s} ]] && echo $(x) && return 0 ; } return 1 } proc __hasgq { __hasg @Argv >/dev/null ; } local phase_func=$[__ebuild_arg_to_phase $EBUILD_PHASE] if [[ -n $phase_func ]] { if ! ___eapi_has_src_configure { [[ $phase_func != src_compile ]] && \ eqawarn "QA Notice: econf called in" \ "$phase_func instead of src_compile" } else { [[ $phase_func != src_configure ]] && \ eqawarn "QA Notice: econf called in" \ "$phase_func instead of src_configure" } } : $(ECONF_SOURCE:=.) if test -x "$(ECONF_SOURCE)/configure" { if [[ -n $CONFIG_SHELL && \ "$(head -n1 "$ECONF_SOURCE/configure")" =~ ^'#!'[[:space:]]*/bin/sh([[:space:]]|$) ]] { cp -p "$(ECONF_SOURCE)/configure" "$(ECONF_SOURCE)/configure._portage_tmp_.$(pid)" || die sed -i \ -e "1s:^#![[:space:]]*/bin/sh:#!$CONFIG_SHELL:" \ "$(ECONF_SOURCE)/configure._portage_tmp_.$(pid)" \ || die "Substition of shebang in '$(ECONF_SOURCE)/configure' failed" # preserve timestamp, see bug #440304 touch -r "$(ECONF_SOURCE)/configure" "$(ECONF_SOURCE)/configure._portage_tmp_.$(pid)" || die mv -f "$(ECONF_SOURCE)/configure._portage_tmp_.$(pid)" "$(ECONF_SOURCE)/configure" || die } if test -e "$(EPREFIX)"/usr/share/gnuconfig/ { find $(WORKDIR) -type f '(' \ -name config.guess -o -name config.sub ')' -print0 | \ while read -r -d $'\0' x { __vecho " * econf: updating $(x/${WORKDIR}\/) with $(EPREFIX)/usr/share/gnuconfig/$(x##*/)" # Make sure we do this atomically incase we're run in parallel. #487478 cp -f "$(EPREFIX)"/usr/share/gnuconfig/"$(x##*/)" "$(x).$(pid)" mv -f "$(x).$(pid)" $(x) } } local conf_args=() if ___eapi_econf_passes_--disable-dependency-tracking || ___eapi_econf_passes_--disable-silent-rules || ___eapi_econf_passes_--docdir_and_--htmldir { local conf_help=$["$(ECONF_SOURCE)/configure" --help !2 >/dev/null] if ___eapi_econf_passes_--disable-dependency-tracking { if [[ ${conf_help} == *--disable-dependency-tracking* ]] { setglobal conf_args = ''( --disable-dependency-tracking ) } } if ___eapi_econf_passes_--disable-silent-rules { if [[ ${conf_help} == *--disable-silent-rules* ]] { setglobal conf_args = ''( --disable-silent-rules ) } } if ___eapi_econf_passes_--docdir_and_--htmldir { if [[ ${conf_help} == *--docdir* ]] { setglobal conf_args = ''( --docdir="${EPREFIX}"/usr/share/doc/${PF} ) } if [[ ${conf_help} == *--htmldir* ]] { setglobal conf_args = ''( --htmldir="${EPREFIX}"/usr/share/doc/${PF}/html ) } } } # if the profile defines a location to install libs to aside from default, pass it on. # if the ebuild passes in --libdir, they're responsible for the conf_libdir fun. local CONF_LIBDIR LIBDIR_VAR="LIBDIR_$(ABI)" if [[ -n ${ABI} && -n ${!LIBDIR_VAR} ]] { setglobal CONF_LIBDIR = $(!LIBDIR_VAR) } if [[ -n ${CONF_LIBDIR} ]] && ! __hasgq --libdir='*' @Argv { export CONF_PREFIX=$[__hasg --exec-prefix='*' @Argv] [[ -z ${CONF_PREFIX} ]] && setglobal CONF_PREFIX = $[__hasg --prefix='*' @Argv] : $(CONF_PREFIX:=${EPREFIX}/usr) setglobal CONF_PREFIX = $(CONF_PREFIX#*=) [[ ${CONF_PREFIX} != /* ]] && setglobal CONF_PREFIX = ""/$(CONF_PREFIX)"" [[ ${CONF_LIBDIR} != /* ]] && setglobal CONF_LIBDIR = ""/$(CONF_LIBDIR)"" setglobal conf_args = ''( --libdir="$(__strip_duplicate_slashes "${CONF_PREFIX}${CONF_LIBDIR}")" ) } # Handle arguments containing quoted whitespace (see bug #457136). eval "local -a EXTRA_ECONF=($(EXTRA_ECONF))" set -- \ --prefix="$(EPREFIX)"/usr \ $(CBUILD:+--build=${CBUILD}) \ --host=$(CHOST) \ $(CTARGET:+--target=${CTARGET}) \ --mandir="$(EPREFIX)"/usr/share/man \ --infodir="$(EPREFIX)"/usr/share/info \ --datadir="$(EPREFIX)"/usr/share \ --sysconfdir="$(EPREFIX)"/etc \ --localstatedir="$(EPREFIX)"/var/lib \ $(conf_args[@]) \ @Argv \ $(EXTRA_ECONF[@]) __vecho "$(ECONF_SOURCE)/configure" @Argv if ! "$(ECONF_SOURCE)/configure" @Argv { if test -s config.log { echo echo "!!! Please attach the following file when seeking support:" echo "!!! $(PWD)/config.log" } __helpers_die "econf failed" return 1 } } elif test -f "$(ECONF_SOURCE)/configure" { die "configure is not executable" } else { die "no configure script found" } } proc einstall { if ! ___eapi_has_einstall { die "'$(FUNCNAME)' has been banned for EAPI '$EAPI'" exit 1 } # CONF_PREFIX is only set if they didn't pass in libdir above. local LOCAL_EXTRA_EINSTALL="$(EXTRA_EINSTALL)" if ! ___eapi_has_prefix_variables { local ED=$(D) } setglobal LIBDIR_VAR = ""LIBDIR_$(ABI)"" if test -n $(ABI) -a -n $(!LIBDIR_VAR) { setglobal CONF_LIBDIR = $(!LIBDIR_VAR) } unset LIBDIR_VAR if test -n $(CONF_LIBDIR) && test $(CONF_PREFIX:+set) = set { setglobal EI_DESTLIBDIR = ""$(D)/$(CONF_PREFIX)/$(CONF_LIBDIR)"" setglobal EI_DESTLIBDIR = $[__strip_duplicate_slashes $(EI_DESTLIBDIR)] setglobal LOCAL_EXTRA_EINSTALL = ""libdir=$(EI_DESTLIBDIR) $(LOCAL_EXTRA_EINSTALL)"" unset EI_DESTLIBDIR } if test -f ./[mM]akefile -o -f ./GNUmakefile { if test $(PORTAGE_DEBUG) == "1" { $(MAKE:-make) -n prefix="$(ED)usr" \ datadir="$(ED)usr/share" \ infodir="$(ED)usr/share/info" \ localstatedir="$(ED)var/lib" \ mandir="$(ED)usr/share/man" \ sysconfdir="$(ED)etc" \ $(LOCAL_EXTRA_EINSTALL) \ $(MAKEOPTS) -j1 \ @Argv $(EXTRA_EMAKE) install } if ! $(MAKE:-make) prefix="$(ED)usr" \ datadir="$(ED)usr/share" \ infodir="$(ED)usr/share/info" \ localstatedir="$(ED)var/lib" \ mandir="$(ED)usr/share/man" \ sysconfdir="$(ED)etc" \ $(LOCAL_EXTRA_EINSTALL) \ $(MAKEOPTS) -j1 \ @Argv $(EXTRA_EMAKE) install { __helpers_die "einstall failed" return 1 } } else { die "no Makefile found" } } proc __eapi0_pkg_nofetch { [[ -z ${A} ]] && return elog "The following files cannot be fetched for $(PN):" local x for x in [$(A)] { elog " $(x)" } } proc __eapi0_src_unpack { [[ -n ${A} ]] && unpack $(A) } proc __eapi0_src_compile { if test -x ./configure { econf } __eapi2_src_compile } proc __eapi0_src_test { # Since we don't want emake's automatic die # support (EAPI 4 and later), and we also don't # want the warning messages that it produces if # we call it in 'nonfatal' mode, we use emake_cmd # to emulate the desired parts of emake behavior. local emake_cmd="$(MAKE:-make) $(MAKEOPTS) $(EXTRA_EMAKE)" local internal_opts= if ___eapi_default_src_test_disables_parallel_jobs { setglobal internal_opts = '" -j1'" } if $emake_cmd $(internal_opts) check -n &> /dev/null { __vecho "$(emake_cmd) $(internal_opts) check" > !2 $emake_cmd $(internal_opts) check || \ die "Make check failed. See above for details." } elif $emake_cmd $(internal_opts) test -n &> /dev/null { __vecho "$(emake_cmd) $(internal_opts) test" > !2 $emake_cmd $(internal_opts) test || \ die "Make test failed. See above for details." } } proc __eapi1_src_compile { __eapi2_src_configure __eapi2_src_compile } proc __eapi2_src_prepare { : } proc __eapi2_src_configure { if [[ -x ${ECONF_SOURCE:-.}/configure ]] { econf } } proc __eapi2_src_compile { if test -f Makefile || test -f GNUmakefile || test -f makefile { emake || die "emake failed" } } proc __eapi4_src_install { if [[ -f Makefile || -f GNUmakefile || -f makefile ]] { emake DESTDIR="$(D)" install } if ! declare -p DOCS &>/dev/null { local d for d in [README* ChangeLog AUTHORS NEWS TODO CHANGES \ THANKS BUGS FAQ CREDITS CHANGELOG] { [[ -s "${d}" ]] && dodoc $(d) } } elif [[ $(declare -p DOCS) == "declare -a "* ]] { dodoc $(DOCS[@]) } else { dodoc $(DOCS) } } proc __eapi6_src_prepare { if [[ $(declare -p PATCHES 2>/dev/null) == "declare -a"* ]] { [[ -n ${PATCHES[@]} ]] && eapply $(PATCHES[@]) } elif [[ -n ${PATCHES} ]] { eapply $(PATCHES) } eapply_user } proc __eapi6_src_install { if [[ -f Makefile || -f GNUmakefile || -f makefile ]] { emake DESTDIR="$(D)" install } einstalldocs } # @FUNCTION: has_version # @USAGE: [--host-root] # @DESCRIPTION: # Return true if given package is installed. Otherwise return false. # Callers may override the ROOT variable in order to match packages from an # alternative ROOT. proc has_version { local atom eroot host_root=false root=$(ROOT) if [[ $1 == --host-root ]] { setglobal host_root = 'true' shift } setglobal atom = $1 shift test $Argc -gt 0 && die "$(FUNCNAME[0]): unused argument(s): $ifsjoin(Argv)" if $(host_root) { if ! ___eapi_best_version_and_has_version_support_--host-root { die "$(FUNCNAME[0]): option --host-root is not supported with EAPI $(EAPI)" } setglobal root = '/' } if ___eapi_has_prefix_variables { # [[ ${root} == / ]] would be ambiguous here, # since both prefixes can share root=/ while # having different EPREFIX offsets. if $(host_root) { setglobal eroot = "$(root%/)$(PORTAGE_OVERRIDE_EPREFIX)/" } else { setglobal eroot = "$(root%/)$(EPREFIX)/" } } else { setglobal eroot = $(root) } if [[ -n $PORTAGE_IPC_DAEMON ]] { "$PORTAGE_BIN_PATH"/ebuild-ipc has_version $(eroot) $(atom) } else { "$(PORTAGE_BIN_PATH)/ebuild-helpers/portageq" has_version $(eroot) $(atom) } local retval=$Status match $(retval) { with 0|1 return ${retval} with 2 die "$(FUNCNAME[0]): invalid atom: $(atom)" with * if [[ -n ${PORTAGE_IPC_DAEMON} ]] { die "$(FUNCNAME[0]): unexpected ebuild-ipc exit code: $(retval)" } else { die "$(FUNCNAME[0]): unexpected portageq exit code: $(retval)" } } } # @FUNCTION: best_version # @USAGE: [--host-root] # @DESCRIPTION: # Returns highest installed matching category/package-version (without .ebuild). # Callers may override the ROOT variable in order to match packages from an # alternative ROOT. proc best_version { local atom eroot host_root=false root=$(ROOT) if [[ $1 == --host-root ]] { setglobal host_root = 'true' shift } setglobal atom = $1 shift test $Argc -gt 0 && die "$(FUNCNAME[0]): unused argument(s): $ifsjoin(Argv)" if $(host_root) { if ! ___eapi_best_version_and_has_version_support_--host-root { die "$(FUNCNAME[0]): option --host-root is not supported with EAPI $(EAPI)" } setglobal root = '/' } if ___eapi_has_prefix_variables { # [[ ${root} == / ]] would be ambiguous here, # since both prefixes can share root=/ while # having different EPREFIX offsets. if $(host_root) { setglobal eroot = "$(root%/)$(PORTAGE_OVERRIDE_EPREFIX)/" } else { setglobal eroot = "$(root%/)$(EPREFIX)/" } } else { setglobal eroot = $(root) } if [[ -n $PORTAGE_IPC_DAEMON ]] { "$PORTAGE_BIN_PATH"/ebuild-ipc best_version $(eroot) $(atom) } else { "$(PORTAGE_BIN_PATH)/ebuild-helpers/portageq" best_version $(eroot) $(atom) } local retval=$Status match $(retval) { with 0|1 return ${retval} with 2 die "$(FUNCNAME[0]): invalid atom: $(atom)" with * if [[ -n ${PORTAGE_IPC_DAEMON} ]] { die "$(FUNCNAME[0]): unexpected ebuild-ipc exit code: $(retval)" } else { die "$(FUNCNAME[0]): unexpected portageq exit code: $(retval)" } } } if ___eapi_has_get_libdir { proc get_libdir { local libdir_var="LIBDIR_$(ABI)" local libdir="lib" [[ -n ${ABI} && -n ${!libdir_var} ]] && setglobal libdir = $(!libdir_var) echo $(libdir) } } if ___eapi_has_einstalldocs { proc einstalldocs { shell { if ! declare -p DOCS &>/dev/null { local d for d in [README* ChangeLog AUTHORS NEWS TODO CHANGES \ THANKS BUGS FAQ CREDITS CHANGELOG] { [[ -f ${d} && -s ${d} ]] && docinto / && dodoc $(d) } } elif [[ $(declare -p DOCS) == "declare -a"* ]] { [[ ${DOCS[@]} ]] && docinto / && dodoc -r $(DOCS[@]) } else { [[ ${DOCS} ]] && docinto / && dodoc -r $(DOCS) } } shell { if [[ $(declare -p HTML_DOCS 2>/dev/null) == "declare -a"* ]] { [[ ${HTML_DOCS[@]} ]] && \ docinto html && dodoc -r $(HTML_DOCS[@]) } else { [[ ${HTML_DOCS} ]] && \ docinto html && dodoc -r $(HTML_DOCS) } } } } if ___eapi_has_eapply { proc eapply { local failed patch_cmd=patch local -x LC_COLLATE=POSIX # for bsd userland support, use gpatch if available type -P gpatch > /dev/null && setglobal patch_cmd = 'gpatch' proc _eapply_patch { local f=$(1) local prefix=$(2) setglobal started_applying = '1' ebegin "$(prefix:-Applying )$(f##*/)" # -p1 as a sane default # -f to avoid interactivity # -s to silence progress output # -g0 to guarantee no VCS interaction # --no-backup-if-mismatch not to pollute the sources $(patch_cmd) -p1 -f -s -g0 --no-backup-if-mismatch \ $(patch_options[@]) < $(f) setglobal failed = ${?$(?) if ! eend $(failed) { __helpers_die "patch -p1 $(patch_options[*]) failed with $(f)" } } local patch_options=() files=() local i found_doublehyphen # first, try to split on -- for (( i = 1; i <= ${#@}; ++i )); do if [[ ${@:i:1} == -- ]]; then patch_options=( "${@:1:i-1}" ) files=( "${@:i+1}" ) found_doublehyphen=1 break fi done # then, try to split on first non-option if [[ -z ${found_doublehyphen} ]] { for (( i = 1; i <= ${#@}; ++i )); do if [[ ${@:i:1} != -* ]]; then patch_options=( "${@:1:i-1}" ) files=( "${@:i}" ) break fi done # ensure that no options were interspersed with files for i in [$(files[@])] { if [[ ${i} == -* ]] { die "eapply: all options must be passed before non-options" } } } if [[ -z ${files[@]} ]] { die "eapply: no files specified" } local f for f in [$(files[@])] { if [[ -d ${f} ]] { proc _eapply_get_files { local LC_ALL=POSIX local prev_shopt=$[shopt -p nullglob] shopt -s nullglob local f for f in ["$(1)"/*] { if [[ ${f} == *.diff || ${f} == *.patch ]] { setglobal files = ''( "${f}" ) } } $(prev_shopt) } local files=() _eapply_get_files $(f) [[ -z ${files[@]} ]] && die "No *.{patch,diff} files in directory $(f)" einfo "Applying patches from $(f) ..." local f2 for f2 in [$(files[@])] { _eapply_patch $(f2) ' ' # in case of nonfatal [[ ${failed} -ne 0 ]] && return "${failed}" } } else { _eapply_patch $(f) # in case of nonfatal [[ ${failed} -ne 0 ]] && return "${failed}" } } return 0 } } if ___eapi_has_eapply_user { proc eapply_user { [[ ${EBUILD_PHASE} == prepare ]] || \ die "eapply_user() called during invalid phase: $(EBUILD_PHASE)" # keep path in __dyn_prepare in sync! local tagfile=$(T)/.portage_user_patches_applied [[ -f ${tagfile} ]] && return >> $(tagfile) local basedir=$(PORTAGE_CONFIGROOT%/)/etc/portage/patches local applied d f local -A _eapply_user_patches local prev_shopt=$[shopt -p nullglob] shopt -s nullglob # Patches from all matched directories are combined into a # sorted (POSIX order) list of the patch basenames. Patches # in more-specific directories override patches of the same # basename found in less-specific directories. An empty patch # (or /dev/null symlink) negates a patch with the same # basename found in a less-specific directory. # # order of specificity: # 1. ${CATEGORY}/${P}-${PR} (note: -r0 desired to avoid applying # ${P} twice) # 2. ${CATEGORY}/${P} # 3. ${CATEGORY}/${PN} # all of the above may be optionally followed by a slot for d in []"${basedir}"/${CATEGORY}/{${P}-${PR},${P},${PN}}{:${SLOT%/*},} { for f in ["$(d)"/*] { if [[ ( ${f} == *.diff || ${f} == *.patch ) && -z ${_eapply_user_patches[${f##*/}]} ]] { compat array-assign _eapply_user_patches '${f##*/}' $(f) } } } if [[ ${#_eapply_user_patches[@]} -gt 0 ]] { while read -r -d '' f { setglobal f = $(_eapply_user_patches[${f}]) if [[ -s ${f} ]] { eapply $(f) setglobal applied = '1' } } < <(printf -- '%s\0' "${!_eapply_user_patches[@]}" | LC_ALL=C sort -z) } $(prev_shopt) [[ -n ${applied} ]] && ewarn "User patches applied." } } if ___eapi_has_in_iuse { proc in_iuse { local use=$(1) if [[ -z "${use}" ]] { echo "!!! in_iuse() called without a parameter." > !2 echo "!!! in_iuse " > !2 die "in_iuse() called without a parameter" } local liuse=( ${IUSE_EFFECTIVE} ) has $(use) $(liuse[@]#[+-]) } } if ___eapi_has_master_repositories { proc master_repositories { local output repository=$1 retval shift [[ $# -gt 0 ]] && die "$(FUNCNAME[0]): unused argument(s): $ifsjoin(Argv)" if [[ -n ${PORTAGE_IPC_DAEMON} ]] { "$(PORTAGE_BIN_PATH)/ebuild-ipc" master_repositories $(EROOT) $(repository) } else { setglobal output = $["$(PORTAGE_BIN_PATH)/ebuild-helpers/portageq" master_repositories $(EROOT) $(repository)] } setglobal retval = $Status [[ -n ${output} ]] && echo $(output) match $(retval) { with 0|1 return ${retval} with 2 die "$(FUNCNAME[0]): invalid repository: $(repository)" with * if [[ -n ${PORTAGE_IPC_DAEMON} ]] { die "$(FUNCNAME[0]): unexpected ebuild-ipc exit code: $(retval)" } else { die "$(FUNCNAME[0]): unexpected portageq exit code: $(retval)" } } } } if ___eapi_has_repository_path { proc repository_path { local output repository=$1 retval shift [[ $# -gt 0 ]] && die "$(FUNCNAME[0]): unused argument(s): $ifsjoin(Argv)" if [[ -n ${PORTAGE_IPC_DAEMON} ]] { "$(PORTAGE_BIN_PATH)/ebuild-ipc" repository_path $(EROOT) $(repository) } else { setglobal output = $["$(PORTAGE_BIN_PATH)/ebuild-helpers/portageq" get_repo_path $(EROOT) $(repository)] } setglobal retval = $Status [[ -n ${output} ]] && echo $(output) match $(retval) { with 0|1 return ${retval} with 2 die "$(FUNCNAME[0]): invalid repository: $(repository)" with * if [[ -n ${PORTAGE_IPC_DAEMON} ]] { die "$(FUNCNAME[0]): unexpected ebuild-ipc exit code: $(retval)" } else { die "$(FUNCNAME[0]): unexpected portageq exit code: $(retval)" } } } } if ___eapi_has_available_eclasses { proc available_eclasses { local output repository=$(PORTAGE_REPO_NAME) retval [[ $# -gt 0 ]] && die "$(FUNCNAME[0]): unused argument(s): $ifsjoin(Argv)" if [[ -n ${PORTAGE_IPC_DAEMON} ]] { "$(PORTAGE_BIN_PATH)/ebuild-ipc" available_eclasses $(EROOT) $(repository) } else { setglobal output = $["$(PORTAGE_BIN_PATH)/ebuild-helpers/portageq" available_eclasses $(EROOT) $(repository)] } setglobal retval = $Status [[ -n ${output} ]] && echo $(output) match $(retval) { with 0|1 return ${retval} with 2 die "$(FUNCNAME[0]): invalid repository: $(repository)" with * if [[ -n ${PORTAGE_IPC_DAEMON} ]] { die "$(FUNCNAME[0]): unexpected ebuild-ipc exit code: $(retval)" } else { die "$(FUNCNAME[0]): unexpected portageq exit code: $(retval)" } } } } if ___eapi_has_eclass_path { proc eclass_path { local eclass=$1 output repository=$(PORTAGE_REPO_NAME) retval shift [[ $# -gt 0 ]] && die "$(FUNCNAME[0]): unused argument(s): $ifsjoin(Argv)" if [[ -n ${PORTAGE_IPC_DAEMON} ]] { "$(PORTAGE_BIN_PATH)/ebuild-ipc" eclass_path $(EROOT) $(repository) $(eclass) } else { setglobal output = $["$(PORTAGE_BIN_PATH)/ebuild-helpers/portageq" eclass_path $(EROOT) $(repository) $(eclass)] } setglobal retval = $Status [[ -n ${output} ]] && echo $(output) match $(retval) { with 0|1 return ${retval} with 2 die "$(FUNCNAME[0]): invalid repository: $(repository)" with * if [[ -n ${PORTAGE_IPC_DAEMON} ]] { die "$(FUNCNAME[0]): unexpected ebuild-ipc exit code: $(retval)" } else { die "$(FUNCNAME[0]): unexpected portageq exit code: $(retval)" } } } } if ___eapi_has_license_path { proc license_path { local license=$1 output repository=$(PORTAGE_REPO_NAME) retval shift [[ $# -gt 0 ]] && die "$(FUNCNAME[0]): unused argument(s): $ifsjoin(Argv)" if [[ -n ${PORTAGE_IPC_DAEMON} ]] { "$(PORTAGE_BIN_PATH)/ebuild-ipc" license_path $(EROOT) $(repository) $(license) } else { setglobal output = $["$(PORTAGE_BIN_PATH)/ebuild-helpers/portageq" license_path $(EROOT) $(repository) $(license)] } setglobal retval = $Status [[ -n ${output} ]] && echo $(output) match $(retval) { with 0|1 return ${retval} with 2 die "$(FUNCNAME[0]): invalid repository: $(repository)" with * if [[ -n ${PORTAGE_IPC_DAEMON} ]] { die "$(FUNCNAME[0]): unexpected ebuild-ipc exit code: $(retval)" } else { die "$(FUNCNAME[0]): unexpected portageq exit code: $(retval)" } } } } if ___eapi_has_package_manager_build_user { proc package_manager_build_user { echo $(PORTAGE_BUILD_USER) } } if ___eapi_has_package_manager_build_group { proc package_manager_build_group { echo $(PORTAGE_BUILD_GROUP) } }