#!/bin/bash
# Part of the SMLinux distribution
# pktsurf.in

# Exit on any error
set -e 

# Store the source directory the build file was initiated from inside $SRCDIR
SRCDIR="$PWD"

# get relative directory name from SRCDIR
SRCDIRRPATH="$(basename $SRCDIR)"

# Generate sha512sums in the build file
genchecksum() {
  echo "Discarding old SHA512SUMS from $SRCDIRRPATH.SMBuild"
  sed -E -i \
  -e '/^SHA512SUMS=".*"$/d' \
  -e '/^SHA512SUMS="/,/"$/d' \
  -e "/^SHA512SUMS='.*'\$/d" \
  -e "/^SHA512sums='/,/'\$/d" \
  "$SRCDIRRPATH".SMBuild

  echo "Adding new SHA512SUMS in $SRCDIRRPATH.SMBuild..."
  printf 'SHA512SUMS="\n' >> "$SRCDIRRPATH".SMBuild

  # File types
  FILES=( *.tar.* *.zip *.t?z *.patch *.diff *.c *.h )

  # Checksum digest to be used along with arguments
  CHECKSUMBINARY="sha512sum"

  for FILE in ${FILES[@]} ; do
     if [ -f "$FILE" ] ; then
       $CHECKSUMBINARY $FILE >> "$SRCDIRRPATH".SMBuild
     fi
  done
  printf '"' >> "$SRCDIRRPATH".SMBuild
  echo "You may now run bldpkg again without any arguments"
  exit 0
}


if [ -n "$1" ] && [ "$1" = "genchecksum" ] ; then
  genchecksum
elif [ -n "$1" ] ; then
  if [ -f "$1" ]; then
    source "$1"
  else 
    echo "File not found!"
    exit 1
  fi
elif [ -z $1 ] && [ -f "$SRCDIRRPATH".SMBuild ]; then
  source "$SRCDIRRPATH".SMBuild
else
  echo "Please provide a build file as an argument"
  exit 1
fi

#type -t prepbdir

# Then source the conf file holding all values
. ${BUILDVARS:-/etc/bldpkg.conf} 
# This file is executed by bldpkg.conf and assists in preparing a complete build environment.

# Execute everything inside this condition so that stuff isn't executed and put into the build environment 
# unnecessarily when the section build file runs. This happens mostly during autobuilds.
# Get APP and VERSION from the build file
if [ -n "$APP" ] && [ -n "$VERSION" ]; then
  
  # Display the package and its version we are building
  echo "[INFO] Building package $APP version $VERSION ..."
  sleep 0.5
   
  # Create the $SM_PARENTTEMP directory. This directory is used for everything related to the build process outside 
  #the source directory $SRCDIR
  mkdir -p $SM_PARENTTMP

  # If $SM_HTMLOUTPUT is set to 1, echo $APP, $VERSION and $BUILD as file names inside the parent build directory. 
  # This will output into an HTML file so that the basic status of the build process (whether started, stopped, 
  # interrupted or failed) can be viewed in the web browser. 
  if [ -n "$SM_HTMLOUTPUT" ] && [ "$SM_HTMLOUTPUT" = "1" ] ; then
    echo $APP > $SM_PARENTTMP/$APP.APP
    echo $VERSION > $SM_PARENTTMP/$APP.VERSION
    echo $BUILD > $SM_PARENTTMP/$APP.BUILD
  fi

  # Store the source directory the build file was initiated from inside $SRCDIR
  #SRCDIR="$PWD"

  # Function to match specifically match arrays inside a value. This function will be used later on to perform package 
  # and directory matches using certain conditions. Note: "${ARRAY[@]}" =~ "${VARIABLE}" isn't fool-proof.
  inarray() {
    local n=$1 h
    shift
    for h ;
      do
        [[ $n = "$h" ]] && return
      done
    return 1
  }

  for f in /etc/bldpkg.d/* ; do
    source $f
  done

  # Time when the build commenced. Note: elapsed time is logged by the runtime function way below. This output goes 
  # into package build summary.
  SM_COMMENCEDATE="$(date '+%a, %d %b %Y, %T')"
  
  if [ -n "$SM_HTMLOUTPUT" ] && [ "$SM_HTMLOUTPUT" = "1" ] ; then
    if [ -n "$SM_AUTOBUILD" ] ; then
      cat << EOF >> $SM_PARENTTMP/BUILDMONITOR
<b>$SM_COMMENCEDATE | Building package # $CURRENTPKGNUMBER / $TOTALPKGNUMBER: <i><a href="/smlinux/pkgresults?pkg=$APP&amp;smver=1.0&amp;arch=all&amp;resultnum=25">$APP $VERSION</a></i></b>
EOF
    else 
      cat << EOF >> $SM_PARENTTMP/BUILDMONITOR
<b>$SM_COMMENCEDATE | Building package <i><a href="/smlinux/pkgresults?pkg=$APP&amp;smver=1.0&amp;arch=all&amp;resultnum=25">$APP $VERSION</a></i></b>
EOF
    fi

    touch $SM_PARENTTMP/BUILDING
  fi
  
  # Validate compressor and set extension
  validatecompressors

  # Validate tmpfs
  validatetmpfs
  
  # Validate system swap if SM_SWAPCHECK is defined and set to 1
  validateswap

  # Set the temporary directory for building the package. Also define package staging directory. This is where package
  # files that get "installed" go into, for example 'make install DESTDIR=$PKG' or 'DESTDIR="$PKG" ninja install'.

  # If SM_USETMPFS is set to 1, SM_TMPFSDIR is defined and SM_TMPFSCHECKFAILED  variable is unset, determine if the
  # $APP is in the exception list and whether to build inside or outside the TMPFS directory.
  if [ "$SM_USETMPFS" = "1" ] && [ -n "$SM_TMPFSDIR" ] && \
     [ -z "$SM_TMPFSCHECKFAILED" ] ; then
     
    # If $APP is in the TMPFS exception list inside /etc/bldpkg.conf, compile it *OUTSIDE* the TMPFS directory, i.e
    # the non-TMPFS directory, else compile it *INSIDE* the TMPFS directory. This if/else is solely for deciding 
    # whether $APP is in the exception list or not. 
    if inarray "${APP}" "${SM_TMPFSEXCEPTIONLIST[@]}" ; then

      # We DO NOT compile inside tmpfsdir
      SM_TMPFSENABLEDFORTHISPACKAGE=0
  
      # In the absence of tmpfs, we use the normal directory 
      SM_TMP="$SM_NONTMPFSDIR/$APP.src"
      PKG=${PKG:-$SM_NONTMPFSDIR/package-$APP}
    else
      # We compile inside tmpfsdir. Set the TMPFSENABLEDFORTHISPACKAGE variable here to inform build summary function at the bottom
      SM_TMPFSENABLEDFORTHISPACKAGE=1

      # Disable ccache
      SM_CCACHE=0

      # Override SM_PRESERVEBUILDDIR and SM_PRESERVEPACKAGEDIR to remove both build and package directories
      SM_PRESERVEBUILDDIR=0
      SM_PRESERVEPACKAGEDIR=0

      # Get the directory from the SM_TMPFSDIR variable for extracting the source
      SM_TMP="$SM_TMPFSDIR/$APP.src"
      PKG=${PKG:-$SM_TMPFSDIR/package-$APP}
    fi
  else
    # If SM_USETMPFS is disabled, we compile in the non-TMPFS directory
    SM_TMP="$SM_NONTMPFSDIR/$APP.src"
    PKG=${PKG:-$SM_NONTMPFSDIR/package-$APP}
  fi


  # Validate and export $SM_CPUTHREADS as MAKEFLAGS variable 
  if [ -n "$SM_CPUTHREADS" ]; then
    # export the user-defined number
    MAKEFLAGS="$SM_CPUTHREADS"
    export MAKEFLAGS
  else
    # Or fetch the number from nproc
    MAKEFLAGS="$(nproc --all)"
    export MAKEFLAGS
  fi
  
  # Invoke validatecompilers function
  validatecompilers

  # Apply CPU-specific compiler variables defined inside bldpkg.conf
  # https://github.com/sakaki-/gentoo-on-rpi-64bit/blob/master/reference/compile_run_benchmarks.sh
  # https://www.raspberrypi.org/forums/viewtopic.php?t=11629
  # noarch is set inside initfs, pkgtools, GTK themes and some other stuff.

  # If $ARCH has not been exported by autobuild or not set in the individual build files that have ARCH=noarch, we set our own
  # $HOSTTYPE is only set in the bash shell.
  [ -z "$ARCH" ] && ARCH="$HOSTTYPE"

  if [ "$ARCH" = "noarch" ]; then
    CFLAGS=""
    export CFLAGS

  elif [ "$ARCH" = "aarch64" ]; then  
    HOSTDIST="$SM_AARCH64HOSTDIST"
    BUILDDIST="$SM_AARCH64BUILDDIST"
    if [ -n "$SM_DEBUG" ]; then
      CFLAGS="$(echo $SM_GCCDEBUG $SM_AARCH64CFLAGS)"
    else
      CFLAGS="$SM_AARCH64CFLAGS"
    fi
    CXXFLAGS="$CFLAGS"
    export HOSTDIST BUILDDIST CFLAGS CXXFLAGS

  elif [ "$ARCH" = "x86_64" ]; then
    BUILDDIST="$SM_X8664BUILDDIST"
    if [ -n "$SM_DEBUG" ]; then
      CFLAGS="$(echo $SM_GCCDEBUG $SM_X8664CFLAGS)"
    else
      CFLAGS="$SM_X8664CFLAGS"
    fi
    CXXFLAGS="$CFLAGS"
    export BUILDDIST CFLAGS CXXFLAGS

  else
    echo "[ERROR] Sorry! '$ARCH' CPU architecture not supported by SMLinux! Aborting!"
    exit 1
  fi
  
  # Function to do a preliminary package dependency check
  checkdependencies

  # If $SM_NOAUTOCONFSITE is unset in an individual package build file, export CONFIG_SITE variable into the build 
  # environment for a package's configure script to pickup. Most autoconf-compatible configure scripts will 
  # automatically pick up this variable from the environment and speed up the initial configure process. 
  if [ -z "$SM_NOAUTOCONFSITE" ] ; then
    if [ -n "$SM_CONFIGSITE" ]; then
      CONFIG_SITE="$SM_CONFIGSITE"
      if [ -e "$CONFIG_SITE" ]; then
        export CONFIG_SITE
      fi
    fi
  fi

  # Check if SM_VERIFYCHECKSUMS is set and enabled to 1 and determine whether to continue building or abort if checksums fail
  if [ -n "$SM_VERIFYCHECKSUMS" ] && [ "$SM_VERIFYCHECKSUMS" = "1" ] ; then
    echo "[INFO] Verifying source checksums..."
     if [ -f "$SRCDIR/$APP.CHKSUM512" ] && \
        [ -f "$SRCDIR/$APP.CHKSUM512.sig" ] ; then
        # Verify the checksum file using our tool mkchecksums
       if [ -x /bin/mkchecksums ] ; then
         /bin/mkchecksums -vv
       else
         echo "/bin/mkchecksums script not found! Aborting!"
         exit 1
       fi
     else
       echo "[ERROR] Checksum files not found! Exiting!"
       exit 1
     fi
  fi
  
  # Condition to reuse the AUTOBUILDTEMP file if set from autobuild or make a new temporary file
  if [ -n "$SM_AUTOBUILDTEMP" ]; then
    SM_TEMPFILE="$SM_AUTOBUILDTEMP"
  else
    SM_TEMPFILE="$(mktemp $SM_PARENTTMP/SMBUILD.XXXXXX)"
  fi

  # https://unix.stackexchange.com/questions/462392/bash-the-function-is-executed-twice
  # https://stackoverflow.com/questions/9256644/identifying-received-signal-name-in-bash/9256709
  # We use two traps to identify the signals, EXIT and INT. EXIT will invoke  'prepbuildsummary' function on any exit
  # status >= 0. The script fail status  is determined by the above SM_PKGSTATUS or any premature compile failure.
  # The 'interrruptsummary' function is invoked when the user sends CTRL-C aka SIGINT. The SIGINT trap does not work
  # for auto builds, it has been added in the section build file too.
  
  trap "prepbuildsummary" EXIT
  trap "interruptsummary" INT

fi

#if [ -z $1 ] ; then
#  echo "Please provide a build file or an argument."
#  exit 1
#else
#  source $1
#fi

verifychecksums
#build 2>&1 | tee -a "$APP".SMBuild.log.txt
build

