#!/bin/bash # Copyright 1999-2003 Gentoo Technologies, Inc. # Distributed under the terms of the GNU General Public License v2 # $Header: /home/cvsroot/gentoo-src/portage/bin/ebuild.sh,v 1.168 2004/06/02 23:28:05 carpaski Exp $ ORIG_VARS=`declare | egrep '^[^[:space:]{}()]+=' | cut -s -d '=' -f 1` ORIG_FUNCS=`declare -F | cut -s -d ' ' -f 3` DONT_EXPORT_FUNCS='' DONT_EXPORT_VARS='COMPLETED_EBUILD_PHASES TMP TMPDIR CCACHE_DIR ROOTPATH myarg SANDBOX_DISABLED BASH_VERSINFO EUID PPID SHELLOPTS UID' #DEBUGGING="yes" export SANDBOX_PREDICT="${SANDBOX_PREDICT:+${SANDBOX_PREDICT}:}/proc/self/maps:/dev/console:/usr/lib/portage/pym:/dev/random" export SANDBOX_WRITE="${SANDBOX_WRITE:+${SANDBOX_WRITE}:}/dev/shm:${PORTAGE_TMPDIR}" export SANDBOX_READ="${SANDBOX_READ:+${SANDBOX_READ}:}/dev/shm:${PORTAGE_TMPDIR}" # Prevent aliases from causing portage to act inappropriately. # Make sure it's before everything so we don't mess aliases that follow. unalias -a # We need this next line for "die" and "assert". It expands # It _must_ preceed all the calls to die and assert. shopt -s expand_aliases # Unset some variables that break things. unset GZIP BZIP BZIP2 CDPATH GREP_OPTIONS GREP_COLOR alias die='diefunc "$FUNCNAME" "$LINENO" "$?"' alias assert='_pipestatus="${PIPESTATUS[*]}"; [[ "${_pipestatus// /}" -eq 0 ]] || diefunc "$FUNCNAME" "$LINENO" "$_pipestatus"' diefunc() { local funcname="$1" lineno="$2" exitcode="$3" shift 3 echo >&2 echo "!!! ERROR: $CATEGORY/$PF failed." >&2 echo "!!! Function $funcname, Line $lineno, Exitcode $exitcode" >&2 echo "!!! ${*:-(no error message)}" >&2 echo "!!! If you need support, post the topmost build error, NOT this status message." >&2 echo >&2 exit 1 } hasq() { local x local me=$1 shift # All the TTY checks really only help out depend. Which is nice. # Logging kills all this anyway. Everything becomes a pipe. --NJ for x in "$@"; do if [ "${x}" == "${me}" ]; then return 0 fi done return 1 } #if no perms are specified, dirs/files will have decent defaults #(not secretive, but not stupid) umask 022 # the sandbox is disabled by default except when overridden in the relevant stages export SANDBOX_ON="0" gen_filter() { if [ "$#" == 0 ]; then return fi echo -n '(' while [ "$1" ]; do echo -n "$1" shift if [ "$1" ]; then echo -n '|' fi done echo -n ')' } dump_environ() { local f x; debug-print "dumping env" f=`declare | egrep -on -m1 '^[^ ]+ \(\) +$'` f="$(( ${f/:*/} - 1 ))" declare | head -n $f | egrep -v "^`gen_filter ${DONT_EXPORT_VARS} f x y`="; f=`declare -F | cut -s -d ' ' -f 3 | egrep -v "^$(gen_filter ${DONT_EXPORT_FUNCS} )\$"`; #can't just use which --read-functions, see bug #55522 for x in ${f}; do type ${x} | tail -n +2; done echo "reinstate_loaded_env_attributes ()" echo "{" # declare -rxi | egrep -o '^declare -[airtx]+ [^=]+' | egrep -v " `gen_filter ${DONT_EXPORT_VARS} f x y`\$" # echo " export $(echo $(export | cut -s -d '=' -f 1 | cut -s -d ' ' -f 3 | egrep -v "^$(gen_filter ${DONT_EXPORT_VARS} f x y)$"))" # echo " readonly $(echo $(readonly | cut -s -d '=' -f 1 | cut -s -d ' ' -f 3 | egrep -v "^$(gen_filter ${DONT_EXPORT_VARS} f x y)$"))" # echo " declare -i $(echo $(declare -i | cut -s -d '=' -f 1| cut -s -d ' ' -f 3 | egrep -v "$(gen_filter ${DONT_EXPORT_VARS} f x y)$"))" # declare -F | egrep -v "^declare -(f |[aFfirtx]+ `gen_filter ${f} `)\$"; x=`export | egrep -o '^declare +-[airtx]+ +[^=]+' | cut -s -d ' ' -f 3 | egrep -v "^$(gen_filter ${DONT_EXPORT_VARS} f x y)$"` [ ! -z "$x" ] && echo " export `echo $x`" x=`readonly | egrep -o '^declare +-[airtx]+ +[^=]+'| cut -s -d ' ' -f 3 | egrep -v "^$(gen_filter ${DONT_EXPORT_VARS} f x y)$"` [ ! -z "$x" ] && echo " readonly `echo $x`" x=`declare -i | egrep -o '^declare +-[airtx]+ +[^=]+' | cut -s -d ' ' -f 3 | egrep -v "$(gen_filter ${DONT_EXPORT_VARS} f x y)$"` [ ! -z "$x" ] && echo " declare -i $x" declare -F | egrep "^declare -[aFfirtx]+ $(gen_filter ${f} )\$" | egrep -v "^declare -f " echo " unset reinstate_loaded_env_attributes" echo "}" debug-print "dumped" if [ ! -z ${DEBUGGING} ]; then echo "#dumping debug info" echo "#var filter..." echo "#$(gen_filter ${DONT_EXPORT_VARS} f x | sort)" echo "#func filter..." echo "#$(gen_filter ${DONT_EXPORT_FUNCS} | sort)" echo "#DONT_EXPORT_VARS follow" for x in `echo $DONT_EXPORT_VARS | sort`; do echo "# $x"; done echo "" echo "#DONT_EXPORT_FUNCS follow" for x in `echo $DONT_EXPORT_FUNCS | sort`; do echo "# $x"; done fi } #selectively saves the environ- specifically removes things that have been marked to not be exported. export_environ() { # echo "exporting env for ${EBUILD_PHASE}" >&2 local temp_umask if [ "${1:-unset}" == "unset" ]; then die "export_environ requires at least one arguement" fi #the spaces on both sides are important- otherwise, the later ${DONT_EXPORT_VARS/ temp_umask /} won't match. #we use spaces on both sides, to ensure we don't remove part of a variable w/ the same name- # ex: temp_umask_for_some_app == _for_some_app. #Do it with spaces on both sides. DONT_EXPORT_VARS="${DONT_EXPORT_VARS} temp_umask " temp_umask=`umask` umask 0002 debug-print "exporting env for ${EBUILD_PHASE} to $1, using optional post-processor '${2:-none}'" if [ "${2:-unset}" == "unset" ]; then dump_environ > "$1" else dump_environ | $2 > "$1" fi if [ ! -z ${DEBUGGING} ]; then SANDBOX_WRITE="/tmp/blah:${SANDBOX_WRITE}" { declare -p; declare -rxi; } > /tmp/blah fi chown portage:portage "$1" &>/dev/null chmod 0664 "$1" &>/dev/null DONT_EXPORT_VARS="${DONT_EXPORT_VARS/ temp_umask /}" umask $temp_umask debug-print "exported." } load_environ() { local src #protect the exterior env to some degree from older saved envs, where *everything* was dumped (no filters applied) local SANDBOX_STATE=$SANDBOX_ON local EBUILD_PHASE=$EBUILD_PHASE SANDBOX_ON=0 SANDBOX_READ="/bin:${SANDBOX_READ}:/dev/urandom:/dev/random:/usr/lib/portage/bin/" SANDBOX_ON=$SANDBOX_STATE if [ ! -z $DEBUGGING ]; then echo "loading env for $EBUILD_PHASE" >&2 fi if [ "${PORT_ENV_FILE:-unset}" != "unset" ]; then src="$PORT_ENV_FILE" else src="${T}/environment" COMPLETED_EBUILD_PHASES="`cat ${BUILDDIR}/.completed_stages 2> /dev/null`" # echo "COMPLETED_EBUILD_PHASE loaded=${COMPLETED_EBUILD_PHASES}" >&2 fi debug-print "loading environment from $src" if [ -f "$src" ]; then if [ "${src%.bz2}" != "${src}" ]; then echo "eval bz2" >&2 eval "`bzcat $src`" &> /dev/null || die "failed loading env" else # echo "loading src $src phase ${EBUILD_PHASE}">&2 source "${src}" &> /dev/null || die "failed loading env" fi else echo "ebuild=${EBUILD}" >&2 echo "dir=`ls ${EBUILD%/*}`" >&2 die "wtf, load_environ called yet $src doesn't exist. phase=${EBUILD_PHASE}" fi if [ -f "${BUILDDIR}/.completed_stages" ]; then COMPLETED_EBUILD_PHASES=`cat ${BUILDDIR}/.completed_stages` else COMPLETED_EBUILD_PHASES='' fi } init_environ() { # echo "initializating environment" >&2 OCC="$CC" OCXX="$CXX" if [ "${EBUILD_PHASE}" == "setup" ]; then #we specifically save the env so it's not stomped on by sourcing. #bug 51552 declare > "${T}/.temp_env" fi if [ "$USERLAND" == "GNU" ]; then source /etc/profile.env &>/dev/null fi if [ -f "${PORTAGE_BASHRC}" ]; then source "${PORTAGE_BASHRC}" fi if [ "${EBUILD_PHASE}" == "setup" ]; then #restore the saved env vars. #we're not filtering vars for this dump, so silence it for read only complaints (BASH_VERSINFO comes to mind) source "${T}/.temp_env" &> /dev/null rm "${T}/.temp_env" fi [ ! -z "$OCC" ] && export CC="$OCC" [ ! -z "$OCXX" ] && export CXX="$OCXX" export PATH="/sbin:/usr/sbin:/usr/lib/portage/bin:/bin:/usr/bin:${ROOTPATH}" [ ! -z "$PREROOTPATH" ] && export PATH="${PREROOTPATH%%:}:$PATH" export DESTTREE=/usr export INSDESTTREE="" export EXEDESTTREE="" export DOCDESTTREE="" export INSOPTIONS="-m0644" export EXEOPTIONS="-m0755" export LIBOPTIONS="-m0644" export DIROPTIONS="-m0755" export MOPREFIX=${PN} debug-print "initing environment anew" #this may belong being stored w/ the ebuild. Not sure. if [ -e /etc/init.d/functions.sh ]; then source /etc/init.d/functions.sh &>/dev/null elif [ -e /etc/rc.d/config/functions ]; then source /etc/rc.d/config/functions &>/dev/null else #Mac OS X source /usr/lib/portage/bin/functions.sh &>/dev/null fi if [ "$USERLAND" == "BSD" ]; then alias make=gmake alias tar=gtar alias patch=gpatch alias sed=gsed fi source "/usr/lib/portage/bin/ebuild-functions.sh" || die "failed sourcing ebuild-functions.sh" export SANDBOX_ON="1" export S=${WORKDIR}/${P} unset IUSE DEPEND RDEPEND CDEPEND PDEPEND unset E_IUSE E_DEPEND E_RDEPEND E_CDEPEND E_PDEPEND if [ ! -f "${EBUILD}" ]; then die "EBUILD=${EBUILD}; problem is, it doesn't exist. bye." >&2 fi eval "`cat ${EBUILD}; echo;echo 'true'`" || die "error sourcing ebuild" [ -z "${ERRORMSG}" ] || die "${ERRORMSG}" hasq nostrip ${RESTRICT} && export DEBUGBUILD=1 #a reasonable default for $S if [ "$S" = "" ]; then export S=${WORKDIR}/${P} fi #some users have $TMP/$TMPDIR to a custom dir in their home ... #this will cause sandbox errors with some ./configure #scripts, so set it to $T. export TMP="${T}" export TMPDIR="${T}" # Note: this next line is not the same as export RDEPEND=${RDEPEND:-${DEPEND}} # That will test for unset *or* NULL (""). We want just to set for unset... #turn off glob expansion from here on in to prevent *'s and ? in the DEPEND #syntax from getting expanded :) Fixes bug #1473 set -f if [ "${RDEPEND-unset}" == "unset" ]; then export RDEPEND="${DEPEND}" debug-print "RDEPEND: not set... Setting to: ${DEPEND}" fi #add in dependency info from eclasses IUSE="$IUSE $E_IUSE" DEPEND="${DEPEND} ${E_DEPEND}" RDEPEND="$RDEPEND $E_RDEPEND" CDEPEND="$CDEPEND $E_CDEPEND" PDEPEND="$PDEPEND $E_PDEPEND" unset E_IUSE E_DEPEND E_RDEPEND E_CDEPEND E_PDEPEND declare -r DEPEND RDEPEND SLOT SRC_URI RESTRICT HOMEPAGE LICENSE DESCRIPTION declare -r KEYWORDS INHERITED IUSE CDEPEND PDEPEND PROVIDE COMPLETED_EBUILD_PHASES='' # echo "DONT_EXPORT_FUNCS=$DONT_EXPORT_FUNCS" >&2 } source "/usr/lib/portage/bin/ebuild-default-functions.sh" || die "failed sourcing ebuild-default-functions.sh" #echo, everything has been sourced. now level the read-only's. for x in ${DONT_EXPORT_FUNCS}; do declare -r "$x" done f=`declare | egrep -on -m1 '^[^ ]+ \(\) +$'` f="$(( ${f/:*/} - 1 ))" if [ -z "${ORIG_VARS}" ]; then DONT_EXPORT_VARS="${DONT_EXPORT_VARS} $(declare | head -n $f | cut -s -d '=' -f 1)" else DONT_EXPORT_VARS="${DONT_EXPORT_VARS} $(declare | head -n $f | cut -s -d '=' -f 1 | egrep -v \"^`gen_filter ${ORIG_VARS}`\$\")" fi unset f if [ -z "${ORIG_FUNCS}" ]; then DONT_EXPORT_FUNCS="${DONT_EXPORT_FUNCS} $(declare -F | cut -s -d ' ' -f 3)" else # DONT_EXPORT_FUNCS="${DONT_EXPORT_FUNCS} $(declare -F | cut -s -d ' ' -f 3 | egrep -v \"^`gen_filter ${ORIG_FUNCS}`\$\")" DONT_EXPORT_FUNCS="${DONT_EXPORT_FUNCS} $(declare -F | cut -s -d ' ' -f 3 )" fi set +f for myarg in $*; do EBUILD_PHASE="$myarg" MUST_EXPORT_ENV="no" # echo "processing $EBUILD_PHASE" if [ `id -nu` == "portage" ] ; then export USER=portage fi case $EBUILD_PHASE in nofetch) init_environ pkg_nofetch # exit 1 ;; prerm|postrm|postinst|config) export SANDBOX_ON="0" load_environ if type reinstate_loaded_env_attributes &> /dev/null; then reinstate_loaded_env_attributes fi if [ -f "${T}/successful" ]; then rm -f "${T}/successful" fi if [ "$PORTAGE_DEBUG" != "1" ]; then pkg_${EBUILD_PHASE} #Allow non-zero return codes since they can be caused by && else set -x pkg_${EBUILD_PHASE} #Allow non-zero return codes since they can be caused by && set +x fi ;; clean) if [ "${SANDBOX_DISABLED="0"}" == "0" ]; then export SANDBOX_ON="1" else export SANDBOX_ON="0" fi killparent() { trap INT kill ${PORTAGE_MASTER_PID} } trap "killparent" INT # echo "cleaning..." >&2 # enable_qa_interceptors init_environ # disable_qa_interceptors trap - INT unset killparent if [ "$PORTAGE_DEBUG" != "1" ]; then dyn_${EBUILD_PHASE} #Allow non-zero return codes since they can be caused by && else set -x dyn_${EBUILD_PHASE} #Allow non-zero return codes since they can be caused by && set +x fi export SANDBOX_ON="0" MUST_EXPORT_ENV="no" unset COMPLETED_EBUILD_PHASES ;; unpack|compile|test|install) if [ "${SANDBOX_DISABLED="0"}" == "0" ]; then export SANDBOX_ON="1" else export SANDBOX_ON="0" fi load_environ if type reinstate_loaded_env_attributes &> /dev/null; then # echo "reinstating attribs" >&2 reinstate_loaded_env_attributes fi if [ -f "${T}/successful" ]; then rm -f "${T}/successful" fi if [ "$PORTAGE_DEBUG" != "1" ]; then dyn_${EBUILD_PHASE} #Allow non-zero return codes since they can be caused by && else set -x dyn_${EBUILD_PHASE} #Allow non-zero return codes since they can be caused by && set +x fi COMPLETED_EBUILD_PHASES="${COMPLETED_EBUILD_PHASES} ${EBUILD_PHASE}" export SANDBOX_ON="0" ;; setup) #pkg_setup needs to be out of the sandbox for tmp file creation; #for example, awking and piping a file in /tmp requires a temp file to be created #in /etc. If pkg_setup is in the sandbox, both our lilo and apache ebuilds break. export SANDBOX_ON="0" temp_ebuild_phase=`cat "${BUILDDIR}/.completed_stages" 2> /dev/null` if hasq setup ${temp_ebuild_phase}; then unset temp_ebuild_phase MUST_EXPORT_ENV="no" else unset temp_ebuild_phase init_environ MUST_EXPORT_ENV="yes" if [ "$PORTAGE_DEBUG" != "1" ]; then dyn_${EBUILD_PHASE} else set -x dyn_${EBUILD_PHASE} set +x fi if hasq distcc ${FEATURES} &>/dev/null; then if [ -d /usr/lib/distcc/bin ]; then #We can enable distributed compile support if [ -z "${PATH/*distcc*/}" ]; then # Remove the other reference. remove_path_entry "distcc" fi export PATH="/usr/lib/distcc/bin:${PATH}" [ ! -z "${DISTCC_LOG}" ] && addwrite "$(dirname ${DISTCC_LOG})" elif type -p distcc &>/dev/null; then export CC="distcc $CC" export CXX="distcc $CXX" fi fi if hasq ccache ${FEATURES} &>/dev/null; then #We can enable compiler cache support if [ -z "${PATH/*ccache*/}" ]; then # Remove the other reference. remove_path_entry "ccache" fi if [ -d /usr/lib/ccache/bin ]; then export PATH="/usr/lib/ccache/bin:${PATH}" elif [ -d /usr/bin/ccache ]; then export PATH="/usr/bin/ccache:${PATH}" fi [ -z "${CCACHE_DIR}" ] && export CCACHE_DIR="/root/.ccache" addread "${CCACHE_DIR}" addwrite "${CCACHE_DIR}" [ -z "${CCACHE_SIZE}" ] && export CCACHE_SIZE="2G" ccache -M ${CCACHE_SIZE} &> /dev/null fi fi COMPLETED_EBUILD_PHASES="${COMPLETED_EBUILD_PHASES} ${EBUILD_PHASE}" ;; help|preinst) #pkg_setup needs to be out of the sandbox for tmp file creation; #for example, awking and piping a file in /tmp requires a temp file to be created #in /etc. If pkg_setup is in the sandbox, both our lilo and apache ebuilds break. export SANDBOX_ON="0" init_environ if [ "$PORTAGE_DEBUG" != "1" ]; then dyn_${EBUILD_PHASE} else set -x dyn_${EBUILD_PHASE} set +x fi COMPLETED_EBUILD_PHASES="${COMPLETED_EBUILD_PHASES} ${EBUILD_PHASE}" ;; package|rpm) export SANDBOX_ON="0" load_environ if type reinstate_loaded_env_attributes &> /dev/null; then reinstate_loaded_env_attributes fi if [ "$PORTAGE_DEBUG" != "1" ]; then dyn_${EBUILD_PHASE} else set -x dyn_${EBUILD_PHASE} set +x fi COMPLETED_EBUILD_PHASES="${COMPLETED_EBUILD_PHASES} ${EBUILD_PHASE}" ;; depend) export SANDBOX_ON="0" set -f killparent() { trap INT kill ${PORTAGE_MASTER_PID} } trap "killparent" INT enable_qa_interceptors init_environ disable_qa_interceptors trap - INT unset killparent if [ ! -d "${dbkey%/*}" ]; then install -d -g ${PORTAGE_GID} -m2775 "${dbkey%/*}" fi # Make it group writable. 666&~002==664 umask 002 #temporary hack. SANDBOX_WRITE="${SANDBOX_WRITE}:${dbkey}" #the extra `echo` commands remove newlines echo `echo "$DEPEND"` > $dbkey echo `echo "$RDEPEND"` >> $dbkey echo `echo "$SLOT"` >> $dbkey echo `echo "$SRC_URI"` >> $dbkey echo `echo "$RESTRICT"` >> $dbkey echo `echo "$HOMEPAGE"` >> $dbkey echo `echo "$LICENSE"` >> $dbkey echo `echo "$DESCRIPTION"` >> $dbkey echo `echo "$KEYWORDS"` >> $dbkey echo `echo "$INHERITED"` >> $dbkey echo `echo "$IUSE"` >> $dbkey echo `echo "$CDEPEND"` >> $dbkey echo `echo "$PDEPEND"` >> $dbkey echo `echo "$PROVIDE"` >> $dbkey echo `echo "$UNUSED_01"` >> $dbkey echo `echo "$UNUSED_02"` >> $dbkey echo `echo "$UNUSED_03"` >> $dbkey echo `echo "$UNUSED_04"` >> $dbkey echo `echo "$UNUSED_05"` >> $dbkey echo `echo "$UNUSED_06"` >> $dbkey echo `echo "$UNUSED_07"` >> $dbkey echo `echo "$UNUSED_08"` >> $dbkey set +f #make sure it is writable by our group: exit 0 ;; *) export SANDBOX_ON="1" echo "Please specify a valid command." echo dyn_help exit 1 ;; esac # echo "PHASE=${EBUILD_PHASE} COMPLETED=$COMPLETED_EBUILD_PHASES" >&2 if [ "${MUST_EXPORT_ENV}" == "yes" ]; then # echo "exporting environ ${EBUILD_PHASE}" >&2 export_environ "${T}/environment" list='' for x in ${COMPLETED_EBUILD_PHASES}; do if ! hasq $x $list; then list="${list} ${x}" fi done COMPLETED_EBUILD_PHASES="${list}" unset list # echo "${COMPLETED_EBUILD_PHASES}" > "${BUILDDIR}/.completed_stages" chown portage:portage "${BUILDDIR}/.completed_stages" &> /dev/null chmod g+w "${BUILDDIR}/.completed_stages" &> /dev/null MUST_EXPORT_ENV="no" fi done touch "${T}/successful" &>/dev/null chown portage:portage "${T}/successful" &>/dev/null chmod g+w "${T}/successful" &>/dev/null exit 0