Settarg is an optional feature of Lmod.  It is there to answer the
question is there an easy way for your build system to know which
compiler you are using, which mpi stack, what other modules are you
using.  And the fundamental feature of settarg is: Can you have an
single environment variable that enscapsulates the state of your
modules (that you care about).  The answer to those questions is yes,
it is settarg.  Settarg knows how to read the module table and
therefore know what modules you have loaded.

Many developers like to build their programs in multiple ways (say in
debug or optimized modes).  Settarg provides environment variables that
be used to control the build process.

The workflow envisioned here is that $TARG will name a directory that
will contain the build artifacts (e.g. *.o and executables).


How do you use settarg?
-----------------------

a) Configure and install Lmod with settarg support to be "yes" or
   "full".  Using "full" will provide some aliases which are optional.
b) Try loading the settarg module.
c) If you can't then copy the modulefiles/Core/settarg/settarg.lua
   into your module tree. Note that modulefiles is a directory under
   the same tree where the lmod program is stored.  Then try again
   to load settarg.
d) Run any module command and verify that the TARG variable have been
   set:
       $ env | grep TARG
e) Verify that the "precmd" shell function or alias is defined and
   PROMPT_COMMAND="precmd" for bash.  Strings that contain the
   compiler name should appear in the xterm title bar.

What variables are set?
-----------------------

    TARG_MACH=x86_64_06_2d
    TARG_BUILD_SCENARIO=dbg

    TARG_COMPILER=gcc-4.6.3
    TARG_COMPILER_FAMILY=gcc

    TARG_MPI=openmpi-1.6.3
    TARG_MPI_FAMILY=openmpi


    TARG_OS=Linux-2.6.32-279
    TARG_OS_Family=Linux
    TARG_HOST=stampede


    TARG_SUMMARY=x86_64_06_2d_dbg_gcc-4.6.3_openmpi-1.6.3

    TARG_TITLE_BAR=D G-4.6.3 O-1.6.3
    TARG_TITLE_BAR_PAREN=(D G-4.6.3 O-1.6.3)

    TARG=OBJ/_x86_64_06_2d_dbg_gcc-4.6.3_openmpi-1.6.3

This is a common set of variables generated or used by settarg.

2) TARG_MACH:      This is the machine architecture along with the
                   cpu family and model number in two hex numbers.

3) TARG_BUILD_SCENARIO:  This can be used to control compiler flags
                         so that "dbg" might mean to create a
                         debuggable executable.  Where as "opt" might
                         mean to build a fully optimized build.  To
                         clear this field use "empty"


4) TARG_OS, TARG_OS_FAMILY: These are the OS name and family.  These
                            variables are always defined even if there
                            are not part of TARG_SUMMARY.


5) TARG_HOST:  See below on how this is extracted from `hostname -f`

6) TARG_COMPILER, TARG_MPI, etc:  the name of the compiler and version


7 TARG_SUMMARY:  The dynamic combination of items like the machine
                 architecture, build scenario, etc.   See below for
                 how this gets built.

8) TARG_TITLE_BAR:  This contains everything in TARG_SUMMARY but it is
                    abbreviated to fit the space available.

8) TARG:  This variable contains all the "interesting" items.  How is
          put together is described later.



Controlling settarg via the .settarg.lua configuration files:
-------------------------------------------------------------

Below is a typical .settarg.lua file.  This is file contains several
tables in written in Lua.  If you don't know Lua, it still should be
easy to modify this table. just remember the comma's.

The BuildScenarioTbl table maps host name to Build Scenario state.  So
the default is "empty" which means that the TARG_BUILD_SCENARIO is
undefined.  If you are on "login1.stampede.tacc.utexas.edu" your
default TARG_BUILD_SCENARIO will be "opt".  Similarily, any host with
"foo.bar.edu" will have a default scenario of "dbg".

------------------------------------------------------------------------
BuildScenarioTbl = {
   default             = "empty",
   ["tacc.utexas.edu"] = "opt",
   ["foo.bar.edu"]     = "dbg",
}

ModuleTbl = {
   build_scenario     = { "dbg", "opt", "empty"},
   compiler           = { "intel", "pgi", "gcc", "sun",},
   mpi                = { "mpich", "mpich2", "openmpi", "mvapich2", "impi"},
   solver             = { "petsc","trilinos"},
   profiling          = { "mpiP", "tau"},
   file_io            = { "hdf5", "netcdf", },
}

TargetList = { "mach", "build_scenario", "compiler", "mpi"}

SettargDirTemplate = { "$SETTARG_TAG1", "/", "$SETTARG_TAG2", "$TARG_SUMMARY" }

NoFamilyList = {"mach", "build_scenario"}

TitleTbl = {
   dbg                    = 'D',
   opt                    = 'O',
   impi                   = "IM",
   mvapich2               = 'M',
   openmpi                = "O",
   mpich                  = "M",
   mpich2                 = "M2",
   intel                  = "I",
   gcc                    = "G",
   phdf5                  = "H5"
   hdf5                   = "H5"
}

TargPathLoc = "first"

HostnameTbl = { 2}

------------------------------------------------------------------------

ModuleTbl connects module names with a category.  It is also used to
define "build_scenario" which is just words to declare a build state.
In other words, in the above table "dbg" and "opt" could be anything.
The only hard-wired name is "empty".  The category "build_scenario" is
also hard-wired.  The names of all other categories are not fixed and
you are free to add other categories.

This table is also how settarg knows what the names of the compiler
and mpi stacks are.  If your site uses the name "ompi" for openmpi
then the above table will have to be modified to match.

TargetList defines how TARG_SUMMARY is assembled.  It is an array of
categories.   The category "mach" is special it is always defined to
be `uname -m` plus on linux systems it contains the cpu family and
model from /proc/cpuinfo. Each piece is concatenated together with
"_".  If an item is undefined then the extra "_" is removed.

Settarg ships with the order given above, but sites and users can
change the order to be anything they like.  Also notice that there are
many more categories then are listed in TargetList.  More on this
aspect in the "Custom Configuration" section.

SettargDirTemplate specifies how TARG is assembled.  In the case shown
above then env var SETTARG_TAG1 is combined with "/" and
SETTARG_TAG2 followed by TARG_SUMMARY.  Both "TAG" variables have to
be set in the environment.  Here we have assumed that SETTARG_TAG1 is
"OBJ" and SETTARG_TAG2 is "_".  This leads to TARG being:

    TARG=OBJ/_x86_64_06_2d_dbg_gcc-4.6.3_openmpi-1.6.3


The NoFamilyList is an array of categories that do not get the FAMILY
version.  All categories do.  For example, if TARG_COMPILER is
"gcc-4.7.2" then TARG_COMPILER_FAMILY is "gcc".

The TARG_TITLE_BAR and TARG_TITLE_BAR_PAREN are strings that could be
used in a terminal title bar. Every item in the TARG_SUMMARY is in the
TITLE bar variables (except for TARG_MACH).  Because the title bar
space is limited, TitleTbl is a way to map each item into an
abbreviation.   The order in which categories appear on the
title bar is the same as TargetList.  So a title bar with "O G-4.7.2
O-1.6.3" would mean that you are in "opt" mode with gcc/4.7.2 and
openmpi/1.6.3 loaded.

TargPathLoc controls where (or if) $TARG.  Normally the value of TARG
is placed in the PATH at the begining of your PATH.  You can place it
at the end of your PATH when TargPathLoc = "last".  If TargPathLoc is
"empty" then TARG is removed from your path.  Actually the rules
controlling where TARG goes in your path are slightly more
complicated.  TargPathLoc controls where $TARG is placed in your path
when TARG was not there before.  After the first time TARG is added to
your path, TARG maintains its relative location.

Finally, HostnameTbl tells settarg how to extract an entry from the
full hostname to be used as TARG_HOST.  If your host has multiple
components then a "2" would say to use the second component as
TARG_HOST.  So if your hostname is "login1.stampede.tacc.utexas.edu"
then TARG_HOST would be "stampede".  If HostnameTbl was "{ 3,2}" then
TARG_HOST would be "tacc.stampede".  If your hostname has a single
component then that is used for TARG_HOST.

Commands:
---------

The environment TARG's value is typically used as a name of the build
directory.  So the settarg module provides some helpful aliases to
take advantage of this.

   * gettargdir: it is simply an alias for "echo $TARG"
   * cdt:        Another alias: "cd $TARG"
   * settarg:    How to set the build scenario and to access other
                 features.

By default settarg has an "empty" build scenario.  This can be changed
by:
    $ settarg dbg
    $ settarg opt

Which will change TARG_BUILD_SCENARIO to "dbg" or "opt".  Also

    $ settarg --report

report the state of the .settarg table after combining all the
possible .settarg.lua files.

For those of you who like short commands the settarg module provides:

    $ targ

which is a short for "gettargdir".  Also if you switch between build
scenarios frequently may wish to define the following shortcuts for
setting dbg and opt.

    dbg() { settarg "$@" dbg; }
    opt() { settarg "$@" opt; }

These shortcuts are defined by the settarg module if Lmod is installed
with "--with-settarg=full"

Custom Configuration:
---------------------

Settarg will read up to three separate copies of .settarg.lua.  The
first one is in the same directory as the settarg command is.  The
second place is in the user's home directory (if it exists).  Then
from the current directory up to "/" it looks for another .settarg.lua
(if it exists).  It will not re-read the ~/.settarg.lua.  Typically a
user should copy the system .settarg.lua to their home directory and
specify the generally desired behaviour.  Then in top directory of a
project place a simple .settarg.lua that specifies how the target list
should be put together for that project:

Suppose that TargetList ~/.settarg.lua is

   TargetList  = { "mach", "build_scenario", "compiler", "mpi",}

Then in ~/project/a there is another .settarg.lua that just has:

   TargetList  = { "mach", "build_scenario", "compiler", "mpi", "file_io"}

Normally in any directory your TARG will be the default, but in any
directory below ~/project/a TARG will have hdf5 or netcdf if either
are loaded.


Using TARG in a Makefile:
-------------------------

See the make_example directory and the README.txt inside.  That directory
contains a simple Makefile and a more complicated one to a way to use
$TARG in a Makefile so that all generated files (*.o and the
executable) are in the $TARG directory.
