2014-09-14 08:36:58 +02:00

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