| JamPlus manual
    | 
JamPlus has built-in Lua support, provided through a minimal distribution of LuaPlus (http://luaplus.org/) using Lua 5.3. Lua scripts may be run during the Parsing Phase and during the Updating Phase.
JamPlus also utilizes Lua scripts located in bin/scripts/, but these are not executed as part of the build process.
If a Jamfile.lua file is present instead of a Jamfile.jam, Lua execution of Jamfile.lua happens automatically.
There are two rules for execution of Lua script available for use during the rule parsing phase of JamPlus. They are rule LuaString LUA_SCRIPT and rule LuaFile LUA_FILENAME.
Executes
LUA_SCRIPT, returning any results back to the caller.
- Parameters
LUA_SCRIPT Syntactically correct Lua script embedded in a string. Only the first string list item is executed. Please note that double quotes should be escaped. 
- Returns
- If the Lua script doesn't return any values, the return value is an empty list. If the Lua script does return values, the return values are transformed to a Jam string list. Nested tables are collapsed.
Executes
LUA_FILENAME, returning any results back to the caller.
- Parameters
LUA_FILENAME The filename of the Lua script to run. 
- Returns
- If the Lua script doesn't return any values, the return value is an empty list. If the Lua script does return values, the return values are transformed to a Jam string list. Nested tables are collapsed.
Using the lua modifier for an action, Lua script can be run in a thread within the Jam process.
actions lua RunLuaScript{osprocess = require 'osprocess'osprocess.sleep($(SLEEP))print($(TEXT))}
Any settings attached to the target are propogated to the Lua task and are available via the jamvar table.
Certain modifiers can be applied to determine which settings are bound and unbound. Use JAM_UNBOUND_SETTINGS to use a setting as is within the jamvar table. Use JAM_BOUND_SETTINGS to force a setting to resolve its path.
actions screenoutput lua _EmbedFile{osprocess = require 'osprocess'local targets, sources = ...local in_file = io.open(sources[1], 'rb')local data = in_file:read('*a')in_file:close()local out_file = io.open(targets[1], 'w')local name = jamvar.NAMElocal sleepAmount = jamvar.SLEEP[1]local symbol = name[1]:upper():gsub('%.', '_'):gsub('-', '_'):gsub('@', 'at')local cpp_str = [[#include <stdint.h>unsigned char %s[] =]]out_file:write(cpp_str:format(symbol))out_file:write('{\n ')local data_is_binary = falselocal tmp = {}local format = string.formatlocal sbyte = string.byteif data_is_binary thenfor index = 1, #data doendelsefor index = 1, #data dolocal x = sbyte(data, index, index + 1)tmp[#tmp + 1] = format('0x%x', x)tmp[#tmp + 1] = ', 'if index > 1 and (index - 1) % 4 == 0 thentmp[#tmp + 1] = '\n 'endendendosprocess.sleep(tonumber(sleepAmount))out_file:write(table.concat(tmp))out_file:write('\n};\n')out_file:write(('uint32_t %s_SIZE = sizeof(%s);\n'):format(symbol, symbol))out_file:close()}rule EmbedFile SOURCES : SLEEP{local alltargets ;SOURCES = [ C.GristFiles : $(SOURCES) ] ;local source ;for source in $(SOURCES){local splits = [ Split $(source) : "=" ] ;local source = $(splits[1]) ;local name = $(splits[2]:E=$(source):G=) ;SEARCH on $(source) = $(SEARCH_SOURCE) ;local target.cpp = @($(source).embed.cpp:G=$(C.ACTIVE_TOOLCHAIN_TARGET_GRIST)) ;local targets = $(target.cpp) ;alltargets += $(targets) ;MakeLocate $(targets) : $(LOCATE_TARGET) ;Depends $(targets) : $(source) ;C.Clean : $(targets) ;UseCommandLine $(targets) : v1r ;NAME on $(targets) = $(name:BS) ;SLEEP on $(targets) = $(SLEEP) ;JAM_UNBOUND_SETTINGS on $(targets) = NAME SLEEP ;_EmbedFile $(target.cpp) : $(source) ;}return $(alltargets) ;}local EMBED_SOURCES = [ EmbedFile fileglob.c jrun.jam main.cpp license : 0 ] ;C.Library test : $(EMBED_SOURCES) ;C.LinkLibraries main : test ;C.Application main : main.cpp ;
The LineFilters table contains a mapping of an action name to a line-by-line parsing function. For every line of output received by the action, the appropriate LineFilters table actionname->function is run. The function can do with the output what it wants and return the result.
For example, in the LineFilters.Compiler function and action below, a GCC-style error message is changed into a Visual C++ compatible error message.
USE_LUA_LINE_FILTERS = 1 ;LuaString "LineFilters.UpperCaseRule = function(input)return '-> ' .. input:upper()endLineFilters.LowerCaseRule = function(input)return '-> ' .. input:lower()endLineFilters.Compiler = function(input)return input:gsub('(.-):(%d+):(.+)', '%1(%2) %3')end" ;actions UpperCaseRule {echo This text will be uppercase.echo This text will also be uppercase in the output.}actions LowerCaseRule {echo THIS TEXT will be LOWERCASE.}actions Compiler {echo c:\the\directory\filename.cpp:1000:This is an error message.}Always all ;UpperCaseRule all ;LowerCaseRule all ;Compiler all ;
Within a Lua script, it is possible to access Jam variables and execute Jam rules.
Upon first encountering a Jamfile.lua or using rule LuaFile LUA_FILENAME or rule LuaString LUA_SCRIPT, several Jam-related namespaces become available in Lua accessible via the namespaces jam, jamtarget, and jamvar. Also, described in the section below, a more rich API lets you access most Jam functionality.
To read or write from any variables currently within scope in Jam, use the Lua-provided jamvar table.
The only data type in Jam is a list of strings, so even GameAssets containing a single path is still a list of strings containing only one element. Within Lua, jamvar.GameAssets is a table containing an array of strings with the only element being $(SUBDIR)/assets. Therefore, to access the actual contents of a Jam-provided string list requires indexing into the returned table.
It is also possible to access a Jam target directly.
Evaluating a rule is done with ease within the jam namespace:
Note that single element data types in Lua are automatically converted to a list of strings for Jam. That means that the second parameter to jam.Depends is converted to { outputTarget }.
The jam namespace provides the most useful access to Jam functionality. It does not cover the full range of Jam features. For a more extensive API to access Jam from Lua, see the next section.
Within a Lua script, it is possible to access Jam variables and execute Jam rules.
Creates an action to be executed by Jam called
ACTION_NAMEmade up ofACTION_TEXT. If written in the Jam language, the equivalent would be:
jam_action(ACTION_NAME, ACTION_TEXT)is equivalent to:actions ACTION_NAME{ACTION_TEXT}
If
FLAGSis specified as a table, those flags are applied to the action and have direct correspondence to action modifiers specified in a Jam action.
jam_action(ACTION_NAME, ACTION_TEXT, { updated = true, together = true })is equivalent to:actions updated together ACTION_NAME{ACTION_TEXT}
- Parameters
ACTION_NAME The name of any valid Jam action. ACTION_TEXT Text representing the commands to be executed by the shell. FLAGS (optional) If specifed, FLAGSmust be a table of action modifiers containing one or more of the following:bind = { 'various', 'target', 'names' },existing = true,ignore = true,lua = true,maxline = true,maxresponse = true,piecemeal = true,quietly = true,removeemptydirs = true,response = true,screenoutput = true,together = true,updated = true
Executes rule
RULE_NAMEusing any optionalPARAMETERSspecified. Returns the result as a Lua table.
- Parameters
RULE_NAME The name of any valid Jam rule. PARAMETERS (optional) If specifed, the PARAMETERSare collapsed into a Jam string list and passed to the rule.
- Returns
- If the Jam rule doesn't return any values, the return value is
nil. If the Jam rule does return values, the return values are transformed to a Lua array of strings.
Expands
TEXT_TO_EXPANDaccording to Jam rules.TEXT_TO_EXPANDmust use the $() or @() expansion forms described elsewhere.
- Parameters
TEXT_TO_EXPAND The text to expand. 
- Returns
- Returns the expanded text.
Retrieves
VARIABLE_NAMEfrom the active Jam globals and returns it as a table of strings.If
TARGET_NAMEis specified,VARIABLE_NAMEis retrieved as if anon TARGET_NAMEhad been issued in Jam.
- Parameters
TARGET_NAME (optional) The target to make active to retrieve VARIABLE_NAMEfrom.VARIABLE_NAME The Jam variable to retrieve. 
- Returns
- All strings within the
VARIABLE_NAMEstring are returned as a Lua array of strings. Returns nil ifVARIABLE_NAMEdoes not exist.
Parses
TEXT_TO_PARSEas if it existed in a Jamfile.
- Parameters
TEXT_TO_PARSE Jam source code to be parsed and executed by Jam immediately. 
Prints
TEXT_TO_PRINTto the standard output stream.
- Parameters
TEXT_TO_PRINT The text to print. 
Sets
VALUEinto the active Jam globalVARIABLE_NAME.VALUEcan be a boolean, number, string, or table. Nested tables are collapsed.If
TARGET_NAMEis specified,VALUEis set intoVARIABLE_NAMEas if anVARIABLE_NAME on TARGET_NAMEhad been issued in Jam.
- Parameters
TARGET_NAME (optional) The target to make active to set VARIABLE_NAMEinto.VARIABLE_NAME The Jam variable to set. 
# HelloLuaString "print('Hello')" ;# 10 hi falseEcho [ LuaString "return { 10, 'hi', false }" ] ;# 5.suf hello.suf true.sufvar = [ LuaString "return { 5, 'hello', true }" ] ;Echo $(var:S=.suf) ;#------------------------------------------------------------------------------# Hello world!var = Hello world! ;Echo [ LuaString "return jam_getvar('var')" ] ;# Hi everyoneLuaString "jam_setvar('var', 'Hi everyone')" ;Echo $(var) ;# Hi everyoneEcho [ LuaString "return jam_getvar('var')" ] ;#------------------------------------------------------------------------------# The Variable ContentsMyVariable on mytarget = The Variable Contents ;Echo [ LuaString "return jam_getvar('mytarget', 'MyVariable')" ] ;# **hello**LuaString "jam_setvar('mytarget', 'MyVariable', '**hello**')" ;Echo [ LuaString "return jam_getvar('mytarget', 'MyVariable')" ] ;rule ReturnList INPUT{return **$(INPUT)** ;}# **MyStuff** **YourStuff**Echo [ LuaString "return jam_evaluaterule('ReturnList', { 'MyStuff', 'YourStuff' })" ] ;