Lua Parser

Introduction

Tup supports writing build definitions using Lua. Tup uses a modified Lua 5.3 parser that supports all standard Lua syntax, with the addition of a new += operator. The statement a += b is equivalent to a = tup_append_assignment(a, b) where tup_append_assignment is a Lua function that, by default, appends to tables or creates a new table of the two values if the left-hand is not already a table. Tup also defines the tostring(argument) operation on tables with no metatable as table.concat(argument, ' ').

File structure

For each directory Tup scans, Tup looks for Tupfile.lua, or, if not present, a Tupdefault.lua file in the current directory or any parent directory up to the Tup root.

If a Tupfile.lua or Tupdefault.lua is found, Tup creates a Lua state and runs any Tuprules.lua files in the current directory and all parent directories up to the Tup root, then runs the located Tupfile.lua or Tupdefault.lua.

Non-Lua Tupfiles can include Lua files, which are able to read non-Lua variables when run.

API

Only a subset of the standard Lua library is defined, in order to prevent untracked dependencies. The standard library methods are filtered as follows:

Tup-specific functions are provided in the tup table. In the following documentation, PROCESSING refers to the directory Tup is currently processing, and RUNNING refers to the directory of the build definition file Tup is currently running. When Tup enters Tupfile.lua, PROCESSING and RUNNING are the same. When running Tuprules.lua or an explicitly included file, PROCESSING AND RUNNING may be different.

tup.include(path)
Returns: none

Parses and runs the Lua file at path.

tup.definerule{inputs = {'', ...}, command = '', outputs = {'', ...}}
Returns: none

Defines a rule. See the Tup manual for more information on rules. command will be executed without any modifications, either directly or in a shell, in the directory PROCESSING. inputs and outputs are optional and are used to determine dependencies.

tup.frule{inputs = {'', ...}, command = '', outputs = {'', ...}}
Returns: table of strings

A wrapper for tup.definerule that performs substitutions on all parameters based on format patterns. Returns a table containing the filenames of all outputs.

If there is a single input, it can be specified as a string argument input, and a single output can be specified as string argument output. In addition to sequential, numerically indexed elements, input can contain a table at index 'extra_inputs', the elements of which are treated like normal inputs but are not used when substituting %f. Likewise, output can contain a table at index 'extra_outputs', the elements of which are treated like normal outputs but are not used when substituting %o. Be aware that you are using input and output as an argument to frule in that case, rather than inputs and outputs!

The substitutions are roughly the same as the substitutions in non-Lua Tupfile rules. See the Tup manual for more information on the format patterns.

  • If a glob character appears in an input, the input string is replaced by its glob results.
  • Global variable and config variable values are substituted for $() and @() respectively.
  • %d is replaced in input strings.
  • %d, %f, %b, and %B are replaced in output strings.
  • %d, %f, %b, %B, and %o are replaced in the command string.
tup.rule(command)
tup.rule(command, outputs)
tup.rule(inputs, command)
tup.rule(inputs, command, outputs)
Returns: table of strings

A forwarding wrapper around tup.frule. Except for the 3-argument version, inputs and outputs must always be tables, and command must be a string. In the 3-argument version, inputs and outputs can be a string for a single input, or a table. Returns the result of tup.frule.

tup.foreach_rule(inputs, command)
tup.foreach_rule(inputs, command, outputs)
Returns: table of strings

A forwarding wrapper around tup.frule. inputs and outputs must always be tables, and command must be a string. For each input INPUT, runs tup.frule with an input table containing INPUT and inputs.extra_inputs if present. Returns the aggregate result of all tup.frule calls.

tup.export(variable)
Returns: none

Adds the environment variable named variable to the export list for future rules. See the Tup manual for more information.

tup.creategitignore()
Returns: none

Tells Tup to automatically generate a .gitignore file in PROCESSING which contains a list of the output files that are generated by Tup. See the Tup manual for more information.

tup.getcwd()
Returns: string

Returns the relative path from PROCESSING to RUNNING.

Example: If /a/b/Tupfile.lua included /a/include.lua, tup.getcwd() would return the path ../.

tup.getdirectory()
Returns: string

Returns the name of RUNNING within RUNNING's parent directory.

Example: Running tup.getdirectory() in /a/b/Tupfile.lua would return b.

tup.getrelativedir(directoryname)
Returns: string

Returns a path to directoryname relative from the active Tupfile.lua file.

tup.nodevariable(path)
Returns: node variable

Returns a node variable referencing a file indicated by path relative to RUNNING. Calling tostring or concatenating the node variable with a string will convert the node variable to the relative path from RUNNING to the referenced file.

Example: A node variable created from path ./data.txt in /a/b/Tupfile.lua would resolve to ../b/data.txt in /a/c/Tupfile.lua.

tup.getconfig(name)
Returns: string

Returns the value of the config item named 'CONFIG_' .. name or the empty string if the config item does not exist.

tup.glob(pattern)
Returns: table of strings

Returns a table of the relative paths of all files matching glob pattern pattern.

tup.append_table(a, b)
Returns: none

Modifies a by appending all elements of b.

tup.file(filename)
Returns: string

Strips all parent directories from the path string filename and returns the result.

tup.base(filename)
Returns: string

Strips all parent directories from the path string filename and the file extension (including the .), and returns the result.

tup.ext(filename)
Returns: string

Returns the extension in the filename filename (excluding the .) or the empty string if there is no extension.