#!/bin/bash
#
#                             stb225 Project
#                   ---------------------------------
#
# Copyright (C) 2009 NXP B.V.,
# All Rights Reserved.
#
# Filename: setup.sh
#
#
# Rev Date        Author      Comments
#-------------------------------------------------------------------------------
#  22 20070131    batelaan    Fail if PRJROOT already defined.
#  23 20070214    batelaan    sde2 ($_TMROOT) moved to toplevel.
#  24 20070419    batelaan    Cygwin compatibility.
#  25 20070531    batelaan    Improve determination of PRJROOT. Partial windows support.
#  26 20070628    batelaan    Rename site setup files.
#  27 20070820    batelaan    Abort setup if prjconfig fails.
#  28 20070823    batelaan    Prevent use of shell aliases.
#  29 20070829    amccurdy    Replace "eval `make foo`" with "eval `make --no-print-directory foo`"
#  30 20070913    batelaan    Define default for ELDK_ROOT.
#  31 20071026    batelaan    Undo changes that prevent it running again after failure.
#  32 20080213    batelaan    Add $PRJROOT/etc/perllib to $PERLLIB
#  33 20080306    batelaan    Toolchain now configured via prjconfig
#  34 20080513    batelaan    Pass all args to prjconfig.
#  35 20080715    batelaan    Require make v3.81
#  36 20080724    amccurdy    Replace 'make foo' with 'make --no-print-directory foo'
#  37 20080908    batelaan    Tar files compatibility and completeness checks
#  38 20080916    batelaan    Set default value for _TMMAKEJOBS
#  39 20090105    batelaan    base_other tarball renamed to base_open.
#                             Handle setup for GPL code build.
#                             Allow executing this script instead of source'ing.
#  40 20090316    batelaan    Improve error output and cleanup.
#  41 20090611    batelaan    Workaround for bash "exports inside function not surviving" problem
#  xx 20091125    amccurdy    Add warning if $HOME/bin/ccache_symlinks directory can not be found
#  xx 20091125    amccurdy    Add error if /bin/sh is a symlink to dash
#  xx 20091130    amccurdy    Detect /bin/sh is a symlink to dash when link uses an absolute path

# Setup script to be executed or sourced first before doing anything like running make!

# Utility functions
function _CheckOverride {
  eval local _overrideValue=\"\$${1}_override\"
  if [ ! -z "$_overrideValue" ]; then
    _SetVar $1 "$_overrideValue"
    /bin/echo; /bin/echo "**INFO: using ${1}_override ($_overrideValue) for $1"
    return 0
  fi
  return 1
}

function _SetOverride {
  _CheckOverride "$1" && return
  eval local _oldVarValue=\"\$$1\"
  if [ "$_oldVarValue" == "$2" ]; then
    export $1
  else
    if [ ! -z "$_oldVarValue" ]; then
      /bin/echo; /bin/echo "**INFO: $1 was already defined ($_oldVarValue)"
      /bin/echo "  Changing to $2"; /bin/echo
    fi
    _SetVar $1 "$2"
  fi
}

function _SetDontOverride {
  _CheckOverride "$@" && return
  eval local _oldVarValue=\"\$$1\"
  if [ "$_oldVarValue" == "$2" ]; then
    export $1
  else
    if [ ! -z "$_oldVarValue" ]; then
      /bin/echo; /bin/echo "**WARNING: $1 is already defined ($_oldVarValue)"
      /bin/echo "  _NOT_ updated to $2"; /bin/echo
    else
      _SetVar $1 "$2"
    fi
  fi
}

function _SetVar {
  _CleanupVars="$_CleanupVars $1"
  eval _OldVarValue_$1=\"\${$1=_Was_Undefined_}\"
  export $1="$2"
}

function _CleanupVars {
  local _var
  local _unsetVar=$1
  shift
  for _var in $*; do
    if [ "$_unsetVar" != 0 ]; then
      local _oldValue
      eval _oldValue=\"\$_OldVarValue_$_var\"
      if [ "$_oldValue" = "_Was_Undefined_" ]; then
        eval unset $_var
      else
        eval $_var=\"\$_oldValue\"
      fi
    fi
    eval unset _OldVarValue_$_var
  done
}

function _prjrootSetup {
  local arg1="$1"
  case "$arg1" in
    h|help|-h|--help)
      /bin/echo
      /bin/echo 'STB225 project environment setup script.'
      /bin/echo 'Usage: . PATH_TO/setup.sh [PRJCONFIG_ARG]'
      /bin/echo
      /bin/echo 'PRJCONFIG_ARG is passed to the prjconfig command.'
      /bin/echo 'For help on prjconfig, first execute the setup.sh script,'
      /bin/echo 'and then run "prjconfig help".'
      return 0
      ;;
  esac

  if 'test' -z "$BASH_VERSION"; then
    /bin/echo "**ERROR: BASH_VERSION variable is not set!"
    /bin/echo "Are you sure you are using the Bash shell?"
    return 1
  fi

  if [ "$(readlink /bin/sh | sed 's|.*/||')" = "dash" ]; then
    /bin/echo ""
    /bin/echo "**ERROR: /bin/sh appears to be a symlink to dash. This can cause build problems"
    /bin/echo ""
    /bin/echo "On Ubuntu, this can be fixed by running 'sudo dpkg-reconfigure dash'"
    /bin/echo "and selecting 'no' when asked whether to install dash as /bin/sh"
    /bin/echo ""
    return 1
  fi

  # Work out where this script lives.
  local _tmp=${BASH_SOURCE[0]%/*}
  if [ -z "$_tmp" ]; then _tmp=`'dirname' "$0"`; fi
  # Ensure it is absolute:
  _tmp=`cd "$_tmp" >&/dev/null && pwd`
  if [ ! -f "$_tmp/setup.sh" ]
  then
    /bin/echo "**ERROR: cannot determine PRJROOT path!"
    /bin/echo "(Could not determine path of directory containing setup.sh)"
    return 1
  fi
  if [ ! -z "$PRJROOT" ]; then
    /bin/echo
    /bin/echo '**ERROR: PRJROOT already defined'
    /bin/echo 'setup.sh should be run from a clean shell environment.'
    /bin/echo 'Aborted.'
    return 1
  fi

  # If using cygwin, pwd could return /cygdrive/X/...;
  # change this to X:... otherwise GNU make has big problems:
  if type cygpath &>/dev/null; then
    _tmp="`cygpath --windows \"$_tmp\" | tr '\\' /`"
  fi
  _SetOverride PRJROOT $_tmp
  cd $PRJROOT
  /bin/echo "PRJROOT=$PRJROOT"

  _SetDontOverride _TMSITE soustb
  [ -r $PRJROOT/etc/site_setup_$_TMSITE.sh ] && . $PRJROOT/etc/site_setup_$_TMSITE.sh setup_start ]

  # Tar file compatibility and completeness checks.
  # The check for tarballs from different release candidates is done
  # inside each etc/.*.info file.
  local fileinfo_stb225_source_proprietary=
  local fileinfo_stb225_base_proprietary=
  local fileinfo_stb225_base_gpl=
  local fileinfo_stb225_base_open=
  local fileinfo_ok=true
  local fileinfo_release=
  local f
  for f in etc/.*.info; do
    if [ -x "$f" ]; then
      . "$f"
    fi
  done
  if [ -n "$fileinfo_release" ]; then
    if [ -n "$fileinfo_stb225_source_proprietary" -a -n "$fileinfo_stb225_base_proprietary" ]; then
      /bin/echo '**ERROR: project workarea setup: too many tarballs:'
      /bin/echo '  The following tarballs are mutually exclusive:'
      /bin/echo '  - stb225_base_proprietary-XXX.tgz'
      /bin/echo '  - stb225_source_proprietary-XXX.tgz'
      fileinfo_ok=false
    fi
    if [ -z "$fileinfo_stb225_source_proprietary" -a -z "$fileinfo_stb225_base_proprietary" ]; then
      /bin/echo
      /bin/echo '**INFO: this workarea seems to be set-up to build the GPL code only.'
    fi
    if [ -z "$fileinfo_stb225_base_gpl" ]; then
      /bin/echo '**ERROR: project workarea setup: have you forgotten to extract stb225_base_gpl-XXX.tgz?'
      fileinfo_ok=false
    fi
    if [ -z "$fileinfo_stb225_base_open" ]; then
      /bin/echo '**ERROR: project workarea setup: have you forgotten to extract stb225_base_open-XXX.tgz?'
      fileinfo_ok=false
    fi
    if ! $fileinfo_ok; then
      /bin/echo 2>&1 'Aborting setup.sh'
      return 1
    fi
  fi

  if [ -d "$PRJROOT/tarballs" ]; then
    _SetOverride TARBALLS $PRJROOT/tarballs
  fi
  if [ ! -d "$TARBALLS" ]; then
    /bin/echo 2>&1 "**WARNING: \$TARBALLS ($TARBALLS) is not visible!"
  fi

  if [ -z "$PERLLIB" ]; then
    PERLLIB="$PRJROOT/etc/perllib"
  else
    PERLLIB="$PRJROOT/etc/perllib:$PERLLIB"
  fi
  export PERLLIB

  # SDE2 related setup:
  _SetOverride _TMROOT $PRJROOT/sde2
  _extrapath=$_TMROOT/sde/scripts:$_extrapath
  _SetOverride _TMPROJECT $_TMROOT/project
  if type cygpath &>/dev/null; then
    # cbuild needs unix style path:
    _SetOverride CBUILDCONFIGPATH "`cygpath \"$PRJROOT/etc\"`"
  else
    _SetOverride CBUILDCONFIGPATH $PRJROOT/etc
  fi

  case "`uname`" in
    Linux|linux) . $PRJROOT/etc/setup_linux.sh;;
    *) . $PRJROOT/etc/setup_windows.sh;;
  esac

  # Use function instead of alias so that these also work in scripts:
  function cbuild () { . $PRJROOT/bin/cbuild "$@" ; }
  export -f cbuild
  function prjconfig () { . $PRJROOT/etc/prjconfig.sh "$@" ; }
  export -f prjconfig

  _extrapath=$PRJROOT/bin:$_extrapath

  _SetDontOverride TFTPBOOT $HOME/tftpboot
  _SetDontOverride NFSROOT $HOME/nfsroot

  prjconfigCommand=$BASH_SOURCE
  case "x$arg1" in
    xn|xnoconfig) :
      ;;
    x) prjconfig oldconfig
      ;;
    *) prjconfig "$@"
      ;;
  esac
  if [ $? != 0 ]; then
    /bin/echo 2>&1 'Aborting setup.sh'
    return 1
  fi

  _extrapath=$BUILDROOT/bin:$_extrapath

  # Remove potential trailing colon:
  _extrapath="${_extrapath%:}"

  # Only prefix the PATH if $_extrapath is not there yet:
  if [ "${PATH#$_extrapath:}" == "$PATH" ]; then PATH=${_extrapath}:$PATH; fi
  # Clean up path if using cygwin, changing ':' to ';' where needed:
  if type cygpath &>/dev/null; then
    local PRJROOTx="`cygpath --unix \"$PRJROOT\"`"
    PATH="`perl -e \"\\$_=\\$ENV{PATH}; s!(^|:)$PRJROOT/!\\$1$PRJROOTx/!g; print;\"`"
  fi

  if [ -r $PRJROOT/etc/site_setup_$_TMSITE.sh ]; then
    . $PRJROOT/etc/site_setup_$_TMSITE.sh setup_end || return 1
  fi

  # If not already set, set number of parallel make jobs to the number of processors + 1.
  if [ -z "$_TMMAKEJOBS" ]; then
    _TMMAKEJOBS=`/bin/ls -d /sys/devices/system/cpu/cpu[0-9]*/ 2>/dev/null | wc -l`
    if [ -z "$_TMMAKEJOBS" ]; then
      _TMMAKEJOBS=`/bin/grep '^processor' /proc/cpuinfo 2>/dev/null | wc -l`
    fi
    let _TMMAKEJOBS="${_TMMAKEJOBS:-0}+1"
    export _TMMAKEJOBS
  fi

  # Builds are slow without ccache... warn if ccache_symlinks directory can not be found
  if [ ! -d "$HOME/bin/ccache_symlinks" ]; then
    /bin/echo ""
    /bin/echo "**WARNING: \${HOME}/bin/ccache_symlinks directory not found!"
    /bin/echo "Please install ccache and then run the 'install_ccache_symlinks' script"
    /bin/echo ""
  fi

  # We require make version 3.81 or later. (check for presence of lastword function)
  if [ "$(echo 'check:;@echo $(lastword OK)' | make --no-print-directory -s -f - check)" != OK ]; then
    /bin/echo "**ERROR: Too old a version of GNU make found (3.81 or later is required)!"
    /bin/echo "You we using $(type -p make); make -v prints:"
    make -v
    /bin/echo ""
    /bin/echo "Please download and build a newer version from http://www.gnu.org/software/make/"
    /bin/echo "Or upgrade your version of Linux."
    /bin/echo "Aborting."
    return 1
  fi

  # Work out if we can have a single CPU configuration available; if so, set it up,
  # otherwise tell the user.
  local configs_count
  if ! eval `make --no-print-directory configs_count.var || echo false`; then
    /bin/echo '**ERROR: "make configs_count.var" returned an error.'
    /bin/echo 'setup.sh aborting.'
    return 1
  fi
  case "$configs_count" in
   1)
    local configs
    if ! eval `make --no-print-directory configs.var || echo false`; then
      /bin/echo '**ERROR: "make configs.var" returned an error.'
      /bin/echo 'setup.sh aborting.'
      return 1
    fi
    _tmpSetupEnvVarsFile=/tmp/setup.sh.$LOGNAME.$$
    if ! make config.printenv >$_tmpSetupEnvVarsFile; then
      /bin/echo '**ERROR: "make config.printenv" returned an error.'
      /bin/echo 'setup.sh aborting.'
      /bin/rm -f $_tmpSetupEnvVarsFile
      return 1
    fi
    /bin/echo "Selected CPU configuration $configs."
   ;;
   0)
    /bin/echo '**ERROR: "make configs_count.var" returned 0 CPU configurations!'
    /bin/echo 'setup.sh aborting.'
    return 1
   ;;
   *)
    /bin/echo "$configs_count CPU configurations available for building. Run prjmake for more info."
  esac
  return 0
}

unset _tmpSetupEnvVarsFile
_prjrootSetup "$@"
_status=$?
if [ $_status == 0 ]; then
  if [ "$_tmpSetupEnvVarsFile" ]; then
    _SHLVLsave=$SHLVL
    . $_tmpSetupEnvVarsFile
    SHLVL=$_SHLVLsave
    unset _SHLVLsave
    /bin/rm $_tmpSetupEnvVarsFile
  fi
else
  unset -f prjconfig cbuild
fi
_CleanupVars $_status $_CleanupVars
unset -f _CheckOverride _SetOverride _SetDontOverride _prjrootSetup _SetVar _CleanupVars
unset _CleanupVars _extrapath prjconfigCommand _tmpSetupEnvVarsFile
if [ $_status = 0 -a "$0" = "$BASH_SOURCE" ]; then
    # All ok, AND we've not sourced but executed this setup script, so start an interactive shell:
    /bin/echo 'Starting build environment sub-shell (type exit or ^D to leave).'
    let PRJCONFIG_SHLVL=$PRJCONFIG_SHLVL+1
    /bin/bash
    /bin/echo 'Leaving build environment sub-shell.'
fi
'test' $_status = 0
