#! /bin/sh
#       Script: hmake
#  Author/Date: James Peachey, HEASARC/GSFC/NASA, Hughes STX / August, 1997
#  Description: run standard UNIX make, but with variables set on the
#               command line, to force configuration-specific overrides.
#               Which variables are set is controlled by a customizable
#               Bourne shell script, called a resource script.
# $Id: hmake,v 1.19 2003/09/26 15:15:10 peachey Exp $
#

# get path to this hmake and set default variables
scripthome=`echo $0 | sed "s:/*[^/]*$::"`
if [ "x$scripthome" = x ]; then
    scripthome=.
fi
scripthome=`cd $scripthome; pwd`
PATH="$scripthome:$PATH"
export PATH
hmake_prompt='hmake:'
hmake_rcfile=hmakerc
this_dir=`pwd`

# check command line for hmake options; pass unrecognized options to final make
for var in "$@"; do
    # strip out spurious empty options
    var=`echo $var | sed -e 's:^[ 	]*::'`
    if [ "x$var" = "x-h" -o "x$var" = "x--help" ]; then
        help=true
    elif [ "x$var" = "x--noexec" ]; then
        noexec=true
    elif [ "x$var" != "x" ]; then
        cl_args="$cl_args \"$var\""
    fi
done

# handle user's request for help
if [ "x$help" = "xtrue" ]; then
    cat << EOHELP
NAME

    hmake - HEASARC make

SYNOPSIS

    hmake [ option ]
    hmake [ target-name ]... [ MACRO=text_or_variable ]...

DESCRIPTION

    General usage

    The utility hmake is a development tool which is configured and
    installed with HEASARC software. Its purpose is to provide a
    wrapper for standard UNIX make which will build software in the
    context of a particular HEASARC package structure, for any
    supported platform/compiler combination, without the need to
    modify local Makefiles. With hmake, a developer can go to a
    directory containing a particular set of source files, type
    hmake, and expect all the macros in the local Makefiles to be
    set to values appropriate to the architecture and compiler for
    which hmake is configured. Moreover, it is not necessary to
    build within the package\'s source tree structure, provided
    that the minimal necessary files (libraries, headers, etc.) are
    accessible by hmake.

    Hmake is a Bourne Shell script which simply "execs" make, with
    certain macros set explicitly on the command line. The macros
    which are set by default are configured when hmake is installed.
    Therefore, to obtain the proper default behavior, developers
    should use a version of hmake which was installed for their
    platform. This should happen automatically if the developer
    runs the setup script for the mother HEASARC package in question.
    For builds within a standard package source tree structure,
    the default behavior should be adequate for most purposes.
    However, the behavior of hmake is completely customizable,
    making it possible, for instance, to link to a particular
    set of libraries, install binaries in a non-standard location,
    or use a different compiler other than the one used to install
    the mother software package. See the section Customized Usage,
    below.

    Example 1

    Developer Ozob wishes to perform some work on a new Ftool in his
    home directory, and test build it against the libraries which
    are currently installed in his local development area, without
    disturbing this local area.

    > setenv LHEASOFT /home/ozob/ftools/Linux_2.2_i686
    > source $LHEASOFT/lhea-init.csh
    > source $LHEASOFT/BUILD_DIR/devinit.csh
    > cd /home/ozob/newftool
    > which hmake
    /home/ozob/ftools/Linux_2.2_i686/BUILD_DIR/hmake
    > hmake
    hmake: Using /usr/bin/make
    hmake: Using resource file /home/ozob/ftools/Linux_2.2_i686/BUILD_DIR/hmakerc

    make CC=gcc FC=f77 FTOOLS=/home/ozob/ftools/Linux_2.0_i686 FTOOLS_SRC=/home/ozob/ftools FTOOLS_BIN=/home/ozob/ftools/Linux_2.0_i686/bin FTOOLS_LIB=/home/ozob/ftools/Linux_2.0_i686/lib LIB_COMMON=-lcftools -lcfitsio -lftools -lxanlib -lfitsio -ltermcap -lpgplot LIB_SYSTEM=  -L/usr/lib/gcc-lib/i486-linux/2.7.2.1.f.1  -lf2c -lm -lgcc -lc -lgcc  -L/usr/X11R6/lib -lX11 FFLAGS=-g -O -fno-second-underscore -fno-f2c -fno-automatic CFLAGS=-g -O -DHAVE_DIRENT_H -DHAVE_STRING_H -trigraphs -Dg77Fortran  -DSTDC_HEADERS=1 -DHAVE_ALLOCA_H=1 -DHAVE_ALLOCA=1  -I/home/ozob/ftools/Linux_2.0_i686/include

    Options

    --noexec
        Echo the command that hmake would issue under current
        circumstances, but do not actually execute the command.
        Note that -n is not recognized as a synonym for this;
        instead, -n will be added to the make command line.

    Customized Usage

    The names of the macros set, and their values, are determined
    by a required companion resource file, which is configured to
    work properly for the platform being used when hmake is
    installed. It may of course be configured again later, in order
    to change compilers, for example. The base name for this resource
    file is $hmake_rcfile. When hmake is invoked, first the current
    directory is checked for the existence of a file with this name.
    If no such file is found, hmake looks in the directory in which
    it is installed. This default file is installed along with
    hmake, and is created by configure from the file $hmake_rcfile.in
    to match the platform on which it is installed. Developers who
    wish to customize hmake\'s behavior should, in general, start
    with, and edit, an $hmake_rcfile copied from such a file.

    The resource file must consist entirely of legal Bourne shell
    commands, because it is executed (sourced) within hmake\'s
    subshell prior to "execing" the UNIX make. Each variable which
    is explicitly exported in the $hmake_rcfile will cause the
    argument "variable=\$variable" to be added to the "execed"
    make command line. For example, if the $hmake_rcfile contained:

        # use env variable CC unless it is not defined
        # in which case, pick gcc
        if [ "x\$CC" = x ]; then
            CC=gcc
        fi

        # choose a Fortran compiler
        ARCH=`uname`
        if [ \$ARCH = "Linux" ]; then
            FC=g77 # only use g77 on Linux
        else
            FC=f77 # otherwise use f77
        fi
        export CC FC # for make's command line

    the make command "execed" by hmake would be:

        make "CC=\$CC" "FC=\$FC"

    with the actual values of CC and FC being determined when hmake
    is invoked by the logic in $hmake_rcfile. Note that the ARCH
    variable was not added to make\'s command line, because ARCH was
    not exported. This allows the user to use environment variables
    to override Makefile defaults as much or as little as he/she
    wishes, simply by adjusting his or her personal $hmake_rcfile.

    Other Features

    There are other conveniences to hmake. One is that a developer
    can treat hmake as a regular make, specifying targets and/or
    macro definitions on the command line, and they will be passed
    to the "execed" make. These will override any settings in the
    resource file. For example, if the resource file contains:

        CC=gcc
        export CC

    and the user invokes hmake as follows:

        hmake -f makefile.special "CC=cc"

    hmake will exec the command:

        make -f makefile.special CC=cc

EOHELP
    exit 0
fi

#-------------------------------------------------------------------------------
# Start main script
#-------------------------------------------------------------------------------

HEATOP=`echo $HEADAS | sed 's:/[^/]*$::'`
HOST=`echo $HEADAS | sed "s:$HEATOP/::"`
# determine whether this is a LHEASOFT or HEADAS makefile
# HEADAS makefiles are required to have the HD_COMPONENT_NAME macro
# LHEASOFT makefiles better not have the HD_COMPONENT_NAME macro
if [ -f $this_dir/makefile ]; then
  headaspkg=`sed -ne 's:^HD_COMPONENT_NAME[ 	]*=[ 	]*::p' $this_dir/makefile | \
    sed -e 's:[	 ]*$::'`
elif [ -f $this_dir/Makefile ]; then
  headaspkg=`sed -ne 's:^HD_COMPONENT_NAME[ 	]*=[ 	]*::p' $this_dir/Makefile | \
    sed -e 's:[	 ]*$::'`
else
  echo $hmake_prompt Cannot find a makefile or Makefile
  exit 1
fi

# assemble a path upon which to look for a resource file
# in any case, first place to look is ., then ./BUILD_DIR, and where this script lives
hmakerc_path="$this_dir:$this_dir/BUILD_DIR:$scripthome"

# if headaspkg is an empty string, there was no HD_COMPONENT_NAME -> not HEADAS
if [ "x$headaspkg" = x ]; then
  # non-HEADAS case, just add in addition the installed BUILD_DIR
  if [ "x$LHEASOFT" != x ]; then
    hmakerc_path="$hmakerc_path:$LHEASOFT/BUILD_DIR"
  fi
else
  # headaspkg defined, giving the name of this HEADAS package
  # recurse upwards, looking for BUILD_DIR until we reach the top of this
  # package
  # start one level up from current directory
  pkg_hmakerc_path=
  tmp=`cd $this_dir/..; pwd`

  # hmake assumes that while the current directory contains the string
  # $headaspkg, the current directory is at or below the "top" of the
  # package tree. If there is a BUILD_DIR at any level it thus adds it
  # to the path.
  while [ `echo $tmp | grep -c $headaspkg` -gt 0 ]; do
#    if [ -d $tmp/BUILD_DIR ]; then
      # found a candidate directory which might contain an rcfile
      pkg_hmakerc_path="$pkg_hmakerc_path:$tmp/BUILD_DIR"
#    fi

    # go "up" one more level
    tmp=`cd $tmp/..; pwd`
  done

  # add the sub-path which was just constructed to the search path
  hmakerc_path="$hmakerc_path$pkg_hmakerc_path"

  # finally add the "installed" headas BUILD_DIR if there is one
  if [ "x$HEADAS" != x ]; then
#    if [ -d $HEADAS/$headaspkg/BUILD_DIR ]; then
      hmakerc_path="$hmakerc_path:$HEATOP/$headaspkg/$HOST/BUILD_DIR"
#    fi
  fi
fi

# go through the path just assembled, and try to find an rcfile appropriate 
# for this Makefile
rcfile_dir=
for dir in `echo $hmakerc_path | awk -F: '{ for(i=1; i<=NF; ++i) print $i }'`;
do
  if [ -f $dir/$hmake_rcfile ]; then
    # see if this file is consistent with the current situation
    # the funny construction of the cases is to get past a limitation
    # in sh syntax
    rcfilepkg=`sed -ne 's:^[ 	]*HD_COMPONENT_NAME[ 	]*=[ 	]*::p' \
      $dir/$hmake_rcfile | sed -e 's:[	 ]*$::'`
    if [ "x$rcfilepkg" = "x$headaspkg" ]; then
      # exact match (HEADAS makefile/rcfile or LHEASOFT makefile/rcfile)
      rcfile_dir=$dir
      break
    elif [ "x$rcfilepkg" = x -o "x$headaspkg" = x ]; then
      # complete mismatch (a HEADAS makefile with LHEASOFT rcfile or vv)
      # skip it and go on
      :
    elif [ `echo $rcfilepkg | grep -c $headaspkg` -gt 0 ]; then
      # one contained the other -- close enough for HEADAS
      rcfile_dir=$dir
      break
    elif [ `echo $headaspkg | grep -c $rcfilepkg` -gt 0 ]; then
      # one contained the other -- close enough for HEADAS
      rcfile_dir=$dir
      break
    fi
  fi
done

# check whether an appropriate resource file was found
if [ "x$rcfile_dir" = x ]; then
  if [ "x$headaspkg" != x ]; then
    echo $hmake_prompt Unable to find a resource file appropriate for HEADAS component $headaspkg
  else
    echo $hmake_prompt Unable to find a LHEASOFT resource file
  fi
  echo "$hmake_prompt in the following path: $hmakerc_path"
  exit 1
fi

HMAKE_CONF_DIR=$rcfile_dir

export HMAKE_CONF_DIR

hmake_rcfile=$rcfile_dir/$hmake_rcfile

# execute the resource file
. $hmake_rcfile

# set MAKE variable, unless it's already set
# tell user which make is being used
if [ "x$MAKE" = x ]; then
  /bin/sh -c "gmake -n" > /dev/null 2>&1
  if [ $? -eq 0 ]; then
    MAKE=gmake
  else
    /bin/sh -c "make -n" > /dev/null 2>&1
    if [ $? -eq 0 ]; then
      MAKE=make
    else
      # no gmake or make -- throw an error
      echo $hmake_prompt Unable to find gmake or make -- check path
      exit 1
    fi
  fi
  export MAKE
  whichmake=`type $MAKE 2> /dev/null`
  echo $hmake_prompt which $MAKE?
  echo $hmake_prompt $whichmake
else
  echo $hmake_prompt Using environment variable MAKE == $MAKE
fi

# tell user which make resource file is being used
echo $hmake_prompt Using resource file $hmake_rcfile
echo $hmake_prompt

# form a list of variables which are exported in the resource file
macro_list=\
`sed -e 's:#.*::' $hmake_rcfile | sed -ne 's:export[ 	]*\(.*\)#*.*:\1:p'| sort | uniq`

# print verbose chatter of the variables set in the resource file
for macro in $macro_list; do
    eval echo "\$macro = \$$macro"
done

# echo and then perform the actual make
eval echo $MAKE $cl_args

# bail if user is running in "noexec" mode
if [ "x$noexec" = "xtrue" ]; then exit 0; fi

eval exec $MAKE $cl_args

# $Log: hmake,v $
# Revision 1.19  2003/09/26 15:15:10  peachey
# Fix check for gmake/make. Problem before was that 'type' writes to
# stdout sometimes even when it fails to find its objective.
#
# Revision 1.18  2002/09/20 18:36:05  peachey
# Hack to help hmake find its rcfile if only the installed hmakerc is available.
#
# Revision 1.17  2002/08/07 21:47:58  peachey
# Change THISPKG to HD_COMPONENT_NAME.
#
# Revision 1.16  2002/05/28 19:02:43  irby
# Update setup/usage example.
#
# Revision 1.15  2002/03/19 17:33:25  peachey
# Change to work in HEADAS or LHEASOFT contexts.
#
# Revision 1.14  1999/04/21 16:40:46  peachey
#  - use MAKE env variable to choose the make to run; simply set it
#    to "make" unless it's already set.
#  - changed slightly the format of how the results of a "type make"
#    are reported, in line with the preceeding change
#  - escaped some single quotes in the help message which were not
#    properly escaped
#
# Revision 1.13  1999/03/10  19:29:28  peachey
# Do not use -e any longer
#
# Revision 1.12  1998/11/13  22:33:25  peachey
# Use make -e instead of putting everything on the command line
# Use the command line supplied by the user as is, and print each
# macro definition on its own line.
#
# Revision 1.11  1998/08/28 04:36:08  peachey
# Alphas do not export PATH by default. If you find that hard to believe, you're
# not alone
#
# Revision 1.10  1998/08/27 22:15:58  peachey
# Compute hmake_path by cd; pwd rather than a clever sed. Changed name of
# hmake_path variable to scripthome to match other scripts
#
# Revision 1.9  1998/07/27 20:08:01  peachey
# Simplify identification of hmakerc file: do not try to \'dereference\' symlinks
#
# Revision 1.8  1998/07/16  13:39:44  peachey
# No longer look for a resource file in user's home directory
#
# Revision 1.7  1998/07/09 22:02:57  peachey
# Simplified means of setting variables. Now all variables which are
# explicitly exported in hmakerc will be used on the command line, period.
# This is more straightforward than the previous method (checking for
# variables assigned in hmakerc).
#
# Revision 1.6  1998/04/21 14:09:23  peachey
# Use 'type' instead of 'which' to find make. The former is universal to Bourne
# shell, while the latter is not (e.g. it doesn't work on Suns)
#
# Revision 1.5  1998/03/02  20:59:16  peachey
# Strip out spurious empty options which are added in by DEC /bin/sh for
# unknown reasons
#
# Revision 1.4  1998/02/12  20:00:34  peachey
# When listing the hmakerc file, list the actual file, rather than any
# symbolic link to that file. Also a bug fix associated with the last
# commit.
#
# Revision 1.3  1998/02/12 19:34:36  peachey
# Better implementation of --noexec option. Also, -n is now *not* treated
# as a synonym for --noexec; rather it is passed to the final execed make.
# This allows user to invoke make -n as well as hmake --noexec.
#
# Revision 1.2  1998/02/12 18:22:58  peachey
# Added support for a 'noexec' feature, which echoes hmake command info without actually execing the final make command
#
# Revision 1.1  1997/11/05 20:40:58  peachey
# New development tool to make easier building on different platforms
#
