156 lines
4.0 KiB
Lua
156 lines
4.0 KiB
Lua
module(..., package.seeall)
|
|
|
|
local boot = require "tundra.boot"
|
|
local util = require "tundra.util"
|
|
local path = require "tundra.path"
|
|
local native = require "tundra.native"
|
|
local environment = require "tundra.environment"
|
|
|
|
local default_pass = { Name = "Default", BuildOrder = 100000 }
|
|
|
|
local all_nodes = {}
|
|
|
|
local _node_mt = {}
|
|
_node_mt.__index = _node_mt
|
|
|
|
function make_node(data_)
|
|
local env_ = data_.Env
|
|
assert(environment.is_environment(env_), "Env must be provided")
|
|
|
|
local root_path = native.getcwd() .. env_:get('SEP')
|
|
|
|
local function path_for_cmdline(p)
|
|
local full_path
|
|
if path.is_absolute(p) then
|
|
full_path = p
|
|
else
|
|
full_path = root_path .. p
|
|
end
|
|
if full_path:find(' ', 1, true) then
|
|
return '"' .. full_path .. '"'
|
|
else
|
|
return full_path
|
|
end
|
|
end
|
|
|
|
local function normalize_paths(paths)
|
|
return util.mapnil(paths, function (x)
|
|
if type(x) == "string" then
|
|
local v = env_:interpolate(x)
|
|
v = path.normalize(v)
|
|
return v
|
|
else
|
|
return x
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- these are the inputs that $(<) expand to
|
|
local regular_inputs = normalize_paths(data_.InputFiles)
|
|
|
|
-- these are other, auxillary input files that shouldn't appear on the command line
|
|
-- useful to e.g. add an input dependency on a tool
|
|
local implicit_inputs = normalize_paths(data_.ImplicitInputs)
|
|
|
|
local inputs = util.merge_arrays_2(regular_inputs, implicit_inputs)
|
|
local outputs = normalize_paths(data_.OutputFiles)
|
|
|
|
local inputs_sorted = inputs and util.clone_array(inputs) or {}
|
|
local outputs_sorted = outputs and util.clone_array(outputs) or {}
|
|
|
|
local cmdline_inputs = util.merge_arrays(regular_inputs, data_.InputFilesUntracked)
|
|
|
|
table.sort(inputs_sorted)
|
|
table.sort(outputs_sorted)
|
|
|
|
-- Quote the paths before interpolation into the command line
|
|
local expand_env = {
|
|
['<'] = util.mapnil(cmdline_inputs, path_for_cmdline),
|
|
['@'] = util.mapnil(outputs, path_for_cmdline),
|
|
}
|
|
|
|
local expand_env_pretty = {
|
|
['<'] = cmdline_inputs,
|
|
['@'] = outputs,
|
|
}
|
|
|
|
local overwrite = true
|
|
if type(data_.OverwriteOutputs) ~= "nil" then
|
|
overwrite = data_.OverwriteOutputs
|
|
end
|
|
|
|
if data_.Scanner and not data_.Scanner.Kind then
|
|
errorf("Missing scanner kind")
|
|
end
|
|
|
|
-- make sure dependencies are unique
|
|
local unique_deps = util.uniq(data_.Dependencies or {})
|
|
|
|
local params = {
|
|
pass = data_.Pass or default_pass,
|
|
scanner = data_.Scanner,
|
|
deps = unique_deps,
|
|
inputs = inputs_sorted,
|
|
outputs = outputs_sorted,
|
|
is_precious = data_.Precious,
|
|
expensive = data_.Expensive,
|
|
overwrite_outputs = overwrite,
|
|
src_env = env_,
|
|
env = env_.external_vars,
|
|
aux_outputs = util.mapnil(data_.AuxOutputFiles, function (x)
|
|
local result = env_:interpolate(x, expand_env)
|
|
return path.normalize(result)
|
|
end),
|
|
}
|
|
|
|
if data_.Action then
|
|
params.action = env_:interpolate(data_.Action, expand_env)
|
|
else
|
|
assert(0 == #params.outputs, "can't have output files without an action")
|
|
params.action = ""
|
|
end
|
|
|
|
if data_.PreAction then
|
|
params.preaction = env_:interpolate(data_.PreAction, expand_env)
|
|
end
|
|
|
|
params.annotation = env_:interpolate(data_.Label or "?", expand_env_pretty)
|
|
|
|
local result = setmetatable(params, _node_mt)
|
|
|
|
-- Stash node
|
|
all_nodes[#all_nodes + 1] = result
|
|
|
|
return result
|
|
end
|
|
|
|
function is_node(obj)
|
|
return getmetatable(obj) == _node_mt
|
|
end
|
|
|
|
function _node_mt:insert_output_files(tab, exts)
|
|
if exts then
|
|
local lut = util.make_lookup_table(exts)
|
|
for _, fn in ipairs(self.outputs) do
|
|
local ext = path.get_extension(fn)
|
|
if lut[ext] then
|
|
tab[#tab + 1] = fn
|
|
end
|
|
end
|
|
else
|
|
for _, fn in ipairs(self.outputs) do
|
|
tab[#tab + 1] = fn
|
|
end
|
|
end
|
|
end
|
|
|
|
function _node_mt:insert_deps(tab)
|
|
for _, dep in util.nil_ipairs(self.deps) do
|
|
tab[#tab + 1] = dep
|
|
end
|
|
end
|
|
|
|
function get_all_nodes()
|
|
return all_nodes
|
|
end
|