cfile with dynamically generated headers sort of works.

This commit is contained in:
David Given 2016-06-07 05:00:26 +02:00
parent f4449e3f97
commit 8082ef16a7
2 changed files with 125 additions and 66 deletions

View file

@ -53,6 +53,25 @@ local function concatpath(...)
return p:gsub("/+", "/"):gsub("^%./", "") return p:gsub("/+", "/"):gsub("^%./", "")
end end
local function basename(filename)
local _, _, b = filename:find("^.*/([^/]*)$")
if not b then
return ""
end
return b
end
local function basenames(collection)
local o = {}
for _, s in pairs(collection) do
local b = basename(s)
if (b ~= "") then
o[#o+1] = b
end
end
return o
end
local function dirname(filename) local function dirname(filename)
local _, _, b = filename:find("^(.*)/[^/]*$") local _, _, b = filename:find("^(.*)/[^/]*$")
if not b then if not b then
@ -74,13 +93,15 @@ end
local function filenamesof(results) local function filenamesof(results)
local f = {} local f = {}
for _, r in pairs(results) do if results then
if (type(r) == "string") then for _, r in pairs(results) do
f[#f+1] = r if (type(r) == "string") then
elseif (type(r) == "table") then f[#f+1] = r
if r.is and r.outs then elseif (type(r) == "table") then
for _, o in pairs(r.outs) do if r.is and r.outs then
f[#f+1] = o for _, o in pairs(r.outs) do
f[#f+1] = o
end
end end
end end
end end
@ -88,6 +109,27 @@ local function filenamesof(results)
return f return f
end end
local function selectof(pattern, targets)
local o = {}
for k, v in pairs(targets) do
if v.is and v.outs then
local targetmatches = nil
for _, f in pairs(v.outs) do
local matches = not not f:find(pattern)
if (targetmatches == nil) then
targetmatches = matches
elseif (targetmatches ~= matches) then
error("selectof() is matching only part of a target")
end
end
if targetmatches then
o[#o+1] = v
end
end
end
return o
end
local function uniquify(collection) local function uniquify(collection)
local s = {} local s = {}
local o = {} local o = {}
@ -238,6 +280,13 @@ local typeconverters = {
end end
return i return i
end, end,
table = function(propname, i)
if (type(i) ~= "table") then
error(string.format("property '%s' must be a table", propname))
end
return i
end,
} }
local function definerule(rulename, types, cb) local function definerule(rulename, types, cb)
@ -258,7 +307,7 @@ local function definerule(rulename, types, cb)
local args = {} local args = {}
for propname, typespec in pairs(types) do for propname, typespec in pairs(types) do
if not e[propname] then if not e[propname] then
if not typespec.optional then if not typespec.optional and not typespec.default then
error(string.format("missing mandatory property '%s'", propname)) error(string.format("missing mandatory property '%s'", propname))
end end
@ -325,19 +374,22 @@ definerule("simplerule",
outs = { type="strings" }, outs = { type="strings" },
label = { type="string", optional=true }, label = { type="string", optional=true },
commands = { type="strings" }, commands = { type="strings" },
vars = { type="table", default={} },
}, },
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(filenamesof(e.outs)))
e.environment:exec(
templateexpand(e.commands, local vars = {
{ ins = e.ins,
ins = e.ins, outs = e.outs
outs = e.outs }
} for k, v in pairs(e.vars) do
) vars[k] = v
) end
e.environment:exec(templateexpand(e.commands, vars))
e.environment:endrule() e.environment:endrule()
return { return {
@ -352,11 +404,17 @@ definerule("simplerule",
globals = { globals = {
asstring = asstring, asstring = asstring,
basename = basename,
basenames = basenames,
concatpath = concatpath, concatpath = concatpath,
cwd = cwd, cwd = cwd,
definerule = definerule, definerule = definerule,
dirname = dirname,
dirnames = dirnames,
emit = emit, emit = emit,
environment = environment, environment = environment,
filenamesof = filenamesof,
selectof = selectof,
} }
setmetatable(globals, setmetatable(globals,
{ {

View file

@ -4,6 +4,7 @@ definerule("normalrule",
outleaves = { type="strings" }, outleaves = { type="strings" },
label = { type="string", optional=true }, label = { type="string", optional=true },
commands = { type="strings" }, commands = { type="strings" },
vars = { type="table", default={} },
}, },
function (e) function (e)
local objpath = "$(OBJDIR)/"..e.name local objpath = "$(OBJDIR)/"..e.name
@ -12,76 +13,76 @@ definerule("normalrule",
realouts[k] = concatpath(objpath, v) realouts[k] = concatpath(objpath, v)
end end
return simplerule { local result = simplerule {
name = e.name, name = e.name,
ins = e.ins, ins = e.ins,
outs = realouts, outs = realouts,
label = e.label, label = e.label,
commands = e.commands, commands = e.commands,
vars = e.vars,
}
result.dir = objpath
return result
end
)
definerule("cfile",
{
srcs = { type="targets" },
hdrs = { type="targets", default={} },
commands = {
type="strings",
default={
"$CC -c -o %{outs[1]} %{ins[1]} %{hdrpaths}"
},
}
},
function (e)
if (#e.srcs ~= 1) then
error("you must have exactly one .c file")
end
hdrpaths = {}
for _, t in pairs(e.hdrs) do
hdrpaths[#hdrpaths+1] = "-I"..t.dir
end
local outleaf = basename(filenamesof(e.srcs)[1]):gsub("%.c$", ".o")
return normalrule {
name = e.name,
ins = {e.srcs[1], unpack(e.hdrs)},
outleaves = {outleaf},
label = e.label,
commands = e.commands,
vars = {
hdrpaths = hdrpaths
}
} }
end end
) )
normalrule { normalrule {
name = "random", name = "mkheader",
ins = {}, ins = {},
outleaves = {"out"}, outleaves = {"foo.h"},
commands = { commands = {
"dd if=/dev/random of=%{outs} bs=1024 count=1" "echo 1 >> %{outs}"
} }
} }
normalrule { cfile {
name = "onetwo", name = "testfile-foo",
ins = {}, srcs = "foo.c",
outleaves = {"one.txt", "two.txt"},
commands = {
"echo 1 >> %{outs[1]}",
"echo 2 >> %{outs[2]}",
}
} }
normalrule { cfile {
name = "concat", name = "testfile-bar",
ins = {":onetwo"}, srcs = "bar.c",
outleaves = {"result.txt"}, hdrs = ":mkheader",
commands = {
"cat %{ins} > %{outs}"
}
}
simplerule {
name = "sorted",
ins = { ":random" },
outs = { "sorted" },
commands = {
"sort %{ins} > %{outs}"
}
} }
--[[ --[[
function environment:cfileflags()
emit("$CFLAGS")
end
function environment:cfile(srcs, obj, includes)
emit("$CC -o", obj, srcs)
emit(ab.expand(includes, "-I%"))
self:cflags()
emit("\n")
end
function environment:clinkflags()
emit("$LDFLAGS")
end
function environment:clink(objs, exe, libraryFlags)
emit("$CC -o", exe, objs, libraryFlags)
self:clinkflags()
emit("\n")
end
-- --
-- Targets: -- Targets:
-- --