#!/bin/bash
# Part of SMLinux distribution
# Package build file generator

# Copyright (c) 2022-2023 PktSurf <smlinux@pktsurf.in>

# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.

# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# Abort on any error
set -e

mksmversion="0.100"

# Date format
filedate="$(date +%Y%m%d%H%M%S)"

# Store PWD as currentdir
currentdir="$PWD"

# Function to generate usage options
mkusage() {
   cat << EOF

mksm is a tool to generate SMLinux-compatible package build files. It currently
supports generation of build files for sources that support compilation using:
-> Make
-> Autoconf
-> Cmake
-> Meson

Usage: mksm -a <app_name> -v <app_version> -b <build_system>

Options:
    -a : Application name. This option is REQUIRED.

    -b : Build system used by the package. This option is REQUIRED.

    -h : Show this usage and exit.

    -v : Application version. This option is REQUIRED.


**You must be inside the directory containing source tarball when running mksm.**. 
For example if you want to build glib 2.60.0, 

$ mkdir glib && cd glib
$ wget <glib-source-tarball-URL>
$ ls 
... 
glib-2.60.0.tar.xz
...

$ mksm -a glib -v 2.60.0 -b meson

EOF
exit 0
}

# Generate sha512sums in the build file
gensha512sums() {
  echo "[INFO] Adding new sha512sums in $appname.SMBuild..."
  printf '\n' >> "$currentdir/$appname".SMBuild
  printf 'sha512sums="\n' >> "$currentdir/$appname".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 >> "$appname".SMBuild
     fi
  done
  printf '"' >> "$appname".SMBuild
}

while getopts ':a:b:v:h' option; do
  case "$option" in
    a) envappname="$OPTARG" ;;
    b) envbuildsys="$OPTARG" ;;
    h) mkusage ;;
    v) envversion="$OPTARG" ;;
    *) mkusage ;;
  esac
done

# If/else to check if first argument is set. If it isn't, invoke mkusage
# function and exit
if [[ $OPTIND = 1 ]] ; then
  mkusage
fi

# Show errors and exit if either of these is not set
if [[ -z $envappname ]] ; then
  echo "[ERROR] Application name not provided. Please provide one." 
  exit 1
fi

if [[ -z $envversion ]] ; then
  echo "[ERROR] Application version not provided. Please provide one."
  exit 1
fi

if [[ -z $envbuildsys ]] ; then
  echo "[ERROR] Build system not provided. Please provide one from make, cmake, autoconf or meson."
  exit 1
fi

# Generate a build file.

# Redefine envappname, envversion and envbuildsys as appname, version and buildsys respectively
appname="$envappname"
version="$envversion"

buildfile="$appname.SMBuild"

# Use case/esac to determine the value of envbuildsys supplied to us. If it isn't what's expected, 
# throw an error and exit.
case "$envbuildsys" in 
  "autoconf"|"make"|"cmake"|"meson"|"guess")
  buildsys="$envbuildsys" ;;
  *) echo "[ERROR] Unknown build system. Try 'autoconf', 'make', 'cmake', 'meson' or 'guess'" ; exit 1 ;;
esac

gen_autoconf() {
  cat << 'EOF' >> $buildfile
  ./configure \
    --prefix="" 

  make 
  make install DESTDIR=$pkg

  cp COPYING $pkgdocs/

  mkfinalpkg
}

EOF
}

# Function for creating "make" template
gen_make() {
  cat << 'EOF' >> $buildfile
  make
  make install DESTDIR=$pkg

  cp LICENSE $pkgdocs/

  mkfinalpkg
}

EOF
}

# Function for creating "cmake" template
gen_cmake() {
  cat << 'EOF' >> $buildfile
  mkdir smbuild && cd smbuild
  cmake .. \
    -DCMAKE_INSTALL_PREFIX="/" \
    -DCMAKE_C_FLAGS="$CFLAGS" \
    -DCMAKE_CXX_FLAGS="$CXXFLAGS" \
    -Wno-dev

  make
  make install DESTDIR=$pkg
  
  cp ../LICENSE $pkgdocs/

  mkfinalpkg
}

EOF
}
   
# Function for creating "meson" template"
gen_meson() {
  cat << 'EOF' >> $buildfile
  mkdir smbuild && cd smbuild
  meson .. \
    --prefix="/" 

  ninja
  DESTDIR="$pkg" ninja install

  cp ../LICENSE $pkgdocs/

  mkfinalpkg
}

EOF
}

gen_guess() {
  echo "Trying to guess build system..."
  mkdir -p tmp.dir && cd tmp.dir
  tar xf "$currentdir/$appname-$version".tar.?z
  if [[ -d $appname-$version ]] ; then
    cd $appname-$version
    if [[ -f configure ]] || [[ -f configure.ac ]] ; then
      echo "Looks like autoconf system..."
      gen_autoconf
    elif [[ -f Makefile ]] ; then
      echo "Looks like simple Makefile..."
      gen_make
    elif [[ -f CMakeLists.txt ]] ; then
      echo "Looks like a cmake system..."
      gen_cmake
    elif [[ -f meson.build ]] && [[ -f meson_options.txt ]] ; then
      echo "Looks like meson build system..."
      gen_meson
    fi
  else
    echo "Non-standard directory. Perhaps you might want to provide a definitive build system"
    echo "instead of guessing?"
    cd $currentdir
    rm -rf tmp.dir
  fi
}


echo "[INFO] Generating build file for application '"$appname"' version '"$version"' which uses build system '"$buildsys"'..."
echo ""
echo "[INFO] Current directory is $PWD"
echo ""

# Copy the sample build file based on the build system argument passed
if [[ -f $buildfile ]] ; then
  echo "[INFO] Found an existing $appname.SMBuild in the current directory." 
  echo "[INFO] Backing it up inside a directory 'old' as '"$buildfile.$filedate"' and creating a new one here." 
  mkdir -p old
  mv "$buildfile" old/"$buildfile.$filedate"
fi
   
# This one came in handy:
# https://unix.stackexchange.com/questions/505949/expanding-only-certain-variables-inside-a-heredoc
# Expand variables in this heredoc
cat << EOF > $buildfile
# Maintainer: PktSurf <smlinux@pktsurf.in>
# Generated by mksm SMLinux build file generator version $mksmversion
app=$appname
version=$version
build=1sml
homepage=""
download=""
desc=""
requires="musl"
EOF
   
# Single-quoted 'EOF' prevents variables from being expanded in this heredoc
cat << 'EOF' >> $buildfile
   
prepbuilddir() {
  mkandenterbuilddir
  rm -rf $app-$version

  tar xf $srcdir/$app-$version.tar.?z*
  cd $app-$version
  fixbuilddirpermissions
}

build() {
EOF

case "$buildsys" in 
  autoconf) gen_autoconf ;;
  make) gen_make ;;
  cmake) gen_cmake ;;
  meson) gen_meson ;;
  guess) gen_guess ;;
esac

chmod +x $buildfile
echo "...done"
echo ""

# Generate SHA512 checksums and exit
gensha512sums

echo
echo "'$buildfile' has been generated successfully."
echo "It is *STRONGLY RECOMMENDED* that you view '$buildfile'"
exit 0
