You must create a file called "Tupfile" anywhere in the tup hierarchy that you want to create an output
file based on the input files. The input files can be anywhere else in the tup hierarchy, but the output
file(s) must be written in the same directory as the Tupfile.
:[foreach][inputs][|order-onlyinputs]|>command|>[outputs][|extraoutputs][<group>][{bin}]
The :-rules are the primary means of creating commands, and are denoted by the fact that the ':'
character appears in the first column of the Tupfile. The syntax is supposed to look somewhat like
a pipeline, in that the input files on the left go into the command in the middle, and the output
files come out on the right.
foreach
This is either the actual string "foreach", or it is empty. The distinction is in how many
commands are generated when there are multiple input files. If "foreach" is specified, one
command is created for each file in the inputs section. If it is not specified, one command
is created containing all of the files in the inputs section. For example, the following
Tupfiles are equivalent:
# Tupfile 1
: foo.c |> gcc -c foo.c -o foo.o |> foo.o
: bar.c |> gcc -c bar.c -o bar.o |> bar.o
# Tupfile 2
: foreach foo.c bar.c |> gcc -c %f -o %o |> %B.o
Additionally, using "foreach" allows the use of the "%e" flag (see below).
inputs The input files for the command. An input file can be anywhere in the tup hierarchy, and is
specified relative to the current directory. Input files affect the %-flags (see below).
Wildcarding is supported within a directory by using the SQLite glob function. The special
glob characters are '*', '?', and '[]'. For example, "*.c" would match any .c file, "fo?.c"
would match any 3-character .c file that has 'f' and 'o' as the first two characters, and
"fo[xyz].c" would match fox.c, foy.c, and foz.c. Globbing does not match directories, so
"src/*.c" will work, but "*/*.c" will not.
Any inputs starting with '^' are Perl-compatible regular expressions used to exclude files
that were matched in a previous glob. For example, you could compile all *.c files except
main.c with the following fragment:
: foreach *.c ^main.c |> ... |>
These input exclusions are handled at parser time, and are distinct from the dependency
exclusions in the outputs section.
order-onlyinputs
These are also used as inputs for the command, but will not appear in any of the %-flags
except %i. They are separated from regular inputs by use of the '|' character. In effect,
these can be used to specify additional inputs to a command that shouldn't appear on the
command line. Globbing is supported as in the inputs section. For example, one use for them
is to specify auto-generated header dependencies:
: |> echo "#define FOO 3" > %o |> foo.h
: foreach foo.c bar.c | foo.h |> gcc -c %f -o %o |> %B.o
This will add the foo.h dependency to the gcc commands for foo.c and bar.c, so tup will
know to generate the header before trying to compile. The foreach command will iterate over
the regular inputs (here, foo.c and bar.c), not the order-only inputs (foo.h). If you
forget to add such a dependency, tup will report an error when the command is executed.
Note that the foo.h dependency is only listed here because it is created by another command
-- normal headers do not need to be specified.
command
The command string that will be passed to the system(3) call by tup. This command is
allowed to read from any file specified as an input or order-only input, as well as any
other file in the tup hierarchy that is not the output of another command. In other words,
a command cannot read from another command's output unless it is specified as an input.
This restriction is what allows tup to be parallel safe. Additionally, the command must
write to all of the output files specified by the "outputs" section, if any.
When executed, the command's file accesses are monitored by tup to ensure that they conform
to these rules. Any files opened for reading that were generated from another command but
not specified as inputs are reported as errors. Similarly, any files opened for writing
that are not specified as outputs are reported as errors. All files opened for reading are
recorded as dependencies to the command. If any of these files change, tup will re-execute
the command during the next update. Note that if an input listed in the Tupfile changes, it
does not necessarily cause the command to re-execute, unless the command actually read from
that input during the prior execution. Inputs listed in the Tupfile only enforce ordering
among the commands, while file accesses during execution determine when commands are re-
executed.
A command string can begin with the special sequence ^ TEXT^, which will tell tup to only
print "TEXT" instead of the whole command string when the command is being executed. This
saves the effort of using echo to pretty-print a long command. The short-display behavior
can be overridden by passing the --verbose flag to tup, which will cause tup to display the
actual command string instead of "TEXT". The space after the first '^' is significant. Any
characters immediately after the first '^' are treated as flags. See the ^-flags section
below for details. For example, this command will print "CC foo.c" when executing
system(gcc -c foo.c -o foo.o) :
: foo.c |> ^ CC %f^ gcc -c %f -o %o |> foo.o
A command string can also begin with the special character '!', in which case the !-macro
specified will be substituted in for the actual command. See the !-macro definition later.
Commands can also be blank, which is useful to put all the input files in a {bin} for a
later rule.
outputs
The outputs section specifies the files that will be written to by the command. Only one
command can write to a specific file, but a single command can output multiple files (such
as how a bison command will output both a .c and .h file). The output can use any %-flags
except %o. Once a file is specified in an output section, it is put into the tup database.
Any following rules can use that file as an input, even if it doesn't exist in the
filesystem yet.
Outputs starting with '^' are used to ignore dependencies on files. These exclusions are
Perl-compatible regular expressions that are stored in the database. Any files that are
read or written to when the sub-process executes that matches these patterns are ignored by
tup. For example, if your compiler writes to a 'license_file.txt', you could instruct tup
to ignore dependency errors on this file like so:
: foreach *.c |> ... |> %B.o ^license_file.txt
Note that this also instructs tup to ignore input dependencies on the file. If you wish to
merely skip files in a glob, see the similar '^' syntax in the inputs section.
An exclusion cannot be used to match file generated by the same rule (ie: one listed as an
output in the command). Doing so will result in an "Unable to exclude a generated file"
error.
You should only ignore dependencies with extreme caution. It is trivial to cause tup to
fail to update when it should have because it's been instructed to ignore dependencies.
extra-outputs
The extra-outputs section is similar to the order-only inputs section. It is separated from
the regular outputs by the '|' character. The extra-outputs behave exactly as regular
outputs, except they do not appear in the %o flag. These can be used if a command generates
files whose names do not actually appear in the command line. If there is exactly one
output specified by the rule, the extra-outputs section can use the %O flag to represent
the basename of the output. This can be useful in extra-outputs for !-macros.
<group>
Output files can be grouped into global groups by specifying a <group> after the outputs
but before a bin. Groups allow for order-only dependencies between folders. Note that
groups are directory specific, however, so when referring to a group you must specify the
path to where it is assigned. For example, if a main project depends on the output from
several submodules you can structure Tup like so to make sure the submodules are built
before the main project:
#./submodules/sm1/Tupfile
: foo.c |> gcc -c %f -o %o |> %B.o ../<submodgroup>
#./submodules/sm2/Tupfile
: bar.c |> gcc -c %f -o %o |> %B.o ../<submodgroup>
#./project/Tupfile
: baz.c | ../submodules/<submodgroup> |> gcc -c %f -o %o |> %B.o
Notice how groups are directory specific and the path is specified outside of the <>. By
specifying the <submodgroup> as an order-only input Tup will build the submodules before
attempting to build the entire project.
{bin} Outputs can be grouped into a bin using the "{bin}" syntax. A later rule can use "{bin}" as
an input to use all of the files in that bin. For example, the foreach rule will put each
.o file in the objs bin, which is used as an input in the linker rule:
: foreach *.c |> gcc -c %f -o %o |> %B.o {objs}
: {objs} |> gcc %f -o %o |> program
In this case one could use *.o as the input instead, but sometimes it is useful to separate
outputs into groups even though they have the same extension (such as if one directory
creates multiple binaries, using *.o wouldn't be correct). If a {bin} is specified in the
output section of multiple rules, the bin will be the union of all the outputs. You can't
remove things from a bin, and the bin disappears after the current Tupfile is parsed.
^-flags
In a command string that uses the ^ TEXT^ sequence, flag characters can be placed immediately
after the ^ until the first space character or closing caret. For example:
: foo.c |> ^c CC %f^ gcc --coverage %f -o %o |> foo | foo.gcno
: bar.c |> ^c^ gcc --coverage %f -o %o |> bar | bar.gcno
In the foo.c case, the command requires namespaces (or suid) and will display "CC foo.c". In the
bar.c case, the command requires namespaces (or suid) and the "gcc --coverage bar.c -o bar" string
is displayed. These are the supported flag characters:
b The 'b' flag causes the command to be run via "/usr/bin/env bash -e -o pipefail -c
<command>" instead of the default "/bin/sh -e -c <command>". In addition to allowing bash
extensions in the :-rule, "-o pipefail" dictates that "the return value of a pipeline is
the value of the last (rightmost) command to exit with a non-zero status, or zero if all
commands in the pipeline exit successfully."
c The 'c' flag causes the command to fail if tup does not support user namespaces (on Linux)
or is not suid root. In these cases, tup runs in a degraded mode where the fake working
directories are visible in the sub-processes, and some dependencies may be missed. If these
degraded behaviors will break a particular command in your build, add the 'c' flag so that
users know they need to add the suid bit or upgrade their kernel. This flag is ignored on
Windows.
j The 'j' flag marks the command for export in the 'tup compiledb' command. If you are
interested in using compile_commands.json, annotate the commands that you want to export
with ^j and then run 'tup compiledb'. See the compiledb command for more details.
o The 'o' flag causes the command to compare the new outputs against the outputs from the
previous run. Any outputs that are the same will not cause dependent commands in the DAG to
be executed. For example, adding this flag to a compilation command will skip the linking
step if the object file is the same from the last time it ran. The 'o' flag is incompatible
with the 't' flag.
s The 's' flag disables buffering of stdout/stderr for the subprocesses and enables
"streaming mode". When streaming, stdout/stderr are inherited from the tup process, so
messages would typically be displayed on the terminal while the subprocess is running in
whatever order they are generated. Note that processes with 's' enabled may display
messages interleaved with each other, as well as with tup's progress bar or other tup
messages. This flag may be useful for long-running processes where you wish to see the
output as it occurs, though it can make for confusing logs if it is used for many noisy
commands that may run in parallel.
By default, tup will buffer a command's messages (for example, compiler warning messages)
and display them under the banner for the command after it completes. Messages from
separate commands are therefore always distinct and associated with the command that
created them.
t The 't' flag causes the command's outputs to be transient. The outputs may be used as
inputs to other commands, but after all dependent commands are executed, the transient
outputs will be deleted from the filesystem. This can be used to save space if there are
many stages of processing that each produce large outputs, but only the final output needs
to be kept. The 't' flag is incompatible with the 'o' flag.
An example where the 't' flag can make sense in a build pipeline is if there are large
assets that go through multiple stages of processing. For example, a large audio or video
file that has stages of effects applied, each as a separate step in the Tupfile.
In contrast, the 't' flag does *not* make sense for object files in a C program, even
though those could theoretically be deleted after the final executable is linked. If the
object files were marked transient in this case, a change to any of the input C files would
require *all* object files to be rebuilt in order to produce the executable, instead of
only the single file that was changed.
%-flags
Within a command string or output string, the following %-flags may also be used to substitute
values from the inputs or outputs. In general, %-flags expand to all filenames in a list. For
example, %o expands to all output files. To refer to a single file, you can use %1o, %2o, etc to
refer to the first or second (and so on) filename in the list.
%% Expands to a single "%" character in the command string. This should be used when you want
the percent character to be interpreted by the command itself rather than by tup's parser.
%f The filenames from the "inputs" section. This includes the path and extension. This is most
useful in a command, since it lists each input file name with the path relative to the
current directory. For example, "src/foo.c" would be copied exactly as "src/foo.c".
Individual files can be referenced with %1f, %2f, etc.
%i The filenames from the "order-only inputs" section. This includes the path and extension.
Usually order-only inputs are used for filenames that you don't want to appear in the
command-line, but if you need to refer to them, you can use %i. Individual files can be
referenced with %1i, %2i, etc.
%b Like %f, but is just the basename of the file. The directory part is stripped off. For
example, "src/foo.c" would become "foo.c". Individual files can be referenced with %1b,
%2b, etc.
%B Like %b, but strips the extension. This is most useful in converting an input file into an
output file of the same name but with a different extension, since the output file needs to
be in the same directory. For example, "src/foo.c" would become "foo". Individual files can
be referenced with %1B, %2B, etc.
%e The file extension of the current file when used in a foreach rule. This can be used for
variables that can have different values based on the suffix of the file. For example, you
could set certain flags for assembly (.S) files that are different from .c files, and then
use a construct like $(CFLAGS_%e) to reference the CFLAGS_S or CFLAGS_c variable depending
on what type of file is being compiled. For example, "src/foo.c" would become "c", while
"src/foo.S" would become "S"
%o The name of the output file(s). It is useful in a command so that the filename passed to a
command will always match what tup thinks the output is. This only works in the "command"
section, not in the "outputs" section. Individual files can be referenced with %1o, %2o,
etc.
%O The name of the output file without the extension. This only works in the extra-outputs
section if there is exactly one output file specified. A use-case for this is if you have a
!-macro that generates files not specified on the command line, but are based off of the
output that is named. For example, if a linker creates a map file by taking the specified
output "foo.so", removing the ".so" and adding ".map", then you may want a !-macro like so:
!ldmap = |> ld ... -o %o |> | %O.map
: foo1.o foo2.o |> !ldmap |> foo.so
%d The name of the lowest level of the directory. For example, in foo/bar/Tupfile, this would
be the string "bar". One case where this can be useful is in naming libraries based on the
directory they are in, such as with the following !-macro:
!ar = |> ar crs %o %f |> lib%d.a
Using this macro in foo/bar/Tupfile would then create foo/bar/libbar.a
%g The string that a glob operator matched. For example with the files a_text.txt and
b_text.txt, the rule:
: foreach *_text.txt |> foo %f |> %g_binary.bin
will output the filenames a_binary.bin and b_binary.bin. Only the first glob expanded will
be substituted in for %g. %g is only valid when there is a single input file or foreach is
used.
%<group>
All of the files in "group". For example:
#./submodules/sm1/Tupfile
: foo.c |> gcc -c %f -o %o |> %B.o ../<submodgroup>
#./submodules/sm2/Tupfile
: bar.c |> gcc -c %f -o %o |> %B.o ../<submodgroup>
#./project/Tupfile
: ../submodules/<submodgroup> |> echo '%f' > %o |> submodules_f.txt
: ../submodules/<submodgroup> |> echo '%<submodgroup>' > %o |> submodules_group.txt
will produce "../submodules/<submodgroup>" in submodules_f.txt, but
"../submodules/sm1/foo.o ../submodules/sm2/bar.o" in submodules_group.txt. If the input
contains multiple groups with the same name but different directories, %<group> will be
expanded to all of the files in each listed group.
var=valuevar:=value
Set the $-variable "var" to the value on the right-hand side. Both forms are the same, and are
allowed to more easily support converting old Makefiles. The $-variable "var" can later be
referenced by using "$(var)". Variables referenced here are always expanded immediately. As such,
setting a variable to have a %-flag does not make sense, because a %-flag is only valid in a
:-rule. The syntax $(var_%e) is allowed in a :-rule. Variable references do not nest, so something
like $(var1_$(var2)) does not make sense. You also cannot pass variable definitions in the command
line or through the environment. Any reference to a variable that has not had its value set
returns an empty string.
CFLAGS = -Dfoo
: bar.c |> cc $(CFLAGS) $(other) -o %o -c %f |> %B.o
will generate the command "cc -Dfoo -o bar.o -c bar.c" when run.
Any $-variable that begins with the string "CONFIG_" is automatically converted to the @-variable of the
same name minus the "CONFIG_" prefix. In other words, $(CONFIG_FOO) and @(FOO) are interchangeable.
Attempting to assign a value to a CONFIG_ variable in a Tupfile results in an error, since these can only
be set in the tup.config file.
Note that you may see a syntax using back-ticks when setting variables, such as:
CFLAGS += `pkg-config fuse3 --cflags`
Tup does not do any special processing for back-ticks, so the pkg-config command is not actually executed
when the variable is set in this example. Instead, this is passed verbatim to any place that uses it.
Therefore if a command later references $(CFLAGS), it will contain the string `pkg-config fuse3
--cflags`, so it will be parsed by the shell.
var+=value
Append "value" to the end of the current value of "var". If "var" has not been set, this is
equivalent to a regular '=' statement. If "var" already has a value, a space is appended to the
$-variable before the new value is appended.
$(TUP_CWD)[lua]tup.getcwd()
The special $-variable TUP_CWD is always set to the path relative to the Tupfile currently parsed.
It can change value when including a file in a different directory. For example, if you "include
../foo.tup", then TUP_CWD will be set to ".." when parsing foo.tup. This lets foo.tup specify
flags like "CFLAGS += -I$(TUP_CWD)", and CFLAGS will always have the -I directory where foo.tup is
located, no matter if it was included as "../foo.tup" or "../../foo.tup" or "subdir/foo.tup". For
an alternative to $(TUP_CWD) when referring to files, see the section on &-variables below.
$(TUP_VARIANTDIR)[lua]tup.getvariantdir()
Similar to $(TUP_CWD), $(TUP_VARIANTDIR) is set to be the path relative to the Tupfile currently
parsed, but points to the corresponding directory in the variant. As an example where this might
be useful, suppose your build generates common headers into a directory called "include/". A
Tuprules.tup file at the level of that directory could add -I$(TUP_VARIANTDIR) to a compiler flags
variable. If a variant is used, this will evaluate to a path like "../build/path/to/include",
where "build" is the name of the variant directory. If variants aren't used, TUP_VARIANTDIR is
equivalent to TUP_CWD.
$(TUP_VARIANT_OUTPUTDIR)[lua]tup.getvariantoutputdir()
$(TUP_VARIANT_OUTPUTDIR) always points to the output directory corresponding to the variant
currently being parsed. Unlike $(TUP_VARIANTDIR), it does not change when including another file
like Tuprules.tup or other partial *.tup files. Without variants, this always evaluates to the
string "." to point to the current directory.
No other special $-variables exist yet, but to be on the safe side you should assume that all variables
named TUP_* are reserved.
&var=file&var:=file&var+=file
Set the &-variable to refer to the given file or directory. The file must be a normal file, not a
generated file (an output from a :-rule). &-variables are used to refer to files in a similar way
as $(TUP_CWD), except that instead of storing the relative path to the file, &-variables store
tup's internal ID of the file. This means that the relative path to the file is determined when
the &-variable is used, rather than when the variable is assigned as is the case with $(TUP_CWD).
&-variables can only be used in the following locations: :-rule inputs, :-rule order-only inputs,
:-rule commands, include lines, and run-script lines, and they can later be referenced by using
"&(var)".
# Tuprules.tup
&libdir = src/lib
!cc = |> cc -I&(libdir) -c %f -o %o |> %B.o
# src/lib/Tupfile
: foreach *.c |> !cc |>
: *.o |> ar crs %o %f |> libstuff.a
# src/lib/test/Tupfile
: test_stuff.c |> !cc |>
: test_stuff.o &(libdir)/libstuff.a |> cc -o %o %f |> test_stuff
# src/Tupfile
: main.c |> !cc |> main.o
: main.o &(libdir)/libstuff.a |> cc -o %o %f |> main_app
will generate the following build.sh commands (via "tup generate build.sh"):
cd src/lib
cc -I. -c lib1.c -o lib1.o
cc -I. -c lib2.c -o lib2.o
ar crs libstuff.a lib1.o lib2.o
cd test
cc -I.. -c test_stuff.c -o test_stuff.o
cc -o test_stuff test_stuff.o ../libstuff.a
cd ../..
cc -Ilib -c main.c -o main.o
cc -o main_app main.o lib/libstuff.a
ifeq(lval,rval)
Evaluates the 'lval' and 'rval' parameters (ie: substitutes all $-variables and @-variables), and
does a string comparison to see if they match. If so, all lines between the 'ifeq' and following
'endif' statement are processed; otherwise, they are ignored. Note that no whitespace is pruned
for the values - all text between the '(' and ',' comprise 'lval', and all text between the ','
and ')' comprise 'rval'. This means that ifeq (foo, foo) is false, while ifeq (foo,foo) is true.
This is for compatibility with Makefile if statements.
ifeq (@(FOO),y)
CFLAGS += -DFOO
else
CFLAGS += -g
endif
ifneq(lval,rval)
Same as 'ifeq', but with the logic inverted.
ifdefVARIABLE
Tests of the @-variable named VARIABLE is defined at all in tup.config. If so, all lines between
the 'ifdef' and following 'endif' statement are processed; otherwise, they are ignored. For
example, suppose tup.config contains:
CONFIG_FOO=n
Then 'ifdef FOO' will evaluate to true. If tup.config doesn't exist, or does not set CONFIG_FOO in
any way, then 'ifdef FOO' will be false.
ifndefVARIABLE
Same as 'ifdef', but with the logic inverted.
else Toggles the true/false-ness of the previous if-statement.
endif Ends the previous ifeq/ifdef/ifndef. Note that only 8 levels of nesting if-statements is
supported.
error[message]
Causes tup to stop parsing and fail, printing message to the user as explanation.
!macro=[inputs]|[order-onlyinputs]|>command|>[outputs]
Set the !-macro to the given command string. This syntax is very similar to the :-rule, since a
!-macro is basically a macro for those rules. The !-macro is not expanded until it is used in the
command string of a :-rule. As such, the primary use of the !-macro is to have a place to store
command strings with %-flags that may be re-used. For example, we could have a !cc macro in a top-
level Tuprules.tup file like so:
!cc = |> ^ CC %f^ gcc -c %f -o %o |>
A Tupfile could then do as follows:
include_rules
: foreach *.c |> !cc |> %B.o
You will only want to specify the output parameter in either the !-macro or the :-rule that uses
it, but not both. If you specify any inputs in the !-macro, they would usually be order-only
inputs. For example, if you have a !cc rule where you are using a compiler that has been generated
by tup, you can list the compiler file in the order-only list of the !-macro. The compiler file
will then become an input dependency for any :-rule that uses the macro.
includefile
Reads the specified file and continues parsing almost as if that file was pasted inline in the
current Tupfile. Only regular files are allowed to be included -- attempting to include a
generated file is an error. Any include statements that occur in the included file will be parsed
relative to the included file's directory.
include_rules
Reads in Tuprules.tup files up the directory chain. The first Tuprules.tup file is read at the top
of the tup hierarchy, followed by the next subdirectory, and so on through to the Tuprules.tup
file in the current directory. In this way, the top-level Tuprules.tup file can specify general
variable settings, and subsequent subdirectories can override them with more specific settings.
You would generally specify include_rules as the first line in the Tupfile. The name is a bit of a
misnomer, since you would typically use Tuprules.tup to define variables rather than :-rules.
run./scriptargs
Runs an external script with the given arguments to generate :-rules. This is an advanced feature
that can be used when the standard Tupfile syntax is too simplistic for a complex program. The
script is expected to write the :-rules to stdout. No other Tupfile commands are allowed - for
example, the script cannot create $-variables or !-macros, but it can output :-rules that use
those features. As a simple example, consider if a command must be executed 5 times, but there are
no input files to use tup's foreach keyword. An external script called 'build.sh' could be written
as follows:
#! /bin/sh -e
for i in `seq 1 5`; do
echo ": |> echo $i > %o |> $i.txt"
done
A Tupfile can then be used to get these rules:
run ./build.sh
Tup will then treat this as if a Tupfile was written with 5 lines like so:
: |> echo 1 > %o |> 1.txt
: |> echo 2 > %o |> 2.txt
: |> echo 3 > %o |> 3.txt
: |> echo 4 > %o |> 4.txt
: |> echo 5 > %o |> 5.txt
Since the Tupfile-parsing stage is watched for dependencies, any files that this script accesses
within the tup hierarchy will cause the Tupfile to be re-parsed. There are some limitations,
however. First, the readdir() call is instrumented to return the list of files that would be
accessible at that time that the run-script starts executing. This means the files that you see in
'ls' on the command-line may be different from the files that your script sees when it is parsed.
Tup essentially pretends that the generated files don't exist until it parses a :-rule that lists
it as an output. Note that any :-rules executed by the run-script itself are not parsed until the
script executes successfully. Second, due to some structural limitations in tup, the script cannot
readdir() on any directory other than the directory of the Tupfile. In other words, a script can
do 'for i in *.c', but not 'for i in sub/*.c'. The '--debug-run' flag can be passed to 'tup' in
order to show the list of :-rules that tup receives from the script. Due to the readdir()
instrumentation, this may be different than the script's output when it is run manually from the
command-line.
preloaddirectory
By default, a run-script can only use a readdir() (ie: use a wild-card) on the current directory.
To specify a list of other allowable wild-card directories, use the preload keyword. For example,
if a run script needs to look at *.c and src/*.c, the src directory needs to be preloaded:
preload src
run ./build.sh *.c src/*.c
exportVARIABLE
The export directive adds the environment variable VARIABLE to the export list for future :-rules
and run-scripts. The value for the variable comes from tup's environment, not from the Tupfile
itself. Generally this means you will need to set the variable in your shell if you want to change
the value used by commands and scripts. By default only PATH is exported. Windows additionally
exports several variables suitable for building with the Visual Studio compiler suite. Tup will
check the exported environment variables to see if they have changed values between updates, and
re-execute any commands that that use those environment variables. Note that this means if PATH is
changed, all commands will run again. For example:
: |> command1 ... |>
export FOO
: |> command2 ... |>
Tup will save the current value of FOO and pass it to the environment when executing command2. If
FOO has a different value during the next update, then command2 will execute again with the new
value in the environment. In this example, command1 will not have FOO in its environment and will
not re-execute when its value changes.
Note that the FOO above is passed to the environment; it is not provided as an internal variable
within tup. Thus, given the following:
export FOO
: |> echo myFOO=$(FOO) envFOO=${FOO} > %o |> foo.txt
when run as "$ FOO=silly tup" would result in the contents of the foo.txt file being "myFOO=
envFOO=silly". If the "export FOO" was removed from the Tupfile, the contents of the file would be
"myFOO= envFOO=" because tup does not propagate environment variables unless they are explicitly
exported. This helps preserve repeatable and deterministic builds.
If you wish to export a variable to a specific value rather than get the value from the
environment, you can do that in your shell instead of through tup. For example, in Linux you can
do:
: |> FOO=value command ... |>
This usage will not create a dependency on the environment variable FOO, since it is controlled
through the Tupfile.
importVARIABLE[=default]
The import directive sets a variable inside the Tupfile that has the value of the environment
variable. If the environment variable is unset, the default value is used instead if provided.
This introduces a dependency from the environment variable to the Tupfile, so that if the
environment variable changes, the Tupfile is re-parsed. For example:
import CC=gcc
: foreach *.c |> $(CC) -c %f -o %o |> %B.o
This will compile all .c files with the compiler defined in the CC environment variable. If CC is
not set in the environment, it will use gcc as the default. On a subsequent build, running
'CC=clang tup' will re-parse this Tupfile and re-build all .c files with clang instead (since the
commandlines have changed).
Unlike 'export', the import command does not pass the variables to the sub-process's environment.
In the previous example, the CC environment variable is therefore not set in the subprocess,
unless 'export CC' was also in the Tupfile.
.gitignore
Tells tup to automatically generate a .gitignore file in the current directory which contains a
list of the output files that are generated by tup. This can be useful if you are using git, since
the set of files generated by tup matches exactly the set of files that you want git to ignore. If
you are using Tuprules.tup files, you may just want to specify .gitignore in the top-level
Tuprules.tup, and then have every other Tupfile use include_rules to pick up the .gitignore
definition. In this way you never have to maintain the .gitignore files manually. Note that you
may wish to ignore other files not created by tup, such as temporary files created by your editor.
In this case case you will want to setup a global gitignore file using a command like 'git config
--global core.excludesfile ~/.gitignore', and then setup ~/.gitignore with your personal list. For
other cases, you can also simply add any custom ignore rules above the "##### TUP GITIGNORE #####"
line.
# At the beginning of a line, a '#' character signifies a comment. A comment line is ignored by the
parser. The comment can have leading whitespaces that is also ignored. If there is any non-
whitespace before a '#' character, then the line is not a comment. It also means that if a
previous line ended with '\' (line wrap) then '#' is interpreted as a regular symbol.