Rather cleaner cfile implementation where you just give it a .c and a pile of .h files.

This commit is contained in:
David Given 2016-06-08 03:21:53 +02:00
parent 8082ef16a7
commit fcc5a878ae
2 changed files with 29 additions and 25 deletions

View file

@ -91,38 +91,40 @@ local function dirnames(collection)
return o return o
end end
local function filenamesof(results) local function filenamesof(targets, pattern)
local f = {} local f = {}
if results then if targets then
for _, r in pairs(results) do for _, r in pairs(targets) do
if (type(r) == "string") then if (type(r) == "table") and r.is then
f[#f+1] = r if r.outs then
elseif (type(r) == "table") then
if r.is and r.outs then
for _, o in pairs(r.outs) do for _, o in pairs(r.outs) do
f[#f+1] = o if not pattern or o:find(pattern) then
f[#f+1] = o
end
end end
end end
else
error("list of targets contains something which isn't a target")
end end
end end
end end
return f return f
end end
local function selectof(pattern, targets) -- Selects all targets containing at least one output file that matches
-- the pattern.
local function selectof(targets, pattern)
local o = {} local o = {}
for k, v in pairs(targets) do for k, v in pairs(targets) do
if v.is and v.outs then if v.is and v.outs then
local targetmatches = nil local matches = false
for _, f in pairs(v.outs) do for _, f in pairs(v.outs) do
local matches = not not f:find(pattern) if f:find(pattern) then
if (targetmatches == nil) then matches = true
targetmatches = matches break
elseif (targetmatches ~= matches) then
error("selectof() is matching only part of a target")
end end
end end
if targetmatches then if matches then
o[#o+1] = v o[#o+1] = v
end end
end end
@ -379,7 +381,7 @@ definerule("simplerule",
function (e) function (e)
e.environment:rule(filenamesof(e.ins), e.outs) e.environment:rule(filenamesof(e.ins), e.outs)
e.environment:label(cwd..":"..e.name, " ", e.label or "") e.environment:label(cwd..":"..e.name, " ", e.label or "")
e.environment:mkdirs(dirnames(filenamesof(e.outs))) e.environment:mkdirs(dirnames(e.outs))
local vars = { local vars = {
ins = e.ins, ins = e.ins,
@ -415,6 +417,7 @@ globals = {
environment = environment, environment = environment,
filenamesof = filenamesof, filenamesof = filenamesof,
selectof = selectof, selectof = selectof,
uniquify = uniquify,
} }
setmetatable(globals, setmetatable(globals,
{ {

View file

@ -29,7 +29,6 @@ definerule("normalrule",
definerule("cfile", definerule("cfile",
{ {
srcs = { type="targets" }, srcs = { type="targets" },
hdrs = { type="targets", default={} },
commands = { commands = {
type="strings", type="strings",
default={ default={
@ -38,20 +37,23 @@ definerule("cfile",
} }
}, },
function (e) function (e)
if (#e.srcs ~= 1) then local csrcs = filenamesof(e.srcs, "%.c$")
if (#csrcs ~= 1) then
error("you must have exactly one .c file") error("you must have exactly one .c file")
end end
hdrpaths = {} local htargets = selectof(e.srcs, "%.h$")
for _, t in pairs(e.hdrs) do local hdrpaths = {}
for _, t in pairs(htargets) do
hdrpaths[#hdrpaths+1] = "-I"..t.dir hdrpaths[#hdrpaths+1] = "-I"..t.dir
end end
hdrpaths = uniquify(hdrpaths)
local outleaf = basename(filenamesof(e.srcs)[1]):gsub("%.c$", ".o") local outleaf = basename(csrcs[1]):gsub("%.c$", ".o")
return normalrule { return normalrule {
name = e.name, name = e.name,
ins = {e.srcs[1], unpack(e.hdrs)}, ins = {csrcs[1], unpack(htargets)},
outleaves = {outleaf}, outleaves = {outleaf},
label = e.label, label = e.label,
commands = e.commands, commands = e.commands,
@ -78,8 +80,7 @@ cfile {
cfile { cfile {
name = "testfile-bar", name = "testfile-bar",
srcs = "bar.c", srcs = {"bar.c", ":mkheader"},
hdrs = ":mkheader",
} }
--[[ --[[