# A collection of commands to make it easier to build projects.

# Default `build` alias to select a `build-dir` then invoke a build, using an
# alias means the configured build command's completion works out of the box.
alias build="build-dir --build"

# Detect installed debugger and set the `debug` alias to debug a program with
# command line arguments.
if [ `uname` = Linux ]; then
  if which cgdb &> /dev/null; then
    alias debug='cgdb --args'
  elif which gdb &> /dev/null; then
    alias debug='gdb --args'
  fi
elif [ `uname` = Darwin ]; then
  which lldb &> /dev/null && \
    alias debug='lldb --'
fi

# Store the path to `build-dir.py`, using `${0:a:h}` does not work in a
# function because it will result in `pwd` not this scripts directory.
_build_dir_py=${0:a:h}/build-dir.py

# Interactively choose a `~build` directory for `build` to build.
# TODO: Support arguments:
# * [ ] [-h,--help] - show this help message and exit
# * [x] [--build] - execute the build commend
# * [ ] <dir> - start in another directory, not `pwd`
build-dir() {
  # Get a unique filename to store the chosen build directory in.
  [ `uname` = Darwin ] && local file=`mktemp` || local file=`tempfile`
  # Prompt user to choose a build directory.
  python $_build_dir_py $file;
  local error=$?
  # If the file exists, read the build directory from it, then delete it.
  [ -f $file ] && build_dir=$PWD/`cat $file`; rm $file
  # If choosing a build directory failed, return that error.
  [[ "$error" = "0" ]] || return $error
  # If `build.ninja` exists in alias `ninja`, return.
  [ -f $build_dir/build.ninja ] && \
    local build="ninja -C $build_dir"
  # If `Makefile` exists in alias `make`, return.
  if [ -f $build_dir/Makefile ]; then
    [ `uname` = Darwin ] && \
      local cpu_count=`sysctl -n hw.ncpu` ||
      local cpu_count=`grep -c '^processor' /proc/cpuinfo`
    local build="make -j $cpu_count -C $build_dir"
  fi
  # If the build variable is not defined the command could not be determined.
  if [ -z $build ]; then
    # TODO: Prompt user to choose a build command?
    echo "could not determine build command"
    return 1
  fi
  # Redefine the `build` alias and update the `~build` hash directory.
  alias build="$build"
  hash -d build=$build_dir
  # If `--build` is specified then evaluate the command.
  [[ "$1" = "--build" ]] && eval $build || true
}

# Build then run a target residing in `$build_dir/bin`.
build-run() {
  local target=$1; shift 1
  build $target && $build_dir/bin/$target $*
}

# Build then debug a target residing in `$build_dir/bin`.
build-debug() {
  local target=$1; shift 1
  build $target && debug $build_dir/bin/$target $*
}