local globals
local cwd = "."
-local function subenv(old, cb)
- if not old then
- old = environment
- end
- local new = {}
- setmetatable(new, {__index = old})
- cb(new, old)
- return new
+local function inherit(high, low)
+ local o = {}
+ setmetatable(o, {
+ __index = function(self, k)
+ local x = high[k]
+ if x then
+ return x
+ end
+ return low[k]
+ end
+ })
+ return o
end
local function asstring(o)
local function concatpath(...)
local p = table.concat({...}, "/")
- return p:gsub("/+", "/"):gsub("^%./", "")
+ return p:gsub("/+", "/"):gsub("^%./", ""):gsub("/%./", "/")
end
local function basename(filename)
return o
end
+local function startswith(needle, haystack)
+ return haystack:sub(1, #needle) == needle
+end
+
local function emit(...)
local n = select("#", ...)
local args = {...}
end
local function templateexpand(list, vars)
- setmetatable(vars, { __index = globals })
+ vars = inherit(vars, globals)
local o = {}
for _, s in ipairs(list) do
local target
if not targetname:find(":") then
+ local files
+ if targetname:find("[?*]") then
+ files = posix.glob(targetname)
+ if not files then
+ error(string.format("glob '%s' matches no files", targetname))
+ end
+ else
+ files = {targetname}
+ end
+
target = {
- outs = {targetname},
+ outs = files,
is = {
__implicitfile = true
}
if (type(s) == "table") and s.is then
o[#o+1] = s
elseif (type(s) == "string") then
- if s:find("^//") then
- s = s:gsub("^//", "")
- elseif s:find("^:") then
+ if s:find("^:") then
s = cwd..s
- elseif s:find("^[^/]") then
+ elseif s:find("^%./") then
s = concatpath(cwd, s)
end
o[#o+1] = loadtarget(s)
e.environment:label(cwd..":"..e.name, " ", e.label or "")
e.environment:mkdirs(dirnames(e.outs))
- local vars = {
+ local vars = inherit(e.vars, {
ins = e.ins,
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()
emit = emit,
environment = environment,
filenamesof = filenamesof,
+ inherit = inherit,
selectof = selectof,
+ startswith = startswith,
uniquify = uniquify,
}
setmetatable(globals,
realouts[k] = concatpath(objpath, v)
end
+ local vars = inherit(e.vars, {
+ dir = objpath
+ })
+
local result = simplerule {
name = e.name,
ins = e.ins,
outs = realouts,
label = e.label,
commands = e.commands,
- vars = e.vars,
+ vars = vars,
}
result.dir = objpath
return result
definerule("cfile",
{
srcs = { type="targets" },
+ deps = { type="targets", default={} },
commands = {
type="strings",
default={
- "$CC -c -o %{outs[1]} %{ins[1]} %{hdrpaths}"
+ "$(CC) -c -o %{outs[1]} %{ins[1]} %{hdrpaths}"
},
}
},
error("you must have exactly one .c file")
end
- local htargets = selectof(e.srcs, "%.h$")
+ local hsrcs = filenamesof(e.srcs, "%.h$")
+ local hdeps = selectof(e.deps, "%.h$")
local hdrpaths = {}
- for _, t in pairs(htargets) do
+ for _, t in pairs(hdeps) do
hdrpaths[#hdrpaths+1] = "-I"..t.dir
end
hdrpaths = uniquify(hdrpaths)
+ for _, f in pairs(filenamesof(hdeps)) do
+ hsrcs[#hsrcs+1] = f
+ end
+
local outleaf = basename(csrcs[1]):gsub("%.c$", ".o")
return normalrule {
name = e.name,
- ins = {csrcs[1], unpack(htargets)},
+ ins = {csrcs[1], unpack(hsrcs)},
outleaves = {outleaf},
label = e.label,
commands = e.commands,
end
)
-normalrule {
- name = "mkheader",
- ins = {},
- outleaves = {"foo.h"},
- commands = {
- "echo 1 >> %{outs}"
- }
-}
+definerule("bundle",
+ {
+ srcs = { type="targets" },
+ commands = {
+ type="strings",
+ default={
+ "tar cf - %{ins} | (cd %{dir} && tar xf -)"
+ }
+ }
+ },
+ function (e)
+ local outleaves = {}
+ local commands = {}
+ for _, f in pairs(filenamesof(e.srcs)) do
+ local localf = basename(f)
+ outleaves[#outleaves+1] = localf
+ commands[#commands+1] = "cp "..f.." %{dir}/"..localf
+ end
-cfile {
- name = "testfile-foo",
- srcs = "foo.c",
-}
+ return normalrule {
+ name = e.name,
+ ins = e.srcs,
+ outleaves = outleaves,
+ label = e.label,
+ commands = commands
+ }
+ end
+)
-cfile {
- name = "testfile-bar",
- srcs = {"bar.c", ":mkheader"},
+definerule("clibrary",
+ {
+ srcs = { type="targets" },
+ deps = { type="targets", default={} },
+ commands = {
+ type="strings",
+ default={
+ "rm -f %{outs}",
+ "$(AR) qs %{outs} %{ins}"
+ },
+ }
+ },
+ function (e)
+ local csrcs = filenamesof(e.srcs, "%.c$")
+ if (#csrcs < 1) then
+ error("you must supply at least one C source file")
+ end
+
+ local hsrcs = filenamesof(e.srcs, "%.h$")
+
+ local ins = {}
+ for _, csrc in pairs(csrcs) do
+ local n = basename(csrc):gsub("%.%w*$", "")
+ ins[#ins+1] = cfile {
+ name = e.name.."/"..n,
+ srcs = {csrc, unpack(hsrcs)},
+ deps = e.deps,
+ }
+ end
+
+ return normalrule {
+ name = e.name,
+ ins = ins,
+ outleaves = { e.name..".a" },
+ label = e.label,
+ commands = e.commands
+ }
+ end
+)
+
+clibrary {
+ name = "mylib",
+ srcs = {
+ "modules/src/string/*.c",
+ },
+ deps = {
+ "modules:headers"
+ }
}
--[[