
# IF YOU DON'T KNOW WHAT THIS WILL DO, RUN `gmake debug` AND LEARN!!!
# (If you still don't know what this will do, try `gmake -n` piped to $PAGER.)

.PHONY: all pponly install debug backup archive
.PHONY: clean distclean libclean binclean ppclean
# The useable goals:
#    all        - (default) compiles source, builds library, links executable
#    pponly     - preprocesses .F, .F90, and .F95 files
#    debug      - (USE THIS OFTEN) lists the behavior make will take when
#                 treating each and every file
#    install    - ${INSTALL}s the library, binary, and/or *.mod files to the
#                 directories specified by DIR_INST*
#                 NOTE: currbin and currlib are dependcies of install so
#                 `gmake install` will attempt to make the library and
#                 binary if they do not exist. This is in line with the
#                 standard GNU `make install` convention.
#    clean      - removes everything that can be generated by make
#    binclean   - removes the current executable
#    libclean   - removes the current executable and library
#    ppclean    - removes the current executable, library, and intermediates
#                 (source files from sources with pre-processor directives --
#                 for use when you want to change defines or include files)
#    distclean  - an alias for clean except when used by a top-level make
#    backup(*)  - (USE BEFORE `gmake clean`) copies ${SLUDGE} to backup.${DATE}
#    archive(*) - puts source and ./include into ${CURR}.tgz compressed archive
#    (*) these goals have BASIC capabilites and are not for normal use
# And, don't forget the chain rule:
#    `gmake clean all install CLI_VAR="some value"`

# To jump through the file, search for any of the following headers:
#    DEFAULT ENVIRONMENT VARIABLES
#    COMMON MAKEFILE.SRC VARIABLES
#    ADVANCED MAKEFILE.SRC VARIABLES
#    PORTING VARIABLES
#    ACES VARIABLES
#    NOT FOR THE WEAK-KNEED
#    THE TARGETS
#    FLAG FUN
#    PUTTING IT ALL TOGETHER
#    ACTUAL MAKEFILE
#    TODO
#    INDEX OF CONFIGURABLE VARIABLES

BANNER = ACES Makefile for GNU make - Version 4.7.3
TECHSUPPORT = yau@qtp.ufl.edu

# Here is a quick rundown of a standard compile environment for ${CURR}
# and its product files:
#
# ACES/
#      bin/
#          x${CURR}
#      include/
#              *.[h,mod]
#      module/
#             *.[F95,F90,f95,f90]
#      lib/
#          libacesmods.a,lib${CURR}.a
#      ${CURR}/
#              include/
#                      *.[h,mod]
#              module/
#                     *.[F95,F90,f95,f90]
#              lib/
#                  lib${CURR}mods.a,libprivatelib.a
#              privatelib/
#                         ...recursive directory structure...
#
# Why do we do this? Well, there are a number of ways to build huge and complex
# programs. One way is to have a different Makefile for every AME and ASL
# (ACES Member Executable and ACES Shared Library) but that would require
# everyone to learn how to write, maintain, and debug Makefiles not to mention
# the work required to add a few subroutines or reorganize a directory
# structure. Abiding by the directory hierarchy means one Makefile can be
# used for all the executables and libraries with minimal customization
# (accomplished via Makefile.src).
# The main problem with this implementation is active porting. Anyone wishing
# to port the code to another machine, architecture or operating system, will
# have to investigate which tools are available for building and archiving.
# If someone had the time and willingness, GNU's autoconf and automake could be
# used to make porting trivial.

#

# NOTES_ON_EDITING

# Edit this file ONLY if you are porting the code to a new computer or
# if you find a bug, which should be reported to ACES technical support;
# otherwise, PLEASE create and edit a Makefile.src file since it will
# override any variable found in the initialization section(s) anyway.

# This Makefile is designed specifically for GNU make and will certainly
# not work (yet) with standard make.

# Referencing variables:
# GNU make allows two forms of variable reference:
#    ${variable} and $(variable).
# Since make doesn't care one way or the other for most of these, we will use
# a convention such that the offset characters have meaning. The convention
# we choose to use is {} for expanded reference and () for stored reference.
# This means: if a variable is to be referenced and its contents are a simple
# string, then call it ${simple_variable}; however, if a variable's contents
# are updated at the moment it is referenced, then call it $(JIT_variable).
# Functions and commands are also offset with parentheses instead of braces.

# Selecting cases for variables:
# GNU make is case sensitive but humans tend not to be; however, if we force
# all variables to be upper or lower case, then we will have many variables
# whose names are derived from other variables like BUILDBIN and INT_BUILDBIN
# for the user-defineable variable and the name of its internal variable. So,
# to decrease the amount of programming needed, variables in all caps will
# be reserved for user variables like those found in Makefile.src and those
# specified on the command line and variables in lower case will be for the
# internal Makefile equivalents. The best example of this is BUILDBIN and
# buildbin. If the user sets BUILDBIN on the command line, then the internal
# logic based on it will be completely screwed up since its value will never
# be changed; therefore, we evaluate BUILDBIN once and set buildbin based on
# it.

# END NOTES_ON_EDITING

#

# NOTES_ON_STYLE

# For some reason, a few terminals don't respond well to scrolling
# two consecutive carriage returns; however, a few blank lines are
# more visually appealing than horizontal rules. Therefore, a hash
# should be used to break up such sequences.

# There are many configurable variables, some have default settings and
# some don't. Every now and then, to decrease obfuscation, the default
# value will be listed in brackets following the variable and a hash. E.G.,
# tmp := ${DIR_INSTINC} # [../lib]
# BUT, an anomoly was found in which adding the default value in a comment
# caused the error message "test: syntax error" every time a file was compiled.

# The more programming languages this file needs to support, the more
# complicated the flag parsing becomes. Already we support C++, C, and
# three FORTRANs. If anyone can think of a better way to divide and
# conquer all these possibilities, please, send the suggestions to
# ${TECHSUPPORT}.

# END NOTES_ON_STYLE

#

# Get the machine name or some other appropriate indentifier.
# Beware when `uname -n` returns the entire DNS name. Since a properly
# networked computer can't have periods in its name, we'll select only
# the first word.

uname := $(subst ., , $(shell uname -n))
uname := $(word  1, ${uname})
uname := $(strip ${uname})
MACHNAME := ${uname}

# Lookup node names and replace them with single machine names.
# The first substring is a sed pattern, and the second is a machine name.

pairs :=
pairs += haku[0-9a-f]*:haku simu[1-9]*:simu
pairs += jvn-[ln][0-9]*:jvn
pairs += hpc11-[0-9]*:hpc11 eagle-[0-9]*:eagle falcon-[0-9]*:falcon
pairs += k[1-9][0-9]*n[1-9][0-9]*e*:kraken
pairs += sapphire[0-9]*:sapphire
mapname := $(shell for pair in ${pairs}; \
             do pat=`echo $$pair | sed 's/:.*//'`; \
                name=`echo $$pair | sed 's/.*://'`; \
                echo ${MACHNAME} | sed -n "/^ *$$pat *$$/{s/.*/$$name/;p;}"; \
             done)
ifdef mapname
   MACHNAME := ${mapname}
endif
pairs :=
mapname :=

# Lookup architecture, operating system, and compiler. These three variables
# should only be used in the porting section or for GNUmakefile.src.
# The MACHSTATS variable contains strings of the pattern:
#     MACHNAME:ARCH:OPSYS:CMPLR

# QTP machines
MACHSTATS := \
   crisp:pentium2:freebsd:gnu \
   castor:athlonmp:freebsd:gnu pollux:athlonmp:freebsd:gnu \
   haku01:em64t:linux:gnu linx64:em64t:linux:intel linx32:pentium4:linux:intel \
   crunchb:native64:sunos:forte \
   solx:x86:sunos:pg \
   simu:pwr3:aix:xl ock:itanium2:linux:intel\
   xena:p2sc:aix:xl xena00:p2sc:aix:xl yena00:p2sc:aix:xl

# DoD resources
MACHSTATS += \
   jvn:em64t:linux:intel zornig:r12000:irix:sgi \
   hpc11:r12000:irix:sgi eagle:itanium2:linux:intel falcon:opteron:linux:pg \
   zeus:sv1ex:unicos:cray kraken:pwr4:aix:xl \
   smi:crayx1:unicos:cray mos:crayx1:unicos:cray

# DoE resources
MACHSTATS += \
   phoenix:crayx1:unicos:cray

# other
MACHSTATS += \
   medial:alpha:osf:digital \
   terminator:r10000:irix:sgi \
   miles:whoknows:hpux:hp

# determine H/W
MACHSTATS += ${MACHNAME}:undefined:undefined:undefined # this must be last
MACHSTATS := $(filter ${MACHNAME}:%, ${MACHSTATS})
list  := $(subst :, , ${MACHSTATS})
ARCH  := $(word  2, ${list})
OPSYS := $(word  3, ${list})
CMPLR := $(word  4, ${list})
list  :=
MACHSTATS :=

# bomb if the compiler is not defined
ifeq (${CMPLR},undefined)
$(error The compiler is undefined)
endif

#

# continue only if GNU make is recent enough

ifndef MAKE_VERSION
   MAKE_VERSION := 0.0
endif
tmp := $(subst ., , ${MAKE_VERSION})
tmp := $(word  2, ${tmp})
ifdef tmp
 # This will have to be changed once 4.x comes out.
   tmp := $(shell test ${tmp} -ge 79 && echo 1)
endif

ifndef tmp
$(error GNU make is too old)
endif

#

###################################
## DEFAULT ENVIRONMENT VARIABLES ##
###################################

SHELL = /bin/sh
TOUCH = touch
ECHO  = echo # used only in the Makefile commands, not in $(shell ...)'s
XARGS = xargs
CHMOD0755 = chmod 0755

RM       = rm -f
MV       = mv -f
CP       = cp -p
MKDIR    = mkdir
INSTALL := ${CP} # `gmake install` compares the installed object with the
                 # local one. Moving during install will always consider
                 # the installed object(s) out-of-date.

# Source file extensions
#    There are two main reasons for this feature:
#     1) C++ source can have multiple file extensions and
#     2) FAT16, FAT32, and NTFS are not case sensitive
EXT_cxx = cpp # C++ source (usually cc, C, or cpp)
EXT_c   = c   # C source
EXT_F95 = F95 # FORTRAN 95 source with preprocessor directives
EXT_f95 = f95 # FORTRAN 95 source
EXT_F90 = F90 # FORTRAN 90 source with preprocessor directives
EXT_f90 = f90 # FORTRAN 90 source
EXT_F   = F   # FORTRAN 77 source with preprocessor directives
EXT_f   = f   # FORTRAN 77 source
EXT_d   = d   # dependency makefile rules
EXT_mod = mod # FORTRAN 9X module definitions
EXT_o   = o   # linkable objects

# Source preprocessor
#    Yes, FORTRAN 9x defines (or comes with) a dedicated preprocessor called
#    fpp, but the parsing behavior is almost exactly the same as the one used
#    by cpp; therefore, we choose to use only one for all languages.
CPP            = cpp # [$(CC) -E]
CPPFLAGS       =
CPPFLAGS_EXTRA =
DEFINES        = # command line overrides all other defines
DEFINES_EXTRA  = # command line is added to other defines
CPPFLAG_DEPEND = -M # tells ${CPP} to list file dependencies as a make rule

# C++ compiler
CXX            = CC -c # [g++]
CXXFLAGS       =
CXXFLAGS_EXTRA =

# C compiler
#   Since C++ is a superset of C, we'll use the C++ compiler for both unless
#   the programmer chooses otherwise. Don't set these with ":=" because we
#   want them to reset along with any changes to the C++ variables.
CC           = ${CXX} # [cc]
CFLAGS       = ${CXXFLAGS}
CFLAGS_EXTRA = ${CXXFLAGS_EXTRA}
MPCC         =

# FORTRAN 9X compiler
F9XC           = f95 -c
F9XFLAGS       =
F9XFLAGS_EXTRA =
MODDIRS_PREFIX = -M # prepends to ${MODDIRS} when compiling (usually -M or -I)

# FORTRAN 77 compiler
#  o Since FORTRAN 9x is a superset of FORTRAN 77, we'll use the latest
#    compiler for all FORTRAN code unless the programmer chooses otherwise.
#    Don't set these with ":=" because we want them to reset along with any
#    changes to the FORTRAN 9x variables.
#  o In order to pass a flag to one generation and not the other, redefine
#    both sets in Makefile.src, e.g.,
#       F9XFLAGS = -free
#       FFLAGS   =
FC           = ${F9XC} # [f77]
FFLAGS       = ${F9XFLAGS}
FFLAGS_EXTRA = ${F9XFLAGS_EXTRA}
MPFC         =

# Archive-maintaining program (without ranlib)
AR         = ar
AR_REPLACE = r
AR_EXTRACT = x # only used if the main object comes from the library
LORDER     = lorder
TSORT      = tsort

# linker variables
#    ACES makes extensive use of FORTRAN much more than C, so we'll link with
#    the FORTRAN compiler instead. Again, don't use ":=".
LD              = $(filter-out -c, ${F9XC}) # [ld]
LDFLAGS         = ${F9XFLAGS}
LDFLAGS_EXTRA   = ${F9XFLAGS_EXTRA}
LDFLAGS_NUMLIBS = -llinpack -leispack -llb
MPLD            =
LDFLAGS_MPILIBS = # -lmpistubs overrides this variable if PARALLEL=0

# tape archiving program
TAR      = tar
TAR_GZIP = -z
TAR_CF   = -c -f
EXT_tgz  = tgz # compressed archive

STRIP = strip

# other common flags and defines
#    Most of these have two parts, a variable assignment and a switch to use it.
#    The switch can take any normally accepted boolean value like 1, TRUE,
#    false, ON, nEgAtIvE, NO, etc.

64BIT ?= 0
DEFINE_64BIT = -DF_64BIT
# We're in for a world of hurt when we start adding DIR_SRCLIB64 et al.

PARALLEL = 0
DEFINE_PARALLEL = -D_HAVE_MPI

C_SUFFIX = 0 # append underscore to global structures and C routines
DEFINE_C_SUFFIX = -DC_SUFFIX -DCB_SUFFIX

DEBUG = 0
DEFINE_DEBUG = -D_DEBUG -D_ASSERT
FLAG_DEBUG = -g
# also switches DIR_DEBUGLIB on or off

PROFILE = 0
FLAG_PROFILE = -pg
# also switches DIR_PROFLIB on or off

TEST = 0
# switches DIR_TEST* on or off

OPTIMIZE = 1
FLAG_OPTIMIZE = -O
# I'm not sure yet if we should have DIR_OPTLIBs or not.

#

###################################
## COMMON MAKEFILE.SRC VARIABLES ##
###################################

# WARNING ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING
#
# This Makefile was written with a specific file hierarchy in mind, and
# sufficient logic has been incorporated to allow the programmer freedom.
# Straying too far from this standard can confuse GNU make. Consequently,
# choosing to buck the system signifies independence and thus transfers
# the responsibility of debugging to the programmer.

# directory variables
#
# the linking order (with the appropriate flag added) is:
#    DEF [TEST] [DEBUG] [PROF] [SRC] [EXTRA]

# default directories
DIR_DEFLIB = . ./lib     ../lib
DIR_DEFINC =   ./include ../include

# directories with test code
DIR_TESTLIB =
DIR_TESTINC =

# directories with special libraries
DIR_DEBUGLIB =
DIR_PROFLIB  = # this should be removed

# permanent ACES directories for a given machine
DIR_SRCLIB =
DIR_SRCINC =

# permanent MPI directories for a given machine
DIR_MPIINC = # ../include/mpi overrides this variable if PARALLEL=0

# extra directories that may contain non-ACES related objects
#    Examples of such directories might be system directories or
#    special routines the programmer may have collected.
DIR_EXTRALIB =
DIR_EXTRAINC =

# `gmake install` will ${INSTALL} each item to the first writeable directory in
# the following path:
#    ${CURRBIN}:                         ${DIR_INSTBIN} ->                  .
#    ${CURRLIB}:       ${DIR_TESTLIB} -> ${DIR_INSTLIB} -> ./lib         -> .
#    *.mod:            ${DIR_TESTINC} -> ${DIR_INSTINC} -> ../../include -> .
#    lib${CURR}mods.a:                   ${DIR_INSTMOD} -> ..            -> .
#    ${CURRTGZ}:                         ${DIR_INSTTGZ}
DIR_INSTBIN = ../bin
DIR_INSTLIB = ../lib
DIR_INSTINC = ../include
DIR_INSTMOD = ../lib
DIR_INSTTGZ = ./

#

# Switches for archiving libraries and compiling binaries.
BUILDLIB = YES # this also affects building modules
BUILDBIN = YES # overridden by BUILDLIB=NO

# The name of the current directory should denote the AME. CURR is the
# most powerful variable here since setting it will determine a huge number
# of other variables (including ones for building modules).
CURR := $(notdir $(shell pwd))
# strip it in the case Makefile.src uses it
CURR := $(strip ${CURR})

# the prefix and suffix to use on ${CURR} for the name of the final library
LIB_PREFIX = lib
LIB_SUFFIX = .a
# CURRLIB = # ${LIB_PREFIX}${CURR}${LIB_SUFFIX}

# the prefix and suffix to use on ${CURR} for the name of the final executable
BIN_PREFIX = x
BIN_SUFFIX =
# CURRBIN = # ${BIN_PREFIX}${CURR}${BIN_SUFFIX}

# the compressed archive file containing the current sources
# CURRTGZ = # [${CURR}.${EXT_tgz}]

# the basename of the object file containing the current binary
# (e.g., v2ja for vmol2ja)
# MAIN_OBJ = # [main -> ${CURR}]

# a semicolon-delimited list of the libraries to link against
# in order (in the case ${CURR} doesn't show up in ACES_LINK_LISTS)
# LIST_LINKLIBS = # [${CURR}:${LIST_DEF_LIBS}]

#

#####################################
## ADVANCED MAKEFILE.SRC VARIABLES ##
#####################################

# FAST controls whether include dependencies are made. I.E., if fast is
# negative then only the object file time is compared to the source time;
# otherwise, make checks the times of the include files as well.
#    There is a missing feature here. I don't know how to print a list
# of module dependencies for a given FORTRAN 9x routine. That means if a
# .mod file is dated later than a dependent .f95 or .f90 file, make won't
# necessarily recompile.
FAST = 1

# extra stuff to remove in a clean command
JUNK = *~ core

# output redirection
MAKE_OUTPUT  = make.output
MAKE_ERROR   = make.error
#REDIRECT    := 1>> ${MAKE_OUTPUT} 2>> ${MAKE_ERROR}
REDIRECT    := 1> ${MAKE_OUTPUT} 2> ${MAKE_ERROR}

#

#######################
## PORTING VARIABLES ##
#######################

# Compilers are more portable than operating systems, so the top-level ifeq
# should be based on the compiler. Consequently, there could be all kinds of
# mess within a compiler branch dealing with OS and architecture. As such,
# we may want to reconsider our DEFINES for machine dependencies.

# Do compiler ports first (and operating system overrides later).

ifeq (${CMPLR},forte) ##########################################################
   DEFINES        = -D_SUNOS # This has to be changed in the code.
   C_SUFFIX       = 1
   CC             = cc -c
   FC             = f77 -c
   LD             = f95 # could be F9XC AS LONG AS "-lF77 -lmvec" are used
   CXXFLAGS       = -dalign -fnonstd
   F9XFLAGS       = -dalign -fnonstd #-ansi -dbl_align_all=yes
   LDFLAGS        = -xildoff #-Bstatic
 # `man fpversion` and `optisa $(isalist)` explain the optimizing flags.
 # We need the "-nodepend" flag since some of our loops are so obfuscated
 # that the compiler must do exactly what we say.
   FLAG_OPTIMIZE = -fast -nodepend
   #ifeq (${ARCH},ultra2)
   #   FLAG_OPTIMIZE += -xtarget=ultra2 -xcache=16/32/1:1024/64/1
   #endif
   FLAG_OPTIMIZE += -xtarget=${ARCH}
   LDFLAGS_NUMLIBS = -llinpack -leispack -xlic_lib=sunperf
   ifeq (${ARCH},native64)
      64BIT=1
   endif
   ifeq (${64BIT},1)
      CXXFLAGS += -xtarget=${ARCH} -xarch=native64
      F9XFLAGS += -xtarget=${ARCH} -xarch=native64 \
                  -xtypemap=real:64,double:64,integer:64
      LDFLAGS  += -xtarget=${ARCH} -xarch=native64 -lF77 -lmvec
      LDFLAGS_NUMLIBS = -llinpack -leispack -llb
   endif
endif

ifeq (${CMPLR},xl) #############################################################
   DEFINES = -D_AIX

   XL_IS_SCREWED_UP=1
   XLC := /usr/vac/bin/xlc
   depend_F95 = ${XLC} -P -M ${cppflags} -D__fortran -D__fortran95 -D__fortran9x
   depend_F90 = ${XLC} -P -M ${cppflags} -D__fortran -D__fortran90 -D__fortran9x
   depend_F   = ${XLC} -P -M ${cppflags} -D__fortran -D__fortran77
   depend_cxx = ${XLC} -P -M ${cppflags} -D__cplusplus
   depend_c   = ${XLC} -P -M ${cppflags} -D__ansi_c

   CXX            = xlC_r -c
   CC             = xlc_r -c
   F9XC           = xlf90_r -c -qsuffix=f=f90
   FC             = xlf_r -c
   LD             = xlf_r
   CFLAGS         = ${CXXFLAGS} -qcpluscmt
   MODDIRS_PREFIX = -I

   MPCC        = mpcc_r -c
   MPFC        = xlf_r -F:mpxlf_r -c
   MPLD        = xlf_r -F:mpxlf_r
   ifeq (${64BIT},1)
      DIR_MPIINC := /usr/lpp/ppe.poe/include/thread64
   else
      DIR_MPIINC := /usr/lpp/ppe.poe/include/thread
   endif
   DIR_MPIINC += /usr/lpp/ppe.poe/include

   FLAG_DEBUG    = -g -qflttrap=ov:zero:inv:en -qsigtrap=xl__trcedump \
                   -qinitauto=FF #-qcheck #-qextchk
   FLAG_OPTIMIZE = -O3 -qstrict -qmaxmem=-1 -Q #-qfloat=hssngl #-qhot # not xlc

 # Override the tune and arch values if we are cross compiling.
   CXXFLAGS = -qtune=${ARCH} -qarch=${ARCH}
   F9XFLAGS = -qtune=${ARCH} -qarch=${ARCH}

   # This causes problems with OpenMP programs.
   #ifeq (${uname},${MACHNAME})
   #   CXXFLAGS := ${CXXFLAGS} -qcache=auto
   #   F9XFLAGS := ${F9XFLAGS} -qcache=auto
   #endif

   LDFLAGS += -bmaxstack:0x10000000 # 256MB
   LDFLAGS_NUMLIBS := -llinpack -leispack

 # This is technically a defect. 64BIT is a switch, but we don't evaluate until
 # after including GNUmakefile.src. Therefore, you could build with
 # `gmake 64BIT=YES` and the following would not be included.
   ifeq (${64BIT},1)
      CXXFLAGS += -q64
      F9XFLAGS += -q64 -qintsize=8
      LDFLAGS  += -q64 -b64
      LDFLAGS  += -bmaxdata:0x100000000 # 4GB
      LDFLAGS_NUMLIBS += -llb
   else
      LDFLAGS  += -bmaxdata:0x80000000 # 2GB
      ifneq ($(filter ${ARCH},pwr2 p2sc),)
         LDFLAGS_NUMLIBS += -L/usr/local/lib -llapackp2 -L/lib -lesslp2
      else
      ifneq ($(filter ${ARCH},pwr3),)
         LDFLAGS_NUMLIBS += -L/usr/local/lib -llapackp3 -L/lib -lessl
      else
         LDFLAGS_NUMLIBS += -L/usr/local/lib -llapack   -L/lib -lessl
      endif
      endif
   endif
endif

ifeq (${CMPLR},pg) #############################################################
   DEFINES         = -D_PORTGRP
   C_SUFFIX        = 1
   CXX             = pgCC -c
   CC              = pgcc -c -B
   F9XC            = pgf90 -c
   MPCC            = mpicc -c
   MPFC            = mpif90 -c
   MPLD            = mpif90
   MODDIRS_PREFIX := "-module "
   CXXFLAGS        = -Mcache_align -Mllalign # -tp k8-64
   F9XFLAGS        = -Mcache_align -Mllalign # -tp k8-64
   FLAG_OPTIMIZE   = -fast
   #LDFLAGS_NUMLIBS = -L/usr/local/lib -llapack -lblas
   ifeq (${64BIT},1)
      DEFINES  += -D_64BIT_MPI
      F9XFLAGS += -i8
   endif
   ifneq (,$(findstring ${MACHNAME},falcon))
      DIR_MPIINC := /opt/hpmpi/include/64
   endif
endif

ifeq (${CMPLR},cray) ###########################################################
   DEFINES  = -D_UNICOS
   CC       = cc -c
   F9XC     = ftn -c
   LD       = ftn
   64BIT    = 1
 # If you compile your own BLAS, then undefine USE_SP_BLAS
   DEFINES += -DUSE_SP_BLAS
   MODDIRS_PREFIX = -p
   ifeq (${ARCH},crayx1)
         DIR_MPIINC   := /opt/ctl/mpt/mpt/include
         DEFINES      += -D_CRAY_NV1 -DC_SUFFIX -DCB_UPPER
         ifeq (${64BIT},1)
            DEFINES   += -D_64BIT_MPI
         endif
         CFLAGS        = -h ssp
         ifeq (${CURR},gamess)
            F9XFLAGS   = -O ssp -e0 -sdefault64 -dp
         else
            F9XFLAGS   = -O ssp -e0 -sdefault64 -dp -O overindex
         endif
         LDFLAGS       = -O ssp -O overindex -e0 -sdefault64 -dp
         FLAG_OPTIMIZE = -O2
   else
      ifeq (${ARCH},t3e)
         DEFINES += -D_CRAY_MPP
      else
         DEFINES += -D_CRAY_PVP -DC_UPPER -DCB_UPPER -DCACHELINE=8 # 8B on SV1
         F9XFLAGS = -O overindex -e0 -dp
         LDFLAGS  = -O overindex -e0 -dp
      endif
      DEFINES      += -D_PTRS_ARE_WORDS
      FLAG_OPTIMIZE = -O2
   endif
   LDFLAGS_NUMLIBS = -llinpack -leispack -ltools -lsci64
                   #                     ^^^^^^^ converts dp to sp for ???pack
endif

ifeq (${CMPLR},digital) ########################################################
 # It is possible that running the program generates a ton of
 # "Unaligned access" error messages. Until we audit the code to find where
 # the complaints are coming from, the warnings can be turned off from the
 # command shell with `uac p noprint`.
   64BIT         = 1
   C_SUFFIX      = 1
   DEFINES       = -D_OSF
   DEFINES      += -D_RECL_IS_WORDS_ -D_CHAR_IS_ACHAR
   CC            = cc -c
   FC            = f90 -c
   LD            = f90
   FFLAGS        = -integer_size 64 -align dcommons -warn noalignments \
                   -fpe1 -static
   LDFLAGS       = -integer_size 64 -align dcommons -warn noalignments
   FLAG_OPTIMIZE = -O3 -tune host
   LDFLAGS_NUMLIBS = -llinpack -leispack -L/usr/lib -ldxml
   ifneq ($(filter ${CURR},vea vee mrcc),)
      LDFLAGS_NUMLIBS = -llinpack -leispack -llb
   endif
   LDFLAGS_MPILIBS = -lfmpi -lmpi -lelan
endif

ifeq (${CMPLR},sgi) ############################################################
 # The IRIX command hinv (hardware inventory) may be able to suggest flags.
 # The most basic for our needs is `hinv -c processor`.
   DEFINES       = -D_IRIX #-D_RECL_IS_WORDS_ # new versions of IRIX are normal
   64BIT         = 1
   C_SUFFIX      = 1
   CC            = cc -c
   FC            = f77 -c
   LD            = f77
   CFLAGS        = -64 -mips4 -${ARCH} -TARG:processor=${ARCH}
   F9XFLAGS      = -64 -mips4 -${ARCH} -TARG:processor=${ARCH} -i8 -static
   #FLAG_OPTIMIZE = -Ofast=ip35 -OPT:IEEE_arith=3:round=3 -IPA
   FLAG_OPTIMIZE = -Ofast -OPT:IEEE_arith=3:round=3
endif

ifeq (${CMPLR},hp) #############################################################
   DEFINES       = -D_HPUX # -D_RECL_IS_WORDS_ # Someone needs to verify this.
   FC            = fort77 -c
   LD            = fort77
   FFLAGS        = +apollo -K
   FLAG_OPTIMIZE = +O2
endif

ifeq (${CMPLR},gnu) ############################################################
   DEFINES = -D_GNU -D_2GB_FILES # This is has to be changed to be OS dependent.
   C_SUFFIX = 1
   CXX = g++ -c
   CC  = gcc -c
   FC  = g77 -c
   LD  = g77
 # make sure the other compilers f9x, cc, and CC all get double alignment
   CFLAGS  = -malign-double
   FFLAGS  = -malign-double -Wall -fno-second-underscore -finit-local-zero
   LDFLAGS = -malign-double
   FLAG_OPTIMIZE = -O2 -funroll-loops
   #LDFLAGS_NUMLIBS := -lg2c -lm # use if LD=ld
 # http://gentoo-wiki.com/Safe_Cflags
   ifeq (${ARCH},pentium2)
      FLAG_OPTIMIZE += -fomit-frame-pointer -pipe -march=pentium2
   endif
   ifeq (${ARCH},pentium4)
      FLAG_OPTIMIZE += -fomit-frame-pointer -pipe -march=pentium4
   endif
   ifeq (${ARCH},athlonmp)
      FLAG_OPTIMIZE += -fomit-frame-pointer -pipe -march=athlon-mp
   endif
   ifeq (${ARCH},em64t)
      CFLAGS  =
      FFLAGS  = -fno-second-underscore -finit-local-zero
      LDFLAGS =
      DEFINES       += -D_USE_SBRK -DF_ADR=integer*8
      FLAG_OPTIMIZE += -fomit-frame-pointer -pipe -march=nocona \
                       -fforce-addr -mmmx -msse3 -mfpmath=sse
   endif
   ifeq (${MACHNAME},crisp)
      DEFINES       += -D_TRAPFPE
      FLAG_DEBUG    += -Wsurprising -fstack-check
      FLAG_OPTIMIZE := -O2 -funroll-loops -pipe -march=i686
   endif
endif

ifeq (${CMPLR},intel) ##########################################################
   DEFINES = -D_INTEL -D_RECL_IS_WORDS_
   ifeq (,$(findstring ${ARCH},itanium2))
      DEFINES += -D_IA32
   else
      DEFINES += -D_IA64
   endif
   ifeq (,$(findstring ${MACHNAME},jvn))
      DIR_MPIINC = /usr/include
      LDFLAGS_MPILIBS = -lmpi
   else
      DIR_MPIINC = $$MPIHOME/include
      MPCC = mpicc -c
      MPFC = mpif90 -c
      MPLD = mpif90
   endif
   C_SUFFIX = 1
   CC   = icc -c
   F9XC = ifort -c -Wall 
   LD   = ifort
 # make sure the other compilers f9x, cc, and CC all get double alignment
   CFLAGS   = -Zp8
   F9XFLAGS = -Zp8 -zero
   LDFLAGS  = -Zp8
   ifneq (,$(findstring ${ARCH},em64t itanium2))
      64BIT = 1
      F9XFLAGS += -i8
      LDFLAGS  += -i8
   endif
   FLAG_OPTIMIZE = -O2
   #LDFLAGS_NUMLIBS = #-Vaxlib # -Vaxlib is for iargc/getarg
endif

# Now add OS-dependent overrides.

ifeq (${OPSYS},sunos) ##########################################################
   CPP        = /usr/ccs/lib/cpp
   CPPFLAGS   = -P -C
   AR_REPLACE = rc
   ifeq (${ARCH},sparc)
    # Any member executable that relies on molcas needs to link against
    # the global array library which in turn links against the OS's
    # shared object libraries.
      MOLCAS_ROOT = /ufl/qtp/rjb/progs/arch/sun4/molcas/5.3
      ifneq (,$(filter ${CURR},vscf squint))
         LDFLAGS_NUMLIBS := -ldl ${LDFLAGS_NUMLIBS}
      endif
   endif
endif

ifeq (${OPSYS},aix) ############################################################
   CPP        = /usr/ccs/lib/cpp
   CPPFLAGS   = -P -C
   AR_REPLACE = -c -s -r
   AR_EXTRACT = -x
   LORDER     = ~yau/power2/bin/lorder # a modified shell script
 # This is technically a defect. 64BIT is a switch, but we don't evaluate until
 # after including GNUmakefile.src. Therefore, you could build with
 # `gmake 64BIT=YES` and the following would not be included.
   ifeq (${64BIT},1)
      AR_REPLACE  = -r -c -s -X64
      LORDER      = lorder -X64
      STRIP       = strip -X64
   endif
   REDIRECT := # There is a bug with the redirection under AIX.
endif

ifeq (${OPSYS},unicos) #########################################################
   CPP        = cpp
   CPPFLAGS   = -P -C
   AR_REPLACE = rc
   STRIP      = touch
endif

ifeq (${OPSYS},osf) ############################################################
   CPP = $(shell test -x /usr/ccs/lib/cpp && echo /usr/ccs/lib/cpp || echo cpp)
   CPPFLAGS   = -P -C
   AR_REPLACE = rc
endif

ifeq (${OPSYS},irix) ###########################################################
   CPP        = /usr/lib/cpp
   CPPFLAGS   = -P -C
   AR_REPLACE = rc
endif

ifeq (${OPSYS},hpux) ###########################################################
   AR_REPLACE = rc
endif

ifeq (${OPSYS},freebsd) ########################################################
   #CPP = /usr/local/bin/cpp -traditional
   CPP = cpp -traditional
   CPPFLAGS       = -P -C # omit hashed comments and pass C-style comments
   CPPFLAG_DEPEND = -MM # do not check system includes
   AR_REPLACE = rs
endif

ifeq (${OPSYS},linux) ##########################################################
   CPP = cpp -traditional
   CPPFLAGS       = -P -C
   CPPFLAG_DEPEND = -MM # do not check system includes
   AR_REPLACE = rs
endif

#

####################
## ACES VARIABLES ##
####################

# the names of all the ACES stand-alone libraries
# If ${CURR} is in this string, then BUILDBIN=NO.
ACES_LIBS = \
   mpistubs mpw p_mpw blas lapack lb eispack linpack \
   tools \
   acescore p_acescore acesutil \
   libr crust oed erd gamess p_gamess \
   symcor ecp \
   libr2 librt3 trp eomtrp\
   imm omm symtools diagtools \
   sbtools \
   mrcca3 mrcccore apg apg2 cse eomprocs mbdirect mbgrad mbtest mbdiag mbtools \
   molcas oeptools nlo

# the names of the parallel libraries and binaries
PACES_DIRS = \
   p_mpw p_gamess p_acescore p_aces2 p_dirmp2 p_vscf p_scfgrd

# default libraries to link against when compiling an unlisted AME
LIST_DEF_LIBS ?= libr:acesutil:acescore:tools

# lists of library dependencies for compiling AMEs
# (The first element in each sublist is ${CURR}.  The remaining elements are
# libraries the binary needs to be linked against in order.)
ACES_LINK_LISTS = \
   a2proc:joda:symcor:sbtools:libr2:${LIST_DEF_LIBS} \
   asv:joda \
   ccsdtq:vcc:trp:librt3:libr2:${LIST_DEF_LIBS} \
   cphf:crust:${LIST_DEF_LIBS} \
   dens:libr2:crust:${LIST_DEF_LIBS} \
   rspdens:libr2:crust:${LIST_DEF_LIBS} \
   findif:joda:symcor:ecp:${LIST_DEF_LIBS} \
   joda:symcor:ecp:a2proc:${LIST_DEF_LIBS} \
   lambda:eomtrp:trp:librt3:libr2:${LIST_DEF_LIBS} \
   nmr:libr2:${LIST_DEF_LIBS} \
   vcc:trp:librt3:libr2:crust:${LIST_DEF_LIBS} \
   lcct:trp:librt3:libr2:crust:${LIST_DEF_LIBS} \
   vcc5q:vcc:librt3:libr2:${LIST_DEF_LIBS} \
   vcc5t:librt3:libr2:${LIST_DEF_LIBS} \
   pdens:vcceh:vee:libr2:${LIST_DEF_LIBS} \
   vcceh:libr2:crust:${LIST_DEF_LIBS} \
   vdint:ecp:${LIST_DEF_LIBS} \
   idint:ecp:${LIST_DEF_LIBS} \
   vea:libr2:${LIST_DEF_LIBS} \
   vee:eomtrp:trp:librt3:libr2:crust:${LIST_DEF_LIBS} \
   vmol:ecp:${LIST_DEF_LIBS} \
   vmol2ja:ecp:${LIST_DEF_LIBS} \
   a2rate:${LIST_DEF_LIBS} \
   rccd::librt3:${LIST_DEF_LIBS} \
   drccd::librt3:${LIST_DEF_LIBS} \
   rpa:${LIST_DEF_LIBS}\
   nlorb:nlo:${LIST_DEF_LIBS}\
\
   p_aces2:symcor:libr:p_acescore:tools:p_mpw \
   p_dirmp2:libr:p_gamess:p_acescore:tools:p_mpw \
   p_scfgrd:libr:p_gamess:p_acescore:tools:p_mpw \
   p_vscf:vscf:libr:p_gamess:acesutil:p_acescore:tools:p_mpw:molcas:ma \
   dirmp2:libr:gamess:acescore:tools \
   scfgrd:libr:gamess:acescore:tools \
   vscf:libr:intgrt:sbtools:oeptools:gamess:acesutil:acescore:tools:molcas:ma \
   squint:libr2:libr:gamess:acesutil:acescore:tools:molcas:ma \
\
   vksdint:intgrt:libr:sbtools:acescore:tools \
   intgrt:libr:sbtools:acescore:tools \
   oepplot:oeptools:${LIST_DEF_LIBS} \
   intpack:oeptools:intgrt:sbtools:acescore:acesutil:${LIST_DEF_LIBS} \
   slater:oeptools:intgrt:sbtools:acescore:acesutil:${LIST_DEF_LIBS} \
   intpack2vmol:oeptools:${LIST_DEF_LIBS} \
\
   mrcc:mrcclibs:mrcca3:tools \
   vibron:mrcclibs:mrcca3:tools

# the names of the main objects for each of the "problem" binaries
# [A name may be omitted if the main object has the same name as ${CURR}]
ACES_MAIN_OBJS = \
   dens:vdens \
   dtran:dtran2 \
   fsip:fs \
   intprc:intproc \
   lambda:vlamcc \
   props:prop \
   squint:nsquint \
   symcor:main \
   tdhf_ks:tdhf \
   vcc5q:t4 \
   vcc5t:nonit3 \
   vea:eaeom \
   vmol:molecu \
   vmol2ja:v2ja \
   idint:vdint \
   itran:vtra \
   pdens:main \
   oepplot:a2plot \
   rccd:ringccd \
   drccd:dringccd \

# more-or-less permanent defines that are ACES related that must be used
DEFINES_ACES = -D_NAMN_THROUGH_CHRTMP

#

############################
## NOT FOR THE WEAK-KNEED ##
############################
##   MAKEFILE.SRC CAN'T   ##
##   SAVE YOU ANYMORE!!   ##
############################

# read in Makefile.src if it exists
makefile_exists := $(shell test -r GNUmakefile.src && echo YES)
ifeq (${makefile_exists},YES)
   include GNUmakefile.src
endif
makefile_exists := $(shell test -r Makefile.src    && echo YES)
ifeq (${makefile_exists},YES)
   include Makefile.src
endif

#

# binary possibilities (we'll use $(upcase) to capitalize the strings)
positive = 1 POSITIVE ON  YES TRUE
negative = 0 NEGATIVE OFF NO  FALSE

# Extra functions with arguments: file, files, dir, dirs

# These settings just prevent the following functions from
# complaining during initialization.
file  = .
files = .
dir   = .
dirs  = .
str   = .

# return the $(files) that exist, null otherwise
files_exist = $(foreach file, $(files), \
   $(shell test -f $(file) && echo $(file)) )

# return $(dir) if it exists, null otherwise
dir_exists = \
   $(shell test -d $(dir) && echo $(dir))

# returns a list of directories from $(dirs) which exist
dirs_exist = \
   $(foreach dir, $(dirs), $(dir_exists))

# return $(dir) if it exists and is writeable
dir_writeable = \
   $(shell test -d $(dir) && test -w $(dir) && echo $(dir))

# return $(dir)/$(file) if it exists, null otherwise
file_exists = \
   $(shell test -f $(dir)/$(file) && echo $(dir)/$(file))

# searches the directories $(dirs) for each one that contains $(file) and
# returns the full path.
find_files = \
   $(foreach dir, $(dirs), $(file_exists))

# searches for each file in $(files) in each of the directories $(dirs)
# and returns the full path to the first one found.  Any file not found in
# any of the directories is omitted.
find_first_file = \
   $(foreach file, $(files), $(word 1, $(find_files)))

# return $(str) uppercased/lowercased
lc = abcdefghijklmnopqrstuvwxyz
uc = ABCDEFGHIJKLMNOPQRSTUVWXYZ
upcase   = $(shell echo $(str) | sed -e "y/${lc}/${uc}/")
downcase = $(shell echo $(str) | sed -e "y/${uc}/${lc}/")

#

##############
## SWITCHES ##
##############

# Switch on parallelization if CURR is in PACES_DIRS.
ifneq ($(filter ${CURR},${PACES_DIRS}),)
   PARALLEL = 1
endif

# Undefine all negative switches. In the safest environment, we would check
# for both negative and not positive, but since "ifdef C_SUFFIX" is true for
# "C_SUFFIX = a_dead_cat" then we assume people know what they're talking
# about when they write "C_SUFFIX = NO".

str := ${64BIT}
tmp := $(filter $(upcase), ${negative})
ifdef tmp
   64bit =
else
   64bit = 1
endif

str := ${PARALLEL}
tmp := $(filter $(upcase), ${negative})
ifdef tmp
   parallel =
else
   parallel = 1
endif

str := ${C_SUFFIX}
tmp := $(filter $(upcase), ${negative})
ifdef tmp
   c_suffix =
else
   c_suffix = 1
endif

str := ${DEBUG}
tmp := $(filter $(upcase), ${negative})
ifdef tmp
   debug =
else
   debug = 1
endif

str := ${PROFILE}
tmp := $(filter $(upcase), ${negative})
ifdef tmp
   profile =
else
   profile = 1
endif

str := ${TEST}
tmp := $(filter $(upcase), ${negative})
ifdef tmp
   test =
else
   test = 1
endif

str := ${OPTIMIZE}
tmp := $(filter $(upcase), ${negative})
ifdef tmp
   optimize =
else
   optimize = 1
endif

str := ${FAST}
tmp := $(filter $(upcase), ${negative})
ifdef tmp
   fast =
else
   fast = 1
endif

#

#################
## THE TARGETS ##
#################

# From here on out, the user should have little to no ability to specify
# variables. Every now and then we'll use a conditional define (?=) in case
# the user really knows what they're doing. This is why we use lowercase
# variable names for the equivalent user-specified variable.

curr := $(strip ${CURR})

# the library
#    buildmod is a switch for installing the library and definitions to
#    directories other than DIR_INSTLIB; otherwise, make treats the source
#    exactly like a vanilla library.
buildmod=
str := ${BUILDLIB}
tmp := $(filter $(upcase), ${negative})
ifdef tmp
   buildlib=
   currlib=
   buildbin=0
else
   buildlib=1
   lib_prefix := $(strip ${LIB_PREFIX})
   lib_suffix := $(strip ${LIB_SUFFIX})
   ifeq (${curr},module)
      # get the name of the parent directory and call the library
      # lib${curr}mods.a or something specified by the user
      tmp      := $(notdir $(dir $(shell pwd)))
      tmp      := $(strip ${tmp})
      CURRLIB  ?= ${lib_prefix}${tmp}mods${lib_suffix}
      buildmod  = 1
      buildbin  = 0
   else
      # See if we're in a directory called "module" in the event CURR
      # is defined.
      tmp := $(notdir $(shell pwd))
      ifeq (${tmp},module)
         CURRLIB  ?= ${lib_prefix}${curr}mods${lib_suffix}
         buildmod  = 1
         buildbin  = 0
      else
         # If ${curr} is an ACES stand-alone library then there is no binary.
         tmp := $(filter ${curr}, ${ACES_LIBS})
         ACES_LIBS :=
         ifdef tmp
            buildbin = 0
         endif
         CURRLIB ?= ${lib_prefix}${curr}${lib_suffix}
      endif
   endif
   currlib := $(strip ${CURRLIB})
endif

# the binary
ifeq (${buildbin},0) # set in the previous section
   buildbin=
else
   str := ${BUILDBIN}
   tmp := $(filter $(upcase), ${negative})
   ifdef tmp
      buildbin=
      currbin=
   else
      buildbin=1
      bin_prefix := $(strip ${BIN_PREFIX})
      bin_suffix := $(strip ${BIN_SUFFIX})
      CURRBIN ?= ${bin_prefix}${curr}${bin_suffix}
      currbin := $(strip ${CURRBIN})
   endif
endif

# the archive
ext_tgz := $(strip ${EXT_tgz})
CURRTGZ ?= ${CURR}.${ext_tgz}
currtgz := $(strip ${CURRTGZ})

#

# the source and its objects

# prepare the extensions
ext_cxx := $(strip ${EXT_cxx})
ext_c   := $(strip ${EXT_c})
ext_F95 := $(strip ${EXT_F95})
ext_f95 := $(strip ${EXT_f95})
ext_F90 := $(strip ${EXT_F90})
ext_f90 := $(strip ${EXT_f90})
ext_F   := $(strip ${EXT_F})
ext_f   := $(strip ${EXT_f})
ext_d   := $(strip ${EXT_d})
ext_mod := $(strip ${EXT_mod})
ext_o   := $(strip ${EXT_o})

tmp     := $(filter-out mod-%, $(wildcard *.${ext_F95}))
F95_F95 := $(wildcard mod-*.${ext_F95} ${tmp})  # all F95 files
F95_f95 := $(F95_F95:.${ext_F95}=.${ext_f95})   # processed source code
F95_o   := $(F95_F95:.${ext_F95}=.${ext_o})     # compiled objects
F95_mod := $(filter mod-%, ${F95_F95})          # module source files
F95_mod := $(patsubst mod-%, %, ${F95_mod})
F95_mod := $(F95_mod:.${ext_F95}=.${ext_mod})   # module description files

tmp     := $(filter-out mod-%, $(wildcard *.${ext_f95}))
f95_f95 := $(wildcard mod-*.${ext_f95} ${tmp})  # all f95 files
f95_f95 := $(filter-out ${F95_f95}, ${f95_f95}) # parentless f95 files
f95_o   := $(f95_f95:.${ext_f95}=.${ext_o})     # compiled objects
f95_mod := $(filter mod-%, ${f95_f95})          # module source files
f95_mod := $(patsubst mod-%, %, ${f95_mod})
f95_mod := $(f95_mod:.${ext_f95}=.${ext_mod})   # module description files

tmp     := $(filter-out mod-%, $(wildcard *.${ext_F90}))
F90_F90 := $(wildcard mod-*.${ext_F90} ${tmp})  # all F90 files
F90_f90 := $(F90_F90:.${ext_F90}=.${ext_f90})   # processed source code
F90_o   := $(F90_F90:.${ext_F90}=.${ext_o})     # compiled objects
F90_mod := $(filter mod-%, ${F90_F90})          # module source files
F90_mod := $(patsubst mod-%, %, ${F90_mod})
F90_mod := $(F90_mod:.${ext_F90}=.${ext_mod})   # module description files

tmp     := $(filter-out mod-%, $(wildcard *.${ext_f90}))
f90_f90 := $(wildcard mod-*.${ext_f90} ${tmp})  # all f90 files
f90_f90 := $(filter-out ${F90_f90}, ${f90_f90}) # parentless f90 files
f90_o   := $(f90_f90:.${ext_f90}=.${ext_o})     # compiled objects
f90_mod := $(filter mod-%, ${f90_f90})          # module source files
f90_mod := $(patsubst mod-%, %, ${f90_mod})
f90_mod := $(f90_mod:.${ext_f90}=.${ext_mod})   # module description files

F_F     := $(wildcard *.${ext_F})               # all F files
F_f     := $(F_F:.${ext_F}=.${ext_f})           # processed source code
F_o     := $(F_F:.${ext_F}=.${ext_o})           # compiled objects

f_f     := $(wildcard *.${ext_f})               # all f files
f_f     := $(filter-out ${F_f}, ${f_f})         # parentless f files
f_o     := $(f_f:.${ext_f}=.${ext_o})           # compiled objects

cxx_cxx := $(wildcard *.${ext_cxx})             # all C++ files
cxx_o   := $(cxx_cxx:.${ext_cxx}=.${ext_o})     # compiled objects

c_c     := $(wildcard *.${ext_c})               # all C files
c_o     := $(c_c:.${ext_c}=.${ext_o})           # compiled objects

tmp :=
ifdef fast
   F95_d :=
   F90_d :=
   F_d   :=
   cxx_d :=
   c_d   :=
else
 # dependency makefiles
   F95_d := $(F95_F95:.${ext_F95}=.${ext_d})
   F90_d := $(F90_F90:.${ext_F90}=.${ext_d})
   F_d   := $(F_F:.${ext_F}=.${ext_d})
   cxx_d := $(cxx_cxx:.${ext_cxx}=.${ext_d})
   c_d   := $(c_c:.${ext_c}=.${ext_d})
endif

# There is a potential hole here. If the programmer has a nested module and
# no ${CURR}/lib directory or ${CURR}/include directory, then all the .mod and
# .o files from the module directory will be installed in ${CURR}. If the
# programmer builds the code in ${CURR}, it will see those .mod and .o files,
# try to archive the .o files in ${CURRLIB}, and install them with the
# library. MAKE SPECIAL NOTE: If you choose to start using modules, then be
# sure to keep track of all the module files, because they will ultimately
# end up everywhere with carelessness.

OBJ ?= ${F95_o} ${F90_o} ${F_o} \
       ${f95_o} ${f90_o} ${f_o} \
       ${cxx_o} ${c_o}
obj := $(strip ${OBJ})
OBJ :=

#

##############
## FLAG FUN ##
##############

# switch-based flags

strip := ${STRIP} # altered by DEBUG and PROFILE

ifdef parallel
   define_parallel := ${DEFINE_PARALLEL}
   ifdef MPCC
      CC := ${MPCC}
   endif
   ifdef MPFC
      FC := ${MPFC}
   endif
   ifdef MPLD
      LD := ${MPLD}
   endif
else
   define_parallel =
   DIR_MPIINC = ../include/mpi ../../include/mpi \
                $(addsuffix /mpi, ${DIR_SRCINC})
   LDFLAGS_MPILIBS = -lmpw -lmpistubs
endif

ifdef 64bit
   define_64bit := ${DEFINE_64BIT}
else
   define_64bit =
endif

ifdef c_suffix
   define_c_suffix := ${DEFINE_C_SUFFIX}
else
   define_c_suffix =
endif

ifdef debug
   define_debug := ${DEFINE_DEBUG}
   flag_debug := ${FLAG_DEBUG}
   dir_debuglib := ${DIR_DEBUGLIB}
   strip := ${TOUCH}
else
   define_debug =
   flag_debug =
   dir_debuglib =
endif

ifdef profile
   flag_profile := ${FLAG_PROFILE}
   dir_proflib := ${DIR_PROFLIB}
   strip := ${TOUCH}
else
   flag_profile =
   dir_proflib =
endif

ifdef test
   dir_testlib := ${DIR_TESTLIB}
   dir_testinc := ${DIR_TESTINC}
else
   dir_testlib =
   dir_testinc =
endif

ifdef optimize
   flag_optimize := ${FLAG_OPTIMIZE}
else
   flag_optimize =
endif

# set preprocessor flags for ${CPP}, ${CXX}, and $(CC)

DEFINES := ${define_64bit} ${define_parallel} \
           ${define_c_suffix} ${define_debug} \
           ${DEFINES} ${DEFINES_EXTRA} ${DEFINES_ACES} \
           -D__CURR__=\"${CURR}\"
defines := $(strip ${DEFINES})
DEFINES :=

dirs    := ${DIR_DEFINC} ${dir_testinc} \
           ${DIR_SRCINC} ${DIR_MPIINC} ${DIR_EXTRAINC}
INCDIRS ?= $(dirs_exist)
FLAG_INCLUDES ?= $(addprefix -I, ${INCDIRS})
flag_includes := $(strip ${FLAG_INCLUDES})
FLAG_INCLUDES :=

FLAG_PREPROC ?= ${defines} ${flag_includes}
flag_preproc := $(strip ${FLAG_PREPROC})
FLAG_PREPROC :=

# set module include path for FORTRAN 9X

moddirs_prefix := $(strip ${MODDIRS_PREFIX})
ifeq (${moddirs_prefix},-I)
   # we've already picked up the directories
   FLAG_MODULES ?=
else
   FLAG_MODULES ?= $(addprefix ${moddirs_prefix}, ${INCDIRS})
endif
flag_modules := $(strip ${FLAG_MODULES})
FLAG_MODULES :=

# set compiler optimization flags

FLAG_OPT ?= ${flag_debug} ${flag_profile} ${flag_optimize}
flag_opt := $(strip ${FLAG_OPT})
FLAG_OPT :=

#

# Combine preprocessor, compiler, and linker flags. The line order is very
# important due to dependencies from the beginning of the Makefile.
# Here is the first time $() and ${} can be seen side-by-side in a sensical way.

# Here is another conundrum. If a user runs:
#    gmake CXXFLAGS=-DMY_DEF all
# Should that override all the other defines, includes, and optimization
# flags? According to the GNU make manual, yes. To accomodate both styles,
# we've added *FLAGS_EXTRA so you can add a flag on the command line and
# retain all other flags.

CPPFLAGS :=             ${flag_preproc} ${CPPFLAGS} ${CPPFLAGS_EXTRA}
LDFLAGS  := ${flag_opt}                 $(LDFLAGS)  $(LDFLAGS_EXTRA)
FFLAGS   := ${flag_opt}                 $(FFLAGS)   $(FFLAGS_EXTRA)
F9XFLAGS := ${flag_opt} ${flag_modules} ${F9XFLAGS} ${F9XFLAGS_EXTRA}
CFLAGS   := ${flag_opt} ${flag_preproc} $(CFLAGS)   $(CFLAGS_EXTRA)
CXXFLAGS := ${flag_opt} ${flag_preproc} ${CXXFLAGS} ${CXXFLAGS_EXTRA}

cppflags := $(strip ${CPPFLAGS})
cxxflags := $(strip ${CXXFLAGS})
cflags   := $(strip ${CFLAGS})
f9xflags := $(strip ${F9XFLAGS})
fflags   := $(strip ${FFLAGS})
ldflags  := $(strip ${LDFLAGS})

CPPFLAGS :=
LDFLAGS  :=
FFLAGS   :=
F9XFLAGS :=
CFLAGS   :=
CXXFLAGS :=

#

#############################
## PUTTING IT ALL TOGETHER ##
#############################

# define the methods for building each object
#    I have been tormented by these variables. On the one hand, I could define
#    them like
# ${CPP} ${CPPFLAGS} ${CPPFLAG_DEPEND} $< $@ ${REDIRECT}
#    but then I can't think of an easy way to reuse this line in the debug
#    target since the automatic variables $< and $@ become meaningless.
#    The other option, currently employed, is to define them like so
# ${CPP} ${CPPFLAGS} ${CPPFLAG_DEPEND}
#    This way, it is easy to echo the whole command when running `gmake debug`
#    but a gaping hole exists, viz., more complicated commands like $(LD)
#    have variables that must appear after the object like ${FLAG_LIBS}.
#    Anyone modifying this file must be aware of that and make sure to update
#    both occurances.

process_F95 ?= ${CPP}  ${cppflags} -D__fortran -D__fortran95 -D__fortran9x
process_F90 ?= ${CPP}  ${cppflags} -D__fortran -D__fortran90 -D__fortran9x
process_F   ?= ${CPP}  ${cppflags} -D__fortran -D__fortran77
compile_cxx ?= ${CXX}  ${cxxflags} # -D__cplusplus
compile_c   ?= $(CC)   ${cflags}   -D__ansi_c
compile_f9x ?= ${F9XC} ${f9xflags}
compile_f   ?= $(FC)   ${fflags}

process_F95 := $(strip ${process_F95})
process_F90 := $(strip ${process_F90})
process_F   := $(strip ${process_F})
compile_cxx := $(strip ${compile_cxx})
compile_c   := $(strip ${compile_c})
compile_f9x := $(strip ${compile_f9x})
compile_f   := $(strip ${compile_f})

depend_F95 ?= ${process_F95}                   ${CPPFLAG_DEPEND}
depend_F90 ?= ${process_F90}                   ${CPPFLAG_DEPEND}
depend_F   ?= ${process_F}                     ${CPPFLAG_DEPEND}
depend_cxx ?= ${CPP} ${cppflags} ${CPPFLAG_DEPEND} # -D__cplusplus
depend_c   ?= ${CPP} ${cppflags} -D__ansi_c    ${CPPFLAG_DEPEND}

depend_F95 := $(strip ${depend_F95})
depend_F90 := $(strip ${depend_F90})
depend_F   := $(strip ${depend_F})
depend_cxx := $(strip ${depend_cxx})
depend_c   := $(strip ${depend_c})

#

# build and install the library

ifdef buildlib

# This section has proven to be utterly unportable. If we need ordered objects
# in the libraries, then uncomment these lines:
#   # lorder looks for TMPDIR from the environment
#   lorder ?= $(strip ${LORDER})
#   TMPDIR ?= /tmp
#   dir    := ${TMPDIR}
#   tmpdir := $(dir_exists)
#   ifndef tmpdir
#      tmpdir := $(shell mkdir ${TMPDIR})
#   endif
#   tsort ?= $(strip ${TSORT})
#   archive_objects ?= \
#      ${AR} ${AR_REPLACE} ${currlib} \
#      `${lorder} *.o 2> /dev/null | grep -v "annot open" | ${tsort}`

   archive_objects ?= ${AR} ${AR_REPLACE} ${currlib} *.o
   strip_library   ?= ${strip} ${currlib}

   # WARNING: If DIR_TESTLIB is defined and TEST is positive, then setting
   # DIR_INSTLIB on the command line will override the default behavior.
   # The crazy logic here is used to preserve the dir_writeable check.
   DIR_INSTLIB := ${dir_testlib} ${DIR_INSTLIB} ./lib
   dirs        := ${DIR_INSTLIB}
   tmp         := $(foreach dir, ${dirs}, $(dir_writeable))
   dir_instlib := $(word 1, ${tmp})
   dir_instlib := $(strip ${dir_instlib})

   ifdef dir_instlib
      install_library ?= ${INSTALL} ${currlib} ${dir_instlib}
   else
      install_library ?= ${ECHO} ${currlib} is installed in ./
   endif

   archive_objects := $(strip ${archive_objects})
   strip_library   := $(strip ${strip_library})
   install_library := $(strip ${install_library})

endif

#

# install the module components
# NOTE: This "feature" has not been fully checked since no one seems to use
# FORTRAN 9x modules.

ifdef buildmod

   DIR_INSTMOD := ${DIR_INSTMOD} ..
   dirs        := ${DIR_INSTMOD}
   tmp         := $(foreach dir, ${dirs}, $(dir_writeable))
   dir_instmod := $(word 1, ${tmp})
   dir_instmod := $(strip ${dir_instmod})

   ifdef dir_instmod
      install_mod_library ?= ${INSTALL} ${currlib} ${dir_instmod}
   else
      install_mod_library ?= ${ECHO} ${currlib} is installed in ./
   endif

   DIR_INSTINC := ${dir_testinc} ${DIR_INSTINC} ../../include
   dirs        := ${DIR_INSTINC}
   tmp         := $(forearch dir, ${dirs}, $(dir_writeable))
   dir_instinc := $(word 1, ${tmp})
   dir_instinc := $(strip ${dir_instinc})

   ifdef dir_instinc
      install_mods ?= \
         ${INSTALL} ${F95_mod} ${f95_mod} ${F90_mod} ${f90_mod} ${dir_instinc}
   else
      install_mods ?= ${ECHO} The mod files are installed in ./
   endif

   install_mod_library := $(strip ${install_mod_library})
   install_mods        := $(strip ${install_mods})

endif

#

# build and install the binary

ifdef buildbin

   # define the main object
   list := $(filter ${curr}:%, ${ACES_MAIN_OBJS}) # vmol2ja:v2ja
   ACES_MAIN_OBJS :=
   list := $(strip ${list})
   ifndef list
      tmp := $(wildcard main.*)
      ifdef tmp
         list := ${curr}:main                     # vscf:main
      else
         list := ${curr}:${curr}                  # vscf:vscf
      endif
   endif
   list := $(subst :, , ${list})                  # vmol2ja v2ja
   tmp  := $(word 2, ${list})                     # v2ja
   MAIN_OBJ ?= $(addsuffix .o, ${tmp})            # v2ja.o
   main_obj := $(strip ${MAIN_OBJ})

   # build the directory search path for linking libraries
   dir_srclib := $(strip ${DIR_SRCLIB})
   ifndef dir_srclib
      dir_srclib := ${dir_instlib}
   endif
   LIBDIRS ?= ${DIR_DEFLIB} \
              ${dir_testlib} \
              ${dir_debuglib} ${dir_proflib} \
              ${dir_srclib} ${DIR_EXTRALIB}
   dirs    := $(strip ${LIBDIRS})
   libdirs := $(dirs_exist)
   libdirs := $(strip ${libdirs})
   LIBDIRS :=

   # AME dependencies (self-inclusive)
   ifndef LIST_LINKLIBS
      # tag each ${curr} in ${ACES_LINK_LISTS} for easy parsing, e.g.,
      #    joda:symcor:ecp:libr        -> xxxxxjoda:symcor:ecp:libr
      #    findif:joda:symcor:ecp:libr -> xxxxxfindif:joda:symcor:ecp:libr
      X    := xxxxx
      list := $(addprefix ${X}, ${ACES_LINK_LISTS})
      ACES_LINK_LISTS :=
      list := $(filter ${X}${curr}:%, ${list})
      list := $(patsubst ${X}%, %, ${list})
      list := $(strip ${list})
      ifdef list
         LIST_LINKLIBS := ${list}
      else
         LIST_LINKLIBS := ${curr}:${LIST_DEF_LIBS}
      endif
      LIST_LINKLIBS := ${LIST_LINKLIBS}:${curr}mods
   endif
   list_linklibs := $(subst :, , ${LIST_LINKLIBS})
   LIST_LINKLIBS :=
   LINKLIBS      ?= $(strip ${list_linklibs})

   # Now that we have a library search path and some potential libraries
   # to look for, verify each library actually exists.
   dir  = .
   file = .
   verify_exist = \
      $(shell if test -f $(dir)/$(file) ; then echo $(file) ; fi)

   ifndef libdirs
      dirs := .
   else
      dirs := ${libdirs}
   endif
   tmp   := $(addprefix ${lib_prefix}, ${LINKLIBS})
   files := $(addsuffix ${lib_suffix}, ${tmp})

   tmp := $(foreach file, $(files), \
            $(word 1, \
              $(foreach dir, $(dirs), $(verify_exist) \
               ) \
             ) \
           )
   ifneq (${currlib},$(word 1, ${tmp}))
      tmp := ${currlib} ${tmp} # the current library doesn't exist yet
   endif

   linklibs := $(patsubst lib%.a, %, ${tmp})
   LINKLIBS :=

   # make the library flags for $(LD)
   tmp       := $(addprefix -L, ${libdirs}) $(addprefix -l, ${linklibs})
   FLAG_LIBS ?= ${tmp} ${LDFLAGS_NUMLIBS} ${LDFLAGS_MPILIBS}
   flag_libs := $(strip ${FLAG_LIBS})
   FLAG_LIBS :=

   extract_main_obj ?= ${AR} ${AR_EXTRACT} ${currlib} ${main_obj}
   link_binary      ?= \
      $(LD) ${ldflags} -o ${currbin} ${main_obj} ${flag_libs}
   strip_binary     ?= ${strip} ${currbin}

   dir         := ${DIR_INSTBIN}
   dir_instbin := $(dir_writeable)
   dir_instbin := $(strip ${dir_instbin})

   ifdef dir_instbin
      install_binary ?= ${INSTALL} ${currbin} ${dir_instbin}
   else
      install_binary ?= ${ECHO} ${currbin} is installed in ./
   endif

   extract_main_obj := $(strip ${extract_main_obj})
   link_binary      := $(strip ${link_binary})
   strip_binary     := $(strip ${strip_binary})
   install_binary   := $(strip ${install_binary})

endif

#

# build/install the archive

ifneq ($(filter archive,${MAKECMDGOALS}),)
   dir         := ${DIR_INSTTGZ}
   dir_insttgz := $(dir_writeable)
   dir_insttgz := $(strip ${dir_insttgz})
   ifndef dir_insttgz
      dir_insttgz := .
   endif
   archive_source := ${TAR} ${TAR_GZIP} ${TAR_CF} \
                     ${dir_insttgz}/${currtgz} \
                     ${F95_F95} ${f95_f95} \
                     ${F90_F90} ${f90_f90} \
                     ${F_F}     ${f_f}     \
                     ${cxx_cxx}            \
                     ${c_c}
   dir := ./include
   tmp := $(dir_exists)
   archive_source := ${archive_source} ${tmp}
   archive_source := $(strip ${archive_source})
else
   archive_source :=
endif

#

#####################
## ACTUAL MAKEFILE ##
#####################

export

.SUFFIXES:
.SUFFIXES: .${ext_cxx} .${ext_c}   \
           .${ext_F95} .${ext_f95} \
           .${ext_F90} .${ext_f90} \
           .${ext_F}   .${ext_f}   \
           .${ext_d}   .${ext_o}  .a

#

all: tabula_rasa ${obj} ${currlib} ${currbin}

pponly: tabula_rasa ${F95_f95} ${F90_f90} ${F_f}

.PHONY: FORCE
FORCE: ;

.PHONY: tabula_rasa
tabula_rasa: FORCE
	@${RM} ${MAKE_OUTPUT}
	@${RM} ${MAKE_ERROR}

########################
# build the object files

${f95_o} : %.${ext_o} : %.${ext_f95}
	@${ECHO} ${CURR}\($<\): compiling at `date +%H:%M:%S`
	@${compile_f9x} $< ${REDIRECT}

${f90_o} : %.${ext_o} : %.${ext_f90}
	@${ECHO} ${CURR}\($<\): compiling at `date +%H:%M:%S`
	@${compile_f9x} $< ${REDIRECT}

${f_o} : %.${ext_o} : %.${ext_f}
	@${ECHO} ${CURR}\($<\): compiling at `date +%H:%M:%S`
	@${compile_f} $< ${REDIRECT}

ifdef fast

   ${F95_o} : %.${ext_o} : %.${ext_f95}
	@${ECHO} ${CURR}\($<\): compiling at `date +%H:%M:%S`
	@${compile_f9x} $< ${REDIRECT}

   ${F90_o} : %.${ext_o} : %.${ext_f90}
	@${ECHO} ${CURR}\($<\): compiling at `date +%H:%M:%S`
	@${compile_f9x} $< ${REDIRECT}

   ${F_o} : %.${ext_o} : %.${ext_f}
	@${ECHO} ${CURR}\($<\): compiling at `date +%H:%M:%S`
	@${compile_f} $< ${REDIRECT}

   ${cxx_o} : %.${ext_o} : %.${ext_cxx}
	@${ECHO} ${CURR}\($<\): compiling at `date +%H:%M:%S`
	@${compile_cxx} $< ${REDIRECT}

   ${c_o} : %.${ext_o} : %.${ext_c}
	@${ECHO} ${CURR}\($<\): compiling at `date +%H:%M:%S`
	@${compile_c} $< ${REDIRECT}

   ${F95_f95} : %.${ext_f95} : %.${ext_F95}
	@${ECHO} ${CURR}\($<\): processing
	@${RM} $@; ${process_F95} $< $@ ${REDIRECT}

   ${F90_f90} : %.${ext_f90} : %.${ext_F90}
	@${ECHO} ${CURR}\($<\): processing
	@${RM} $@; ${process_F90} $< $@ ${REDIRECT}

# .INTERMEDIATE : $(addprefix F, ${})

   ${F_f} : %.${ext_f} : %.${ext_F}
	@${ECHO} ${CURR}\($<\): processing
#      ifeq (${OPSYS},aix)
#	@${process_F} $< ${REDIRECT}
#	@${MV} F$< $<
#      else
	@${RM} $@; ${process_F} $< $@ ${REDIRECT}
#      endif

else

   ${F95_o} ${F90_o} ${F_o} ${cxx_o} ${c_o} : %.${ext_o} : %.${ext_d}
	@${MAKE} --no-print-directory -s -f $< && ${RM} $<

   # If you use syntax highlighting, note the apostrophes in prefix and suffix.
   define depend_prefix
      ${SHELL} -ec '
   endef #'
   ifdef XL_IS_SCREWED_UP
      define depend_F95_suffix
         $< 1> /dev/null; sed "s/$*\.o/$*\.${ext_f95}/" $*.u >> $@; rm $*.[iu]'
      endef #'
      define depend_F90_suffix
         $< 1> /dev/null; sed "s/$*\.o/$*\.${ext_f90}/" $*.u >> $@; rm $*.[iu]'
      endef #'
      define depend_F_suffix
         $< 1> /dev/null; sed "s/$*\.o/$*\.${ext_f}/"   $*.u >> $@; rm $*.[iu]'
      endef #'
      define depend_cxx_suffix
         $< 1> /dev/null; mv $*.u $@; rm $*.i'
      endef #'
      define depend_c_suffix
         $< 1> /dev/null; mv $*.u $@; rm $*.i'
      endef #'
   else
      define depend_F95_suffix
         $< | sed "s/$*\.o/$*\.${ext_f95}/" >> $@'
      endef #'
      define depend_F90_suffix
         $< | sed "s/$*\.o/$*\.${ext_f90}/" >> $@'
      endef #'
         #$< | sed "s/$*\.o/$*\.${ext_f}/"   >> $@'
      define depend_F_suffix
         $< | sed "s/^.*\.o:/$*\.${ext_f}:/"   >> $@'
      endef #'
      define depend_cxx_suffix
         $< > $@'
      endef #'
      define depend_c_suffix
         $< > $@'
      endef #'
   endif

   ${F95_d} : %.${ext_d} : %.${ext_F95} FORCE
	@${ECHO} ${CURR}\($@\): creating
	+@${ECHO} '$*.o : $*.${ext_f95}' > $@
	+@${ECHO} '	@${ECHO} ${CURR}\($$<\): compiling at `date +%H:%M:%S`'\
	          >> $@
	+@${ECHO} '	@${compile_f95} $$< ${REDIRECT}' >> $@
	+@${ECHO} >> $@
	+@${depend_prefix} ${depend_F95} ${depend_F95_suffix}
	+@${ECHO} '	@${ECHO} ${CURR}\($<\): processing' >> $@
	+@${ECHO} '	@${process_F95} $< $*.${ext_f95} ${REDIRECT}' >> $@

   ${F90_d} : %.${ext_d} : %.${ext_F90} FORCE
	@${ECHO} ${CURR}\($@\): creating
	+@${ECHO} '$*.o : $*.${ext_f90}' > $@
	+@${ECHO} '	@${ECHO} ${CURR}\($$<\): compiling at `date +%H:%M:%S`'\
	          >> $@
	+@${ECHO} '	@${compile_f90} $$< ${REDIRECT}' >> $@
	+@${ECHO} >> $@
	+@${depend_prefix} ${depend_F90} ${depend_F90_suffix}
	+@${ECHO} '	@${ECHO} ${CURR}\($<\): processing' >> $@
	+@${ECHO} '	@${process_F90} $< $*.${ext_f90} ${REDIRECT}' >> $@

   ${F_d} : %.${ext_d} : %.${ext_F} FORCE
	@${ECHO} ${CURR}\($@\): creating
	+@${ECHO} '$*.o : $*.${ext_f}' > $@
	+@${ECHO} '	@${ECHO} ${CURR}\($$<\): compiling at `date +%H:%M:%S`'\
	          >> $@
	+@${ECHO} '	@${compile_f} $$< ${REDIRECT}' >> $@
	+@${ECHO} >> $@
	+@${depend_prefix} ${depend_F} ${depend_F_suffix}
	+@${ECHO} '	@${ECHO} ${CURR}\($<\): processing' >> $@
	+@${ECHO} '	@${process_F} $< $*.${ext_f} ${REDIRECT}' >> $@

   ${cxx_d} : %.${ext_d} : %.${ext_cxx} FORCE
	@${ECHO} ${CURR}\($@\): creating
	+@${depend_prefix} ${depend_cxx} ${depend_cxx_suffix}
	+@${ECHO} '	@${ECHO} ${CURR}\($<\): compiling at `date +%H:%M:%S`' \
	          >> $@
	+@${ECHO} '	@${compile_cxx} $< ${REDIRECT}' >> $@

   ${c_d} : %.${ext_d} : %.${ext_c} FORCE
	@${ECHO} ${CURR}\($@\): creating
	+@${depend_prefix} ${depend_c} ${depend_c_suffix}
	+@${ECHO} '	@${ECHO} ${CURR}\($<\): compiling at `date +%H:%M:%S`' \
	          >> $@
	+@${ECHO} '	@${compile_c} $< ${REDIRECT}' >> $@

endif

##########################################
# build and install the library and binary

.PHONY: install_lib install_bin
install: install_lib install_bin

ifdef buildlib

   parentless_objs := $(filter-out ${obj}, $(wildcard *.o))

   ${currlib}: ${obj}
	@${ECHO}
	@${ECHO} Object files are up-to-date.
      ifdef parentless_objs
	@${ECHO}
	@${ECHO} WARNING: The following source-less object files may \
	                  contaminate the library:
	@${ECHO} "   ${parentless_objs}"
      endif
#      ifndef tmpdir
#	@${ECHO} \
#	   'NOTE: $$TMPDIR does not exist and this may cause lorder to crash.'
#      endif
	@${ECHO}
	@${ECHO} Archiving objects
	@${archive_objects} ${REDIRECT}
#	@${ECHO} Stripping library if necessary
#	@${strip_library} ${REDIRECT}

   ifdef buildmod
      install_lib: FORCE
	@${ECHO}
	@${ECHO} Installing the mod files in:
	@${ECHO} "   ${dir_instinc}"
	@${install_mods} ${REDIRECT}
	@${ECHO} Installing the module object library as:
	@${ECHO} "   ${dir_instmod}/${currlib}"
	@${install_mod_library} ${REDIRECT}

   else
      ifdef dir_instlib
         install_lib: ${dir_instlib}/${currlib} FORCE
	@${ECHO}
	@${ECHO} The installed library is up-to-date.

         ${dir_instlib}/${currlib}: ${currlib}
	@${ECHO}
	@${ECHO} Installing the library as:
	@${ECHO} "   ${dir_instlib}/${currlib}"
	@${install_library} ${REDIRECT}
# Some OSes truncate the value of seconds in the time when copying.
# Touching the installed library prevents gmake from gratuitous recopying.
	@${TOUCH} ${dir_instlib}/${currlib}

      else
         install_lib: FORCE
	@${ECHO}
	@${ECHO} Leaving the library as:
	@${ECHO} "   `pwd`/${currlib}"

      endif

   endif

else
   install_lib: FORCE
	@${ECHO}
	@${ECHO} BUILDLIB is negative so the library is not installed.

endif

ifdef buildbin
   ${currbin}: ${currlib}
	@${ECHO}
	@if [ ! -f ${main_obj} ] ; then \
	    ${ECHO} Extracting main object; \
	    ${extract_main_obj} ${REDIRECT}; \
	fi
	@${ECHO} Linking binary
	@${link_binary} ${REDIRECT}
	@${ECHO} Stripping binary if necessary
	@${strip_binary} ${REDIRECT}

   ifdef dir_instbin
      install_bin: ${dir_instbin}/${currbin} FORCE
	@${ECHO}
	@${ECHO} The installed binary is up-to-date.

      ${dir_instbin}/${currbin}: ${currbin}
	@${ECHO}
	@${ECHO} Installing the binary as:
	@${ECHO} "   ${dir_instbin}/${currbin}"
	@${install_binary} ${REDIRECT}
	@${TOUCH} ${dir_instbin}/${currbin}
	@${CHMOD0755} ${dir_instbin}/${currbin}

   else
      install_bin: FORCE
	@${ECHO}
	@${ECHO} Leaving the binary as:
	@${ECHO} "   `pwd`/${currbin}"

   endif

else
   install_bin: FORCE
	@${ECHO}
	@${ECHO} BUILDBIN is negative so the binary is not installed.

endif

##########
# cleaning

distclean clean: tabula_rasa libclean FORCE
	@${ECHO}
	@${ECHO} Removing objects, intermediates, and junk
	@${ECHO} ${F_d} ${F90_d}   ${F95_d}   ${c_d} ${cxx_d} | ${XARGS} ${RM}
	@${ECHO} ${F_f} ${F90_f90} ${F95_f95}                 | ${XARGS} ${RM}
	@${ECHO} ${obj} ${main_obj}                           | ${XARGS} ${RM}
	@${ECHO} ${JUNK}                                      | ${XARGS} ${RM}
   ifneq ($(strip ${F95_mod} ${f95_mod} ${F90_mod} ${f90_mod}),)
	@${ECHO}
	@${ECHO} Removing module files
	@${ECHO} ${F95_mod} ${f95_mod} ${F90_mod} ${f90_mod} | ${XARGS} ${RM}
   endif
	@${ECHO}
	@${ECHO} Remaining files:
	@/bin/ls -F
	@${ECHO}

ppclean: libclean FORCE
	@${ECHO}
	@${ECHO} Removing children of files with pre-processing directives
	@${ECHO} ${F_d} ${F90_d}   ${F95_d}   ${c_d} ${cxx_d} | ${XARGS} ${RM}
	@${ECHO} ${F_f} ${F90_f90} ${F95_f95}                 | ${XARGS} ${RM}
	@${ECHO} ${F_o} ${F90_o}   ${F95_o}   ${c_o} ${cxx_o} | ${XARGS} ${RM}

libclean: binclean FORCE
   ifdef currlib
	@${ECHO}
	@${ECHO} Removing ${currlib}
	@${RM} ${currlib}
   endif

binclean: FORCE
   ifdef currbin
	@${ECHO}
	@${ECHO} Removing ${currbin}
	@${RM} ${currbin}
   endif

#########
# archive

archive: FORCE
	@${ECHO}
	@if [ -f ${dir_insttgz}/${currtgz} ] ; then \
	    ${ECHO} Removing old archive ; \
	    ${RM} ${dir_insttgz}/${currtgz} ; \
	 fi
	@${ECHO} Archiving source files
	@${archive_source}

########
# backup

DATE ?= $(shell date +%m%d)
date := $(strip ${DATE})
BACKUPDIR ?= backup.${date}
backupdir := $(strip ${BACKUPDIR})

backup: FORCE
	@${ECHO}
	@if [ ! -d ${backupdir} ] ; then \
	    ${ECHO} Attempting to ${MKDIR} ${backupdir} ; \
	    ${MKDIR} ${backupdir} ; \
	 else \
	    ${ECHO} ${backupdir} already exists ; \
	 fi
	@${ECHO} Backing-up sludge
#	@${CP} ${sludge} ${backupdir}
#begin AIX cheat
	@${CP} ${currlib} ${currbin} ${main_obj} \
	       ${obj} \
	       ${F_d} ${F90_d}   ${F95_d}   ${c_d} ${cxx_d} \
	       ${F_f} ${F90_f90} ${F95_f95} \
	       ${F95_mod} ${f95_mod} \
	       ${F90_mod} ${f90_mod} ${backupdir}
#end AIX cheat
	@${ECHO}

#######
# debug

debug: FORCE
	@${ECHO} "   ${BANNER}"
	@${ECHO}
	@${ECHO} "   If you are having MAJOR problems, please contact"
	@${ECHO} "   ACES technical support at ${TECHSUPPORT}."
	@${ECHO} "***************************************************"
	@${ECHO}
	@${ECHO} "   PLATFORM:"
	@${ECHO}
	@${ECHO} "architecture     : ${ARCH}"
	@${ECHO} "operating system : ${OPSYS}"
	@${ECHO} "compiler         : ${CMPLR}"
	@${ECHO} "effective name   : ${MACHNAME}"
   ifneq (${MACHNAME},$(word 1, ${uname}))
	@${ECHO} "(real name       : $(word 1, ${uname}))"
   endif
   ifdef 64bit
	@${ECHO} "integer length   : 64 bits"
   else
	@${ECHO} "integer length   : 32 bits"
   endif
#   ifeq (${OPSYS},aix)
#	@${ECHO} "cache spec       : ${CACHE}"
#   endif
	@${ECHO}
	@${ECHO} "   SWITCH STATES:"
	@${ECHO}
	@${ECHO} DEBUG=${DEBUG}, PROFILE=${PROFILE}, OPTIMIZE=${OPTIMIZE}, \
	         FAST=${FAST}, TEST=${TEST}, 64BIT=${64BIT}, \
	         PARALLEL=${PARALLEL}
   ifdef debug
	@${ECHO} "DEFINE_DEBUG := ${define_debug}"
	@${ECHO} "FLAG_DEBUG   := ${flag_debug}"
   endif
   ifdef profile
	@${ECHO} FLAG_PROFILE := ${flag_profile}
   endif
   ifdef optimize
	@${ECHO} FLAG_OPTIMIZE := ${flag_optimize}
   endif
	@${ECHO}
	@${ECHO} "   COMPILING SOURCE CODE:"
	@${ECHO}
   ifneq ($(strip ${cxx_o}),)
	@${ECHO} "${compile_cxx} %.${ext_cxx} %.${ext_o}"
	@${ECHO}
   endif
   ifneq ($(strip ${c_o}),)
	@${ECHO} "${compile_c} %.${ext_c} %.${ext_o}"
	@${ECHO}
   endif
   ifneq ($(strip ${F95_f95}),)
	@${ECHO} "${process_F95} %.${ext_F95} %.${ext_f95}"
	@${ECHO}
   endif
   ifneq ($(strip ${F95_o} ${f95_o}),)
	@${ECHO} "${compile_f9x} %.${ext_f95} %.${ext_o}"
	@${ECHO}
   endif
   ifneq ($(strip ${F90_f90}),)
	@${ECHO} "${process_F90} %.${ext_F90} %.${ext_f90}"
	@${ECHO}
   endif
   ifneq ($(strip ${F90_o} ${f90_o}),)
	@${ECHO} "${compile_f9x} %.${ext_f90} %.${ext_o}"
	@${ECHO}
   endif
   ifneq ($(strip ${F_f}),)
	@${ECHO} "${process_F} %.${ext_F} %.${ext_f}"
	@${ECHO}
   endif
   ifneq ($(strip ${F_o} ${f_o}),)
	@${ECHO} "${compile_f} %.${ext_f} %.${ext_o}"
	@${ECHO}
   endif
   ifdef buildmod
	@${ECHO} "   MODULES:"
	@${ECHO}
	@${ECHO} ${install_mods}
	@${ECHO}
	@${ECHO} ${install_mod_library}
	@${ECHO}
   endif
   ifdef buildlib
	@${ECHO} "   THE LIBRARY:"
	@${ECHO}
	@${ECHO} '${archive_objects}'
	@${ECHO}
	@${ECHO} \`gmake install\` will:
	@${ECHO} ${install_library}
	@${ECHO}
   endif
   ifdef buildbin
	@${ECHO} "   THE BINARY:"
	@${ECHO}
	@${ECHO} \#LDFLAGS_NUMLIBS := ${LDFLAGS_NUMLIBS}
	@${ECHO} \#LDFLAGS_MPILIBS := ${LDFLAGS_MPILIBS}
	@${ECHO}
	@${ECHO} ${extract_main_obj}
	@${ECHO}
	@${ECHO} ${link_binary}
	@${ECHO}
	@${ECHO} ${strip_binary}
	@${ECHO}
	@${ECHO} \`gmake install\` will:
	@${ECHO} ${install_binary}
	@${ECHO}
   endif

#

##########
## TODO ##
##########

# Create installdirs goal.

# Have object directories for debugged, profiled, optimized, and plain
# objects for immediate testing of source.

# Add module dependencies for FAST=0 and FORTRAN 9x source.

# Create curr(some.o) rules so objects can be deleted.

#

#####################################
## INDEX OF CONFIGURABLE VARIABLES ##
#####################################

# Machine dependent variables
#    MACHNAME - the hostname (e.g., "crunch") used as a handle for setting
#               MACH, and OPSYS.
#          } These variables are primarily used in the porting section
#    MACH  } for setting various flags, directories, and commands unique to
#    OPSYS } each environment. If MACH is undefined then make does nothing.

# Basic UNIX commands
#    SHELL, TOUCH, ECHO
#    RM, MV, CP, MKDIR, INSTALL

# Common file extensions
#    EXT_cxx, EXT_c,
#    EXT_F95, EXT_f95, EXT_F90, EXT_f90, EXT_F, EXT_f,
#    EXT_d, EXT_mod, EXT_o
#    EXT_tgz

# Automatic variable controls
#    CPP, CXX, and LD have at least the following variables
#       $*            - the compiler or linker
#       $*FLAGS       - overrides all other flags (except "-c" and NUMLIBS)
#                       if set on the command line
#       $*FLAGS_EXTRA - added to the $*FLAGS
#
#    special variables for the preceding commands
#       DEFINES         - overrides all other defines if set on the CL
#       DEFINES_EXTRA   - added to ${DEFINES}
#       CPPFLAG_DEPEND  - passed to CPP for listing include dependencies
#       LDFLAGS_NUMLIBS - lists -L and -l for numerical libraries
#
#    C, F9X, and F have at least the following variables
#       $*C           - the compiler command
#       $*FLAGS       - overrides all other flags (save "-c") if set on the CL
#       $*FLAGS_EXTRA - added to $*FLAGS
#
#    special variables for the preceding commands
#       MODDIRS_PREFIX - prepends to ${INCDIRS} when compiling F9X
#
#    the object archiver
#       AR         - the archiver command
#       AR_REPLACE - flag for replacing objects in a library
#       AR_EXTRACT - flag for extracting objects from a library
#
#    the tape archiver
#       TAR      - the archiver command
#       TAR_GZIP - flag to pass tar stream through a compressor
#       TAR_CF   - flags for creating a tar file

# Switching behavior
#
#    STRIP - runs on CURRLIB and CURRBIN regardless of compiler commands, but
#            automatically turns to ${TOUCH} if debugging or profiling.
#
#    C_SUFFIX:
#       DEFINE_C_SUFFIX - adds -DC_SUFFIX -DCB_SUFFIX to CPPFLAGS
#
#    DEBUG:
#       DEFINE_DEBUG - adds -D_DEBUG to CPPFLAGS
#       FLAG_DEBUG   - added to the compilers' and linker's flags
#       DIR_DEBUGLIB - added in library search path
#       DIR_PROFLIB  - added in library search path
#
#    PROFILE:
#       FLAG_PROFILE - added to the compilers' and linker's flags
#
#    TEST:
#       DIR_TESTLIB - added in library search path
#       DIR_TESTINC - added in library search path
#
#    OPTIMIZE:
#       FLAG_OPTIMIZE - added to the compilers' and linker's flags
#
#    FAST:
#       - doesn't check for updated include files
#
#    BUILDLIB:
#       LIB_PREFIX - prepends to ${CURR}
#       LIB_SUFFIX - appends to ${CURR}
#       CURRLIB    - final name of the library
#
#    BUILDBIN:
#       BIN_PREFIX - prepends to ${CURR}
#       BIN_SUFFIX - appends to ${CURR}
#       CURRBIN    - final name of the binary
#       LIST_LINKLIBS - colon-delimited list of library kernels for linking

# Common directories
#
#    DEF, SRC, and EXTRA have two directories named from them
#       DIR_$*LIB - added to library search path
#       DIR_$*INC - added to include search path
#
#    BIN, LIB, INC, MOD, and TGZ all have the following
#       DIR_INST$* - directory for installing targets to

# CURR := $(notdir $(shell pwd))

# Extra
#    JUNK        - extra files or file patterns to remove when making clean
#    MAKE_OUTPUT - the output redirection file
#    MAKE_ERROR  - the error redirection file
#    REDIRECT    - the redirection command

# The remaining variables are all conditionally set with "?=" in the file

# INCDIRS       - overrides include directories
# FLAG_INCLUDES - overrides include flags
# FLAG_PREPROC  - overrides define and include flags
# FLAG_MODULES  - overrides module flags
# FLAG_OPT      - overrides -g, -pg, and -O set by the switches

# MAIN_OBJ - overrides ${CURR}.o
# OBJ      - overrides objects to build and archive

# LIBDIRS   - overrides library search path
# LINKLIBS  - overrides libraries to link against
# FLAG_LIBS - overrides all -L and -l linker flags

# SLUDGE - overrides files to remove when making "clean"

# DATE - the extension to "backup." when backing-up ${SLUDGE}
# BACKUPDIR - overrides backup.${DATE} as the backup directory

# Advanced functions - read the file for usage
#    make_depend
#    process_F95
#    process_F90
#    process_F
#    compile_cxx
#    compile_c
#    compile_f9x
#    compile_f
#    archive_objects
#    strip_library
#    install_library
#    install_mod_library
#    install_mods
#    extract_main_obj
#    link_binary
#    strip_binary
#    install_binary

