view sources/utility_functions.sh @ 1391:42ec661e3916

Fix BINARY_PACKAGE_TARBALLS generation: some packages produce no output (zlib used to build dropbear for example), and thus check for an empty list before trying to make a tarball.
author Rob Landley <rob@landley.net>
date Fri, 17 Jun 2011 13:00:17 -0500
parents e26390768b3c
children 9a3f7ada5cb1
line wrap: on
line source

#!/bin/echo "This file is sourced, not run"

# This file contains generic functions, presumably reusable in other contexts.

# Unset all environment variables that we don't know about, in case some crazy
# person already exported $CROSS_COMPILE, $ARCH, $CDPATH, or who knows what
# else.  It's hard to know what might drive some package crazy, so use a
# whitelist.

sanitize_environment()
{
  # Which variables are set in config?

  TEMP=$(echo $(sed -n 's/.*export[ \t]*\([^=]*\)=.*/\1/p' config) | sed 's/ /,/g')

  # What other variables should we keep?

  TEMP="$TEMP,LANG,PATH,SHELL,TERM,USER,USERNAME,LOGNAME,PWD,EDITOR,HOME,DISPLAY,_"
  TEMP="$TEMP,TOPSHELL,START_TIME,STAGE_NAME,TOOLCHAIN_PREFIX,HOST_ARCH"
  TEMP="$TEMP,http_proxy,ftp_proxy,https_proxy,no_proxy"

  # Unset any variable we don't recognize.  It can screw up the build.

  for i in $(env | sed -n 's/=.*//p')
  do
    is_in_list $i "$TEMP" && continue
    [ "${i:0:7}" == "DISTCC_" ] && continue
    [ "${i:0:7}" == "CCACHE_" ] && continue

    unset $i 2>/dev/null
  done
}

# Assign (export) a variable only if current value is blank

export_if_blank()
{
  [ -z "$(eval "echo \"\${${1/=*/}}\"")" ] && export "$1"
}

# Create a blank directory at first argument, deleting existing contents if any

blank_tempdir()
{
  # sanity test: never rm -rf something we don't own.
  [ -z "$1" ] && dienow
  touch -c "$1" || dienow

  # Delete old directory, create new one.
  [ -z "$NO_CLEANUP" ] && rm -rf "$1"
  mkdir -p "$1" || dienow
}

# output the sha1sum of a file

sha1file()
{
  sha1sum "$@" | awk '{print $1}'
}

# dienow() is an exit function that works properly even from a subshell.
# (actually_dienow is run in the parent shell via signal handler.)

actually_dienow()
{
  echo -e "\n\e[31mExiting due to errors ($ARCH_NAME $STAGE_NAME $PACKAGE)\e[0m" >&2
  exit 1
}

trap actually_dienow SIGUSR1
TOPSHELL=$$

dienow()
{
  kill -USR1 $TOPSHELL
  exit 1
}

# Turn a bunch of output lines into a much quieter series of periods,
# roughly one per screenfull

dotprogress()
{
  x=0
  while read i
  do
    x=$[$x + 1]
    if [[ "$x" -eq 25 ]]
    then
      x=0
      echo -n .
    fi
  done
  echo
}

# Announce an action to the world

announce()
{
  # Write a line to the log file with easily greppable header
  echo "=== $1 ($ARCH_NAME $STAGE_NAME)"

  # Set the title bar of the current xterm
  [ -z "$NO_TITLE_BAR" ] && echo -en "\033]2;$ARCH_NAME $STAGE_NAME $1\007"
}

# Filter out unnecessary noise, keeping just lines starting with "==="

maybe_quiet()
{
  [ -z "$FORK" ] && cat || grep "^==="
}

# Run a command background if FORK is set, in foreground otherwise

maybe_fork()
{
  [ -z "$BUILD_VERBOSE" ] || echo "$*"

  if [ -z "$FORK" ]
  then
    eval "$*"
  else
    eval "$*" &
  fi
}

# Kill a process and all its decendants

killtree()
{
  local KIDS=""

  while [ $# -ne 0 ]
  do
    KIDS="$KIDS $(pgrep -P$1)"
    shift
  done

  KIDS="$(echo -n $KIDS)"
  if [ ! -z "$KIDS" ]
  then
    # Depth first kill avoids reparent_to_init hiding stuff.
    killtree $KIDS
    kill $KIDS 2>/dev/null
  fi
}

# Search a colon-separated path for files matching a pattern.

# Arguments are 1) path to search, 2) pattern, 3) command to run on each file.
# During command, $DIR/$FILE points to file found.

path_search()
{
  # For each each $PATH element, loop through each file in that directory,
  # and create a symlink to the wrapper with that name.  In the case of
  # duplicates, keep the first one.

  echo "$1" | sed 's/:/\n/g' | while read DIR
  do
    find "$DIR/" -maxdepth 1 -mindepth 1 -name "$2" | sed 's@.*/@@' | \
    while read FILE
    do
      eval "$3"

      # Output is verbose.  Pipe it to dotprogress.

      echo $FILE
    done
  done
}

# Abort if we haven't got a prerequisite in the $PATH

check_prerequisite()
{
  if [ -z "$(which "$1")" ]
  then
    [ -z "$FAIL_QUIET" ] && echo No "$1" in '$PATH'. >&2
    dienow
  fi
}

# Search through all the files under a directory and collapse together
# identical files into hardlinks

collapse_hardlinks()
{
  SHA1LIST=""
  find "$1" -type f | while read FILE
  do
    echo "$FILE"
    SHA1=$(sha1file "$FILE")
    MATCH=$(echo "$SHA1LIST" | grep "^$SHA1")
    if [ -z "$MATCH" ]
    then
      # Yes, the quote spanning two lines here is intentional
      SHA1LIST="$SHA1LIST
$SHA1 $FILE"
    else
      FILE2="$(echo "$MATCH" | sed 's/[^ ]* //')"
      cmp -s "$FILE" "$FILE2" || continue
      ln -f "$FILE" "$FILE2" || dienow
    fi
  done
}

# Check if $1 is in the comma separated list $2

is_in_list()
{
  [ "$2" == all ] || [ ! -z "$(echo ,"$2", | grep ,"$1",)" ]
}