STU(1)                                STU                               STU(1)

NAME
       stu - build automation

SYNOPSIS
       stu [ -q | -P | -I ] [ -f FILENAME ] [ OPTION ]... [ TARGET ]...

DESCRIPTION
       Stu  is  a  tool  for  build automation.  Like Make, it is used to call
       other programs in order to build files.  Stu has  three  features  that
       work  in  conjunction to allow contructs impossible to realize in Make:
       (1) Dynamic dependencies:  The dependencies of a target  can  be  them‐
       selves computed by a command.  When '[FILENAME]' (a filename currounded
       by angle brackets) is used as a dependency, Stu  will  build  the  file
       FILENAME  and  read  dependencies  from  it.  (2) Parameters:  Names of
       files (and transient targets) can contain parameters written using dol‐
       lar  syntax.   For  example, a rule with a target filename 'list.$name'
       will be used to build any file matching the pattern 'list.*',  and  the
       parameter  $name  can be used in names of dependencies and in the build
       command.  Targets may contain any number of parameters.  (3) Concatena‐
       tion:   Stu allows expressions such as list.[FILENAME] and list.(a b c)
       to construct a list of files following a certain pattern.

       At its core, Stu is very much like Make: Instead of a  'Makefile',  one
       uses a file named 'main.stu', which is read by Stu. Also like Make, Stu
       will build the first target it finds, except if given an explicit  tar‐
       get  to  built.   Stu is designed to follow the conventions of Make, of
       the shell, and of Unix and POSIX in general.  As an  example,  the  op‐
       tions -f and -k have the same meaning in Stu as they do in Make.

       Rules for building files are read from the file 'main.stu', from a file
       passed by the -f option, or using -F.

       Names of targets to build passed on the command line outside of options
       follow  a  simplified  Stu syntax, in which the only special characters
       are the transient target marker '@', brackets '[]', and flags  starting
       with a dash '-'.  All other characters are interpreted as part of file‐
       names; this includes all spaces.  The parentheses '()' are  not  parsed
       as  Stu  syntax,  because  the shell's braces '{}' can be used instead.
       When -J is used, arguments passed on the command line  are  interpreted
       as  filenames  without  Stu syntax.  The syntax of arguments outside of
       options and without using the -J is subject to change with new features
       in  Stu  --  to pass filenames portably, use the -c option when passing
       individual filenames, or -J when passing multiple filenames,  e.g.  via
       xargs(1).   To pass targets in full stu syntax portably, use the -C op‐
       tion.

OPTIONS
       -0 FILENAME
              Read targets from  FILENAME,  which  must  contain  \0-separated
              filenames.   No  Stu  syntax  is processed.  This option is also
              suitable in all cases where a file contains only the name  of  a
              single  file,  since  filenames do not contain the \0 character.
              Using this option is equivalent to using the [-0 FILENAME]  syn‐
              tax.

       -a     Treat  all  trivial dependencies, which are declared with the -t
              flag or option, as non-trivial.

       -c FILENAME
              Pass a target filename, without Stu syntax.   This  option  only
              allows file targets to be specified, not transient targets.

       -C EXPRESSION
              Pass  a  target  using full Stu syntax.  The given expression is
              parsed as if it was given as one or more dependencies in  a  Stu
              script.  As a result, flags -p, -o and -t, brackets, parentheses
              and other Stu syntax elements can be used, and  spaces  separate
              filenames.  This is not equivalent to passing a string as an ar‐
              gument to Stu outside of options, because -C supports  full  Stu
              syntax,  while  arguments  supports  only  a reduced syntax (see
              above).

       -d     Debug mode.  Show internal information about the  Stu  algorithm
              on  standard  error output.  All printed output lines begin with
              the string 'DEBUG  ', i.e. the word DEBUG followed by  two  spa‐
              ces.  The output is otherwise not standardized and is subject to
              change, in particular with internal changes  to  the  algorithms
              used.

       -E     Explain  error  messages.  For certain errors, an additional ex‐
              planation is written on standard error output.  Only some  error
              messages have explanations.

       -f FILENAME
              Read  the  given file instead of the default 'main.stu'.  If the
              name of a directory is passed, the file 'main.stu' in the  given
              directory  is read.  If '-' is passed, read standard input.  The
              -f option can be used multiple times.

       -F RULES
              Pass rules in full Stu syntax.

       -g     Treat all optional dependencies (declared with the -o  flag)  as
              non-optional.

       -h, --help
              Output a short help and exit.

       -i     Interactive  mode.   I.e., put the jobs run into the foreground.
              Must not be used in conjunction with -j N when N >  1.   Without
              this  option, jobs are run in the background, meaning they can't
              read standard input (they get /dev/null instead), will  not  get
              any  terminal  signals,  and  pressing Ctrl-C will stop Stu as a
              whole.  Using this option, each job is run  in  the  foreground,
              and  therefore  they  can read standard input, will get terminal
              signals such as SIGINT (after Ctrl-C)  and  end-of-stdin  (after
              Ctrl-D).   Thus,  when -i is used, pressing Ctrl-C will only in‐
              terrupt the currently running job, and if the -k option is used,
              Stu  will  continue  with the next job.  When Ctrl-Z is pressed,
              Stu will interrupt the currently running job, and ask  the  user
              to  press ENTER to continue, or press Ctrl-C/Ctrl-Z to interrupt
              or suspend Stu itself.  When -i is used, Stu must be  run  in  a
              terminal.

       -I     Print a list of all buildable file targets and exit.  Prints one
              file pattern per line.  The patterns are glob  pattern  suitable
              for  use in the shell.  Use quoting for all characters that need
              quoting in the shell.  Can be used to  populate  files  such  as
              ".gitgignore",  but care should be taken due to the quoting syn‐
              tax and Git's special handling of names that start or end with a
              slash.

       -j K   Run  K jobs in parallel.  K must be a positive integer.  Without
              this option, jobs are not run in parallel, which  is  equivalent
              to  using  the  -j 1 setting.  When running jobs in parallel and
              the -k option is not used, a single job that fails will make Stu
              abort all other running jobs and terminate.  Thus, the -j option
              is often used in conjunction with the -k option.  The  parameter
              K is mandatory.  This option works like the corresponding option
              in GNU Make, but note that in GNU  Make,  the  argument  is  op‐
              tional.

       -J     Parse  all arguments to Stu as filenames, disabling all Stu syn‐
              tax that is otherwise used.  Intended  when  Stu  is  used  with
              tools  such  as  xargs(1) or similar.  The -J option itself does
              not take an argument; it only changes the way arguments  outside
              of options are interpreted.

       -k     Keep going.  Do not stop running when an error occurs.  Instead,
              try to build as much as possible.  This option is equivalent  to
              that of Make.

       -K     Don't  delete partially built files when a command fails or when
              Stu is interrupted.  By default, Stu will delete the target of a
              command after the command fails or is interrupted, when the file
              is newer than it was before starting the  command.  This  option
              disables  that  behavior.   Note that with this option, a subse‐
              quent invocation of Stu may lead to the partially built file be‐
              ing erroneously considered up to date.

       -m ORDER
              Specify  the  order  in which jobs are run.  When ORDER is 'dfs'
              (the default), Stu traverses the dependency graph  in  a  depth-
              first  fashion,  in  a way similar to most Make implementations.
              When ORDER is 'random', the order in which jobs are run is  ran‐
              domized within each target.

       -M STRING
              Run jobs in pseudorandom order, seeded by the given string.

       -n FILENAME
              Read targets from FILENAME, which must contain newline-separated
              filenames.  No Stu syntax is processed.  Using  this  option  is
              equivalent to using the [-n FILENAME] syntax.

       -o FILENAME
              Pass  the  given  file as an optional dependency, i.e., build it
              only if it already exists and is out of date.

       -p FILENAME
              Pass the given file as a persistent dependency, i.e., build  the
              file but ignore its timestamp.

       -P     Print the set of rules and exit.  Note that Make has a -p option
              to print the rules, but does not exit.  The output format is not
              specified.

       -q     Question mode.  Do not execute any commands.  Instead, determine
              whether the targets are up to date.  The exit status is  0  when
              all  given targets (or the default target) are up to date, and 1
              when not.  The exit status may still be 2 or 4  on  encountering
              logical or fatal errors.  The options -k and -j are ignored.

       -s     Silent  mode.   Suppress  messages on standard output:  messages
              about which commands are run, a message when the build  is  suc‐
              cessful,  and a message when there is nothing to be done.  Error
              messages are not suppressed.  This option is comparable  to  the
              same option in Make.

       -V, --version
              Output the version number of Stu and exit.

       -x     Call  the shell using the -x option, i.e., each individual shell
              command is output to standard error output individually, instead
              of outputting a full command at once on standard output.  In the
              output, each command is prefixed by the value of '$PS4'.

       -y     Disable color in output.  By default, Stu checks  whether  error
              output  and  standard error output are TTYs and whether $TERM is
              defined and not 'dumb' and if they are,  uses  ANSI  escape  se‐
              quences to color code messages.

       -Y     Enable color output.

       -z     Output runtime statistics about child processes on standard out‐
              put when finished.  Does not include  the  runtime  of  the  Stu
              process  itself.   Includes  the runtime of all child and grand‐
              child processes, and so on.  Does not  include  the  runtime  of
              children  or  grandchildren that have not been waited for (which
              only happens when Stu is interrupted by a signal.)

              Stu options are parsed with getopt(3) and therefore options must
              precede arguments.  Options following arguments may be supported
              on some platforms.

OVERVIEW
       A simple rule looks as follows:

           results.txt:  data.txt compute {
               ./compute --input data.txt --output results.txt
           }

       The colon may be omitted when there are no dependencies:

           data.csv { ./generate --output data.csv }

       Here is an example of a rule containing three parameters.  Stu will use
       pattern matching to match the target pattern to a given filename:

           plot.$dataset.$method.$measure.eps:
               data-$dataset.txt analyse-$method
           {
               ./analyse-$method \
                   -m $measure \
                   -f data-$dataset.txt \
                   -o plot.$dataset.$method.$measure.eps
           }

       Here  is an example of a dynamic dependency.  The target 'compute' (a C
       program) must be rebuild whenever its source code files  are  modified.
       Since  the  set  of  source  code  files is large and may be changed by
       changing the source code itself, we use  the  file  'compute.c.dep'  to
       contain  the  list of dependencies.  The file 'compute.c.dep' will then
       be built by Stu like any file, and its content parsed  for  the  actual
       dependencies:

           compute:  [compute.c.dep] {
               gcc -c compute.c -o compute
           }
           $name.c.dep:  $name.c compute-dep {
               ./compute-dep-c "$name.c" >"$name.c.dep"
           }

       Parameters can also use the syntax ${...}.

       Syntax  can  be  on  multiple lines; whitespace is not significant.  No
       backslashes are needed at line ends:

           output.txt:
               a.data b.data c.data d.data e.data f.data g.data h.data i.data
               j.data k.data l.data m.data
           {
               do-stuff >output.txt;
           }

       A rule may be entirely given on a single line:

           system-info: { uname -a >system-info }

       The following rule uses single quotes to declare filenames that include
       parentheses and a colon:

           '((':  'aaa:bbb' {
               ./bla -f
           }

       Multiple  parametrized rules may match a target.  In that case Stu uses
       the one that is the least parametrized, as defined by the subset  rela‐
       tion  on  the  set of characters that are in parameters.  When building
       'X.txt' in this example, only the second rule is called:

           $name.txt: {  echo "$name" is the best >"$name.txt" }
           X.txt:  { echo X sucks >X.txt }

       Persistent dependencies:   In  the  following  example,  the  directory
       'data'  is  a  persistent dependency, i.e. 'data' is only built when it
       does not exist, but it is never re-built.  A persistent  dependency  is
       indicated  by the -p flag.  This is useful for directories, whose time‐
       stamps change when files are created/removed in them.

           data/file:  -p data {
               echo Hello >data/file
           }
           data: { mkdir data }

       Optional dependencies can be declared with the -o  flag.   An  optional
       dependency will never be built if it does not already exist.  If it al‐
       ready exists, then its own rule is used (and its date checked)  to  de‐
       cide whether it should be rebuilt.

           target:  -o input {
               if [ -r input ] ; then
                   cp input target
               else
                   echo Hello >target
               fi
           }

       Trivial  dependencies  are denoted with the -t flag.  They denote a de‐
       pendency that should never cause a target to be  rebuilt,  but  if  the
       target is rebuilt for another reason, then they are treated like normal
       dependencies.  Trivial dependencies don't even cause a target to be re‐
       built if they don't exist.  Trivial dependencies are typically used for
       configuration, i.e., for the setting up configuration  of  application.
       Trivial dependencies are not allowed if the rule has no command.

           target:  -t input { ... }

       Variable dependency:  the content of variables can come from files.  In
       the following example, the C flags are stored in the file 'CFLAGS', and
       used in the compilation command using the $[CFLAGS] dependency.

           compute:  compute.c $[CFLAGS]
           {
               gcc $CFLAGS compute -o compute.c
           }
           CFLAGS: { echo -Wall -Werror >CFLAGS }

       Variable  dependencies  may be declared as persistent as in $[-p X] and
       as trivial as in $[-t X] but not as optional using the -o flag.  By de‐
       fault,  the  name of the variable set is the same as the filename.  An‐
       other variable name can be used in the following way:

           $[NAME = FILENAME]

       If multiple variable dependencies have the same name, it is unspecified
       which  one  is used.  If a variable dependencies has the same name as a
       parameter, it overrides the parameter.

       Transient targets are marked with '@'.  They are used for targets  such
       as '@clean' that do an action without building a file, and for lists of
       files that depend on other targets, but don't have a command associated
       with  them.   They are also used instead of variables that would other‐
       wise contain a list of filenames.

       Here is a transient target that cleans up the directory:

           @clean:  { rm -Rf *.o *~ }

       Here a transient target is used as a shortcut to a longer name:

           @build.$name:   dat/build.$name.txt;

       Here a transient target is used as a list of files.   Multiple  targets
       can depend on it, to effectively depend on the individual files:

           @headers:  a.h b.h c.h;

           x:  x.c @headers {
               cc x.c -o x
           }

           y:  y.c @headers {
               cc y.c -o y
           }

FEATURES
       Like  a makefile, a Stu script consists of rules.  In Stu, the order of
       rules is not important, except for the fact that the first rule is used
       by  default  if no rule is given explicitly.  Comments are written with
       '#' like in Make or in the shell.

       The basic syntax is similar to that of  make,  but  does  not  rely  on
       mandatory  whitespace.   Instead  of tabs, the commands are enclosed in
       curly braces.

       Stu syntax supports two types of objects:  file targets  and  transient
       targets.   Files are any file in the file system, and are always refer‐
       enced by their filename.  Transient targets have names  beginning  with
       the  '@'  symbol and do not correspond to files, but can have dependen‐
       cies and commands.

       A rule for a file in Stu has the following syntax:

           [>] TARGET [ : DEPENDENCY ... ] { COMMAND }

       The target is a filename.  DEPENDENCY ... are depencies.  COMMAND is  a
       command which is passed to the shell for building.  Stu will always ex‐
       ecute the whole command block using a single call to the  shell.   This
       is different than Make, which calls each line individually.  This means
       that you can for instance define a variable on one line and use  it  on
       the next.

       Stu  uses  the  -e  option  when calling the shell; this means that any
       failing command will make the whole target fail.

       The standard input is redirected from /dev/null,  except  when  an  ex‐
       plicit  input  redirection is specified using '<'.  Thus, commands exe‐
       cuted from within Stu cannot read from standard input, except when  the
       -i option is used.  Stu starts each job in its own process group, whose
       process group ID is equal to its process ID.  This allows Stu  to  kill
       all  (direct and indirect) child processes of jobs, by using kill(2) to
       terminate all processes in the corresponding process group.

       When the command of a file is replaced by a semicolon, this means  that
       the file is always built together with its dependencies:

           TARGET [ : DEPENDENCY ... ] ;

       In  this  example, the file TARGET is assumed to be up to date whenever
       all dependencies are up to date.  This can be used when two  files  are
       built  by  a  single command.  As a special case, writing the name of a
       file followed by semicolon tells Stu that the file must  always  exist,
       and  is  always  up to date;  Stu will then report an error if the file
       does not exist:

           TARGET ;

       For a transient, the same syntax is used as for a file:

           @TARGET [ : DEPENDENCY ... ] { COMMAND }
           @TARGET [ : DEPENDENCY ... ] ;

       If a transient target includes a command, Stu will have no way  of  re‐
       membering  that  the command was executed, and the command will be exe‐
       cuted again on the next invocation of Stu, even if the previous invoca‐
       tion  was  successful.   Therefore, commands for transient targets will
       typically output build progress information, or perform actions that do
       not  fit  well the build system paradigm, such as removing or deploying
       built files.

       Rules can have multiple targets, in which case the command  must  build
       all  the  targets that are files.  If one of the targets is a transient
       target, this effectively creates an alias for the file targets.

           TARGET... [ : DEPENDENCY ... ] { COMMAND }
           TARGET... [ : DEPENDENCY ... ] ;

       The operator '>' can be used in front of the target  name  to  indicate
       that  the  output  of  the command should be redirected into the target
       file.  As an example, the following rule  creates  the  file  'HEADERS'
       containing the output of the given 'echo' command:

           >HEADERS { echo *.h }

       For  a file target, content can be specified directly using the '=' op‐
       erator:

           TARGET = { CONTENT ... }

       The content is stripped of empty lines and common whitespace at the be‐
       ginning of lines, and written into the file.

       Using  the  equal  sign with a file name creates a copy rule, i.e., the
       given file is copied with the 'cp' command:

           TARGET = [ -p | -o ] SOURCE;

       By default, Stu will use '/bin/cp' to perform the copy.   This  can  be
       changed  by  setting  the  variable $STU_CP.  If source ends in a slash
       (outside of any parameter value), then Stu will look for  a  file  with
       the same basename as TARGET in the directory SOURCE.  If the persistent
       flag -p is used, the timestamp of the source file is not verified, only
       its  existence.  If the optional flag -o is used, it is not an error if
       the target exists and not the source:  in that case the target is  con‐
       sidered up to date.  Both flags must not be used simultaenously.

       A dependency can be one of the following:

           NAME    A file dependency

       The  target depends on the file with the name NAME.  Stu will make sure
       that the file NAME is up to date before the target itself can be up  to
       date.

           @NAME   A transient dependency

       A  transient  target.   They represent a distinct namespace from files,
       and thus their command do not create files.

           -p NAME   A persistent dependency

       Stu will only check whether the dependency exists, but not its  modifi‐
       cation  time.   This is mostly useful for directories, as the modifica‐
       tion time of directories is updated whenever files are added or removed
       in the directory.

           -o NAME   An optional dependency

       Optional dependencies are never built if they don't exist.  If they ex‐
       ist, they are treated like normal dependencies and their date is  taken
       into account for determining whether the target has to be rebuilt.

       A  dependency cannot be declared as persistent and optional at the same
       time, as that would imply that its command is never executed.

           -t NAME   A trivial dependency

       A trivial dependency will never cause the target to be  rebuilt.   How‐
       ever, if the target is rebuilt for another reason, then the trivial de‐
       pendency will be rebuilt itself.  This is mostly useful for  configura‐
       tion  files  that  are  generated  automatically, including the case of
       files containing the flags used to invoke compilers and other programs.

           '[' ['-n' | '-0' | '-C'] NAME ']'  A dynamic dependency

       Stu will ensure the file named NAME exists, and then parse it  as  con‐
       taining  further  dependencies of the target.  The fact that NAME needs
       to be rebuild does not imply that the target has to  be  rebuilt.   The
       flag  -n makes Stu interpret the content of the file as a newline-sepa‐
       rated list of filenames.  Analogously, the -0 flag can be used when the
       file  contains  \0-separated  filenames,  or when the file contains the
       name of exactly one file.  If -C or no flag is used, the file is parsed
       in full Stu syntax.

           '[' @NAME ']'  A dynamic transient target

       Brackets  can also be used around a transient dependency name.  In that
       case, all dependencies of the given transient targets will  be  consid‐
       ered dynamic dependencies.

           $[NAME] A variable dependency

       The  file NAME is ensured to be up to date, and the content of the file
       NAME is used as the value of the variable $NAME when the target's  com‐
       mand is executed.

           <NAME An input dependency

       The  dependency  is a file which will be used as standard input for the
       command.

           ( ... )

       Groups of dependencies can be enclosed in parentheses.  Parentheses may
       not  contain  variable  dependencies (i.e., something like The flags -p
       and -o can be applied to a group of dependencies given in parentheses:

           -p ( ... )
           -o ( ... )

       The flags -p and -o can be applied to dynamic dependencies:

           -p [ ... ]
           -o [ ... ]

       in which case all resulting dynamic dependencies will be flagged as op‐
       tional or persistent.

       Both parentheses and brackets may be nested:

           ((A)) # Equivalent to A
           [[A]] # Read out dependencies from all files given in the file 'A'.

CONCATENATION
       In  certain  circumstances,  two dependencies that are not separated by
       spaces are said to be concatenated.  Concatenation takes place  in  the
       following cases:

           A( A[ )A )( )[ ]A ]( ][

       In this list, 'A' stands for any literal name, including one containing
       parameters or quotes.

       If two dependencies are concatenated, their concatenation is  taken  as
       the dependency.  Effectively this considers each side of the concatena‐
       tion to be a list of names (after processing of dynamic  dependencies),
       and  replaces  the concatenation by the combination of all names in the
       left groups concatenated textually with items in the right group.

PARAMETERS
       Any file or transient target may include  parameters.   Parameters  are
       noted using the '$' character and are given a name.  The syntax for pa‐
       rameters is similar to that for variables in the shell.   If  the  sign
       '$'  is followed by '{', then everything up to the corresponding '}' is
       the parameter name.  Otherwise, all alphanumeric characters and  under‐
       scores '_' following will be taken as the parameter name:

           data/$name.png
           data/${name}_2.png

       Parameters cannot be contiguous.  I.e., there must always be at least a
       single character between two parameters.  (The reason is that otherwise
       it  would  be ambiguous how to match the two parameters.)  Names of pa‐
       rameters cannot be empty.  Thus,

           data/${part1}${part2}.png
           data/${}.png
           data/$

       are errors.

       Stu will match the pattern to any file or transient target it needs  to
       build.   Parameters can appear in dependencies and in commands any num‐
       ber of times (included not appearing in them).  In a target name, a pa‐
       rameter  can  only appear once.  The following rule uses the single pa‐
       rameter $name:

           list.$name:    data.$name ${name}.in
           {
               ./compute-list -n "$name"
           }

       A target name may match more than one rule.  If that is the  case,  Stu
       will  use the rule that dominates all other matching rules.  A rule (x)
       is defined to dominate another rule (y) for a given name if every char‐
       acter  in  the  name that is part of a matched parameter in rule (x) is
       also inside a matched parameter in rule (y), and at least one character
       of  the name is part of a matched parameter in rule (y) but not in rule
       (x).  It is an error when there is no single matching rule  that  domi‐
       nates all other matching rules.

       In  the following example, the first rule dominates the other rules for
       the file named 'a.b.c':

           a.$x.c: ... { ... }
           a.$x:   ... { ... }
           $x.c:   ... { ... }

       In the following example, no rule dominates the others for the filename
       'a.b.c', so Stu will report an error:

           $x.b.c: ... { ... }
           a.$x.c: ... { ... }
           a.b.$x: ... { ... }

CANONICALIZATION
       Stu  canonicalizes  names  of files and transients.  As an example, the
       filenames 'aaa//bbb' and 'aaa/bbb' are considered to  be  the  same  by
       Stu,  and  can  be used interchangingly.  Canonicalization concerns the
       use of '/' (the directory separator) and '.' (the  current  directory).
       The following rules are applied in order:

       (1)  All  instances of multiple slashes ('/') are collapsed to a single
       one, except when the name begins with exactly two slashes.   Then,  any
       ending slash is removed, except if the name is '/' or '//'.

       (2) If the name is '/.', it is changed to '/'.  If the name is './', it
       is changed to '.'.  If the name begins with './' followed by a  charac‐
       ter  that  is not part of a parameter, the './' is removed (the rule is
       applied repeatedly).  Any number of ending '/.' components are removed.
       Any number of '/./' is simplified to '/'.

       Canonicalization  does  not  involve any procedure that requires system
       calls to be performed.  Thus, symlinks are not resolved,  and  'aaa/..'
       is not simplified.  Likewise, '/..' is not simplified to '/'.

       The  canonicalization rules apply not only to file targets, but also to
       transient targets.  Thus, @aaa//bbb and @aaa/bbb refer to the same tar‐
       get.  It is thus strongly suggested to use transient targets in a fash‐
       ion that is consistent with the file system semantics of '/' and '.'.

       Canonicalization is applied in the following fashion:

       Phase 1:  When rules are parsed, canonicalization  is  applied  to  all
       target  names.  At this stage, parameters are not yet replaced by their
       values, and thus the '/' and '.' components in parameter values are not
       canonicalized in targets.

       Phase  2: Second, When a dependency is matched to a rule, canonicaliza‐
       tion is applied to the dependency name.  At this stage,  names  do  not
       contain  parameters and canonicalization is performed on the final file
       or transient name.

       Additionally, there are three special rules for canonicalization:

       (a) There is a special rule concerning  './':   When  a  target  to  be
       canonicalized  in  Phase 1 as described above starts with './' followed
       immediately by a parameter, then this parameter will only match strings
       that do not start with a slash.  The './' is still removed.  This makes
       it possible to distinguish files with relative paths  from  files  with
       absolute paths.  For instance, consider the following example:

           A: ./list.B  { ... }
           $path.B      { ... }
           ./$file      { ... }

       Here,  the dependency './list.B' will match the third rule only.  With‐
       out the special rule, the dependency would match both  the  second  and
       third rule, and produce an error, because none of the two dominates the
       other.

       (b) Another special rule concerns the root directory '/':  A pattern of
       the  form  $A/xxx where $A is a parameter and xxx any string (which may
       contain more parameters) will match the name '/xxx' by setting the  pa‐
       rameter $A to the value '/'.  This special rule corresponds to the fact
       that while the root directory is called '/', a file within it is called
       '/xxx' rather than '//xxx'.

       (c) If the target for a rule is '$x/AAA', where 'AAA' may contain other
       parameters, then a dependency of 'AAA' will match that rule with $x set
       to '.', as long as 'AAA' does not start with a slash.

DIRECTIVES
       Directives  in Stu are introduced by '%' and serve a similar purpose to
       the C preprocessor, i.e., they are  processed  before  the  actual  Stu
       script  is  parsed and interpreted.  (However, they are not used to im‐
       plement a macro system.)  The token '%' must be followed by the  direc‐
       tive  name.  There may be any amount of whitespace (including none) be‐
       tween '%' and the name of the directive.

       File inclusion is done using the '%include' directive.  This can be put
       at any place in the input file, and will temporarily continue tokeniza‐
       tion in another file.  The filename does not have to be quoted,  except
       if it contains special characters, just like any other filename in Stu.
       If a directory is given  after  include  (with  or  without  an  ending
       slash), the file 'main.stu' within that directory is read.

           % include a.stu
           % include "b.stu"
           % include 'c.stu'
           % include data/

       To declare which version of Stu a script is written for, use the '%ver‐
       sion' directive:

           % version 2.3
           % version 2.3.4

       Both variants will allow the script to be executed only with a  version
       of  Stu  of  the  correct major version number (2 in this example), and
       whose minor version (and patch level) have at least the  given  values.
       There  may  be multiple '%version' directives; each one is then checked
       separately.  In particular, it is possible to place a version directive
       in  each source file.  This treatment of version numbers follows seman‐
       tic versionning (semver.org).  The version directive will  not  prevent
       usage of Stu features that were not present in the specified version.

TOKENIZATION
       Unquoted filenames in Stu may contain the following ASCII characters:

           [a-z] [A-Z] [0-9] _ ^ ` + - . ~ /

       and  all  non-ASCII  characters.  Filenames containing other characters
       must be quoted by either single or double quotes,  or  by  using  back‐
       slashes.   The characters -, + and ~ are not allowed as the first char‐
       acter of a name if they are not quoted.

       The following characters have special meaning in Stu and cannot be used
       in unquoted filenames:

           #     Comment (until the end of the line)
           %     Directive (followed by directive name and arguments)
           \     Escape for characters and to ignore newlines
           '     Quote, without escape sequences
           "     Quote, with escape sequences
           :     Separator for rule definition
           ;     In rules without command, end of dependency declaration
           -     Prefix character for flag, followed by a single character
           $     Parameter
           @     Transient target marker
           >     Output redirection
           <     Input redirection
           =     Assignment rule; copy rule; named variable
           ( )   List
           [ ]   Dynamic dependency
           { }   Command

       Comments  introduced  by  '#'  go  until the end of the line.  Commands
       starting with '{' go until the matching '}', taking into account  shell
       syntax,  i.e.,  the  command itself may contain more braces.  All other
       characters are individual tokens and may or may not be  separated  from
       other tokens by whitespace.

       Quoting  in Stu is similar to quoting in the shell.  Quoted or unquoted
       names which are not separated by whitespace are interpreted as a single
       name.  Outside of quotes, the backslash can be used to escape any char‐
       acter.  Backslash-newline sequences are ignored.  All other  characters
       can  be preceded by a backslash to retain their literal meaning as part
       of a name.

       Single quotes may contain any character except single  quotes  and  the
       NUL  character  '\0'.   Backslashes  and newline characters always have
       their literal meaning inside single quotes.

       Inside double quotes, backslashes, double quotes and  the  dollar  sign
       must  be  escaped  by  a backslash.   Other C-like escape sequences are
       supported, too.  To be precise, the following escape sequences are pos‐
       sible:  \" \\ \$ \a \b \f \n \r \t \v.  Dollars in double quotes intro‐
       duce parameter names in the same way as outside quotes.  Double  quotes
       may  also contain unescaped newline characters.  The NUL character '\0'
       is not allowed inside double quotes.  There is no \0  escape  sequence,
       as names of files and transients cannot contain the NUL byte.

       Spacing  rules:   The lack of whitespace between tokens represents con‐
       catenation under certain conditions.  Specifically:  To separate depen‐
       dencies,  whitespace  must appear before opening parentheses and brack‐
       ets, and after closing parenthesis and brackets, when  the  parenthesis
       or bracket in question would otherwise be touching either a name token,
       or another parenthesis or bracket "from outside".  I.e., the  following
       combinations represent concatenation:

           )(  )[  ](  ][  )A  ]A  A(  A[

       In  this  list,  'A'  stands for any name, including quoted names using
       whitespace, except when this would create a new token,  which  is  only
       the case for name tokens.

       The following characters are reserved for future extension:

           * & | ! ? ,

SYNTAX
       The  syntax  of  a Stu script is given in the following Yacc-like nota‐
       tion.  This is the syntax after processing of directives, which are in‐
       troduced with '%'.

           rule_list:        rule*
           rule:              ('@'  NAME  | ['>'] NAME)+ [':' expression_list]
       ('{' COMMAND '}' | ';')
                             NAME '=' '{' CONTENT '}'
                             NAME '=' ('-p' | '-o')* NAME ';'
           expression_list:  expression* {1}
           expression:       unit_expression* {2}
                             flag expression
                             variable_dep
           unit_expression:  '(' expression_list ')'
                             '[' expression_list ']'
                             redirect_dep
           redirect_dep:     ['<'] bare_dep
           bare_dep:         ['@'] NAME
           variable_dep:     '$' '[' flag* ['<'] NAME ']'
           flag:             '-p' | '-o' | '-t' | '-n' | '-0'

       {1} with intervening whitespace {2} without intervening whitespace

       Stu scripts read via the  -f  option  or  as  the  default  Stu  script
       (main.stu),  as  well  as  the argument to the -F option must contain a
       'rule_list'.  A file included by brackets (a  dynamic  dependency)  and
       arguments  to  the  -C option must contain an 'expression_list'.  Argu‐
       ments passed outside of options on the command  line  must  contain  an
       'expression_list',  but  a  simplified syntax is used in which only the
       charaters '[]-@' are recognized, and that only in positions where  they
       make  sense;  in all other cases, characters are interpreted as part of
       filenames -- this is also valid for whitespace.

SEMANTICS
       Cycles in the dependency graph are not allowed. As an example, the fol‐
       lowing results in an error:

           A:  B { ... }
           B:  A { ... }

       Cycles  are considered at the rule level, i.e., cycles such as the fol‐
       lowing are also flagged as an error, even though there is no  cycle  on
       the  filename  level.   In the following example, it is not possible to
       build the file 'a.gz.gz' from the file 'a', even though  it  would  not
       result  in  a  cycle, but since both files 'a.gz' and 'a.gz.gz' use the
       same parametrized rule, this is not allowed:

           $name.gz:  $name { gzip -k -- "$name" ; }

       Cycles are possible in dynamic dependencies, where they are allowed and
       ignored.  For instance, the following examples will correctly build the
       file 'A', after having built 'B' and 'C':

           A:  [B] { echo CORRECT >A ; }
           B:  { echo [C] >B ; }
           C:  { echo [B] >C ; }

       Symlinks are treated transparently by Stu.  In other  words,  Stu  will
       always  consider  the  timestamp of the linked-to file.  A symlink to a
       non-existing file will be treated as a non-existing file.

       Stu uses job control:  Each job is put into its own process group.  All
       jobs  are  put  into the background, except when the option -i is used.
       When -i is not used, the standard input of all jobs is redirected  from
       /dev/null.

       If  a  command  fails, Stu will remove any of its target files, if they
       have been already touched by the command.  If the failing  command  did
       not  touch  a  target  file,  that existing target file is not removed.
       This behavior is necessary to avoid the case that a commands  partially
       creates  a target file, then fails, and then a subsequent invocation of
       Stu sees the new file and considers it as up to date,  even  though  it
       was  only partially created.  Thus, commands in Stu do not need to make
       sure they delete any output files when they  fail.   This  behavior  is
       equivalent to that in Make.

EXIT STATUS
       0      Success.   Everything  was built successfully, or was already up
              to date.

       1      Build error.   This indicates errors in the commands invoked and
              files read by Stu.  Example:  a child process produced an error,
              or a dependency was not found and no  rule  was  given  for  it.
              When  using  the  -q option, the exit status is 1 when the given
              targets are not up to date.

       2      Logical error.  This indicates errors in the usage of Stu.   Ex‐
              amples  are  syntax  errors in Stu scripts, cycles in the depen‐
              dency graph and certain erroneous options on the command line.

       3      Both build and logical errors were encountered (when  using  the
              -k option).

       4      Fatal  error.   An  error occurred that made Stu abort execution
              immediately, regardless of whether the -k option was used.  This
              includes  system  errors  from which Stu cannot recover (such as
              out-of-memory conditions), as well as errors on the Stu  command
              line that make Stu fail immediately.

ENVIRONMENT
       STU_CP If  set,  Stu calls the 'cp' program from the given location in‐
              stead of '/bin/cp'.  The given version of 'cp' must support  the
              syntax 'cp -- "$fileA" "$fileB"'.

       STU_OPTIONS
              Contains  options  to  be set on every run of Stu.  Only the op‐
              tions EQswxyYz can be set this way.  The variable should contain
              only  these characters, dashes, and whitespace; other characters
              produce an error.  Options passed on the command line apply  af‐
              ter those passed using this variable.

       STU_SHELL
              If  set,  Stu calls the shell from the given location instead of
              '/bin/sh'.  The given shell must support the -e and -c  options.
              This  is mainly useful on systems where '/bin/sh' is not a POSIX
              shell.  Stu ignores the $SHELL variable, like Make does, as that
              variable is only intended to set the user's interactive shell.

       STU_STATUS
              Stu  sets  this variable to '1' in all child processes. In order
              to avoid recursive invocation of Stu, Stu will fail with a fatal
              error  (exit  status  4) on startup when the variable is set. To
              circumvent this, unset the variable.  Recursive Stu is as  harm‐
              ful as recursive Make.

       TERM   Used  to  determine  whether to use color output.  This variable
              must be set to a value different from 'dumb', and isatty(3) must
              return  1 for color to be enabled.  (Alternatively, color can be
              controlled by the -y and -Y options.)

SIGNALS
       SIGUSR1
              When received, Stu will output a list of currently running  jobs
              on  standard  output, and statistics about runtime, in a similar
              way to the -z option.  The reported runtimes include  only  jobs
              that  have  already  terminated,  and  exclude currently running
              jobs.  Multiple SIGUSR1 signals sent in rapid succession may re‐
              sult in output only printed once.

CONFORMING TO
       The  Stu  language  is  unique to this implementation, and the man page
       serves as the reference for its syntax.

       Stu follows Semantic Versioning (semver.org).  The major version number
       is  increased  when  backward-incompatible changes are made.  The minor
       version number is increased when features are added. The patch level is
       increased for other changes.

EXAMPLES
       The basic example of a rule in Stu is:

           program:    program.c config.h
           {
               cc -c program.c -o program
           }

       The  following  declaration tells Stu that the file 'config.h' must ex‐
       ist, and will allow Stu to give more meaningful error messages  if  the
       file is not found.

           config.h;

       Input  and output redirection can be used to write commands that invoke
       a filter such as sed, awk or tr.  The following example will build  the
       file 'A' containing the string 'HELLO':

           >A: <B { tr a-z A-Z ; }
           B = { hello }

       Variable dependencies may be included indirectly through transient tar‐
       gets without commands, and through dynamic dependencies.  In  the  fol‐
       lowing  example, the variable $V will be passed through to the commands
       for the targets A and B:

           V: { echo Hello >V ; }
           @x: $[V];
           y: { echo '$[V]' >y ; }
           A: @x { echo $V >A ; }
           B: [y] { echo $V >B ; }

       Trivial dependencies are often combined with variable  dependencies  to
       implement  flags, for instance to a compiler, as in the following exam‐
       ple. This will make sure that a change in the file 'VERSION'  will  not
       lead  to a recompilation of the program, but if 'program.c' is modified
       and 'program' is rebuilt, then 'CFLAGS' will also be rebuilt.

           VERSION; # Contains the version number; updated by hand
           >CFLAGS: $[VERSION] { echo -g -Wall -D VERSION=$VERSION ; }
           program:  program.c $[-t CFLAGS] { gcc $CFLAGS program.c -o program
       ; }

       Copy  rules  are  often used to copy a file from another directory into
       the current directory.  If both files have the same name, the  name  of
       the source file can be omitted.

           #  Copy  the file bsd/config.h to the current directory.  The slash
       at
           # the end of the directory name is not necessary, but provides a
           # useful hint to the reader.
           config.h = bsd/;

       Optional copy rules can be used in projects in which certain files will
       be available for some developers, but not others:

           # The file 'config.h' is delivered with this project.  For users
           # having the /usr/share/project/ directory, the file will always be
           # updated from there by Stu.  For users who don't, the file
           # delivered with the project is always used.
           config.h = -o /usr/share/project/;

       Parentheses  can  be  used  in a similar way to braces in the shell, to
       construct a list of filenames following a pattern:

           @headers:   (config data list).h;

       This will make @headers depend  on  the  files  config.h,  data.h,  and
       list.h.  This can be combined with brackets in the following way:

           @headers:   [NAMES].h;

       The  -C  option allows to pass any dependency in Stu syntax, and there‐
       fore can be used in some advanced use cases:

           stu -C '-o X' # Re-build file 'X' only if it already exists
           stu -C '[X]' # Build all files given in file 'X'

       To check whether Stu is compatible with a particular version of the Stu
       syntax:

           # Make sure Stu is compatible with the given version
           if stu -s -C '%version 2.7' ; then
               echo "Your Stu is compatible with version 2.7"
           fi

       The -F option allows to define rules on the command line, e.g.:

           # Same as GNU's 'cp -u A B'
           stu -F 'B=A;'

       You can also use -F to use Stu as a replacement for 'test':

           # Check that the file 'A' exists; similar to [ -e A ]
           if stu -c A ; then
               echo "The file 'A' exists"
           fi

           # The same, but works also when there is a file 'main.stu' present
           # that should be ignored
           if stu -F 'A;' ...

       You can use Stu to just execute something, like a poor man's shell:

           stu -F '@main{ echo Hello World }'

       of course, you can also type that directly or use 'sh -c', etc.

       Using  the  -i option, Stu commands can read from their standard input.
       For instance, the following will read a line from the user and use  it.
       This cannot be used in conjunction with the -j option (except for -j1).

           >config.h: {
               echo >&2 "Please enter the value of COUNT"
               read -r count
               echo "#define COUNT $count"
           }

BUGS
       There is no way to change the used shell from within a Stu script.  The
       only way to do it is with the $STU_SHELL environment variable.

       The argument to the -j option (number of jobs to run  in  parallel)  is
       mandatory,  as  opposed  to the behavior of GNU Make, where no argument
       means to run as many jobs in parallel as possible.

       For arguments passed on the command line outside of  options,  brackets
       []  can  be  used  for dynamic dependencies, but parentheses () cannot.
       Instead, the shell's braces {} must be used, or the option -C.

       Rule-level recursion is not allowed.  This excludes a recursive parsing
       of  C-like dependencies.  Rule-level recursion would be easy to enable,
       but would open up problems related to infinite loops, which  would  re‐
       quire Stu to have a maximal recursion depth.

       When  a  command fails and its target is a directory, Stu cannot remove
       the directory as it does for regular files.

       Changing a command within a Stu script will not make the target  to  be
       rebuilt.   This  can  be  seen  as  both a feature or a bug.  Also, all
       changes in a file will lead to rebuilds of other  files,  even  if  the
       changes are trivial, e.g., when only whitespace was changed in C source
       code.  Furthermore, touching a file without changing the contents  will
       also  lead  to  a rebuild, although it is not needed.  Both limitations
       could be removed by using fingerprints instead of modification times.

       All timestamps have only one-second resolution, except when the  Linux-
       only USE_MTIM option is set on compilation.  (Which it is by default on
       Linux.)

       Using optional dependencies may make a second  invocation  of  Stu  not
       output  'Targets  are  up to date', as the optional dependency may have
       been created by subsequent targets.

       Commands enclosed in braces { ... } are parsed using shell  syntax,  up
       to  one  exception:  a closing brace is detected everywhere in unqotued
       environments, not only when standing alone as the first word of a  com‐
       mand.   E.g.,  the  command  { echo Hello } is a valid command for Stu,
       while it would be an error for the shell, as the closing } would be in‐
       terpreted as a second argument to 'echo'.

       In error messages, the column numbers are based on the number of bytes,
       and do not take into account multibyte characters or combining  charac‐
       ters,  etc.   Thus, the placement of error messages may be wrong within
       the line in certain editors or GUIs.

       When an error occurs with a concatenated file or  transient  name,  Stu
       only outputs the location of the name as a whole, and does not point to
       the source of the individual components of the concatenation.  This can
       lead to confusing error backtraces.

AUTHOR
       Written  by Jérôme Kunegis <kunegis@gmail.com> at the University of Na‐
       mur, Belgium, as well as at the University of Koblenz-Landau,  Germany,
       with  contributions  and  help by Jun Sun, Aaron McDaid, Heinrich Hart‐
       mann, Holger Heinz, and others.   Our  thanks  go  to  the  many  early
       testers  and  users of Stu, who have helped us fix many bugs, and iden‐
       tify many different use cases and usage patterns.

SEE ALSO
       cook(1), gpl(7), make(1), sh(1)

stu-2.7.116                      December 2024                          STU(1)