Multiple build files work. Use deps intelligently. clibraries.

This commit is contained in:
David Given 2016-06-09 06:55:44 +02:00
parent fcc5a878ae
commit f47bb49c1f
3 changed files with 131 additions and 41 deletions

View file

@ -15,14 +15,18 @@ local buildfiles = {}
local globals local globals
local cwd = "." local cwd = "."
local function subenv(old, cb) local function inherit(high, low)
if not old then local o = {}
old = environment setmetatable(o, {
end __index = function(self, k)
local new = {} local x = high[k]
setmetatable(new, {__index = old}) if x then
cb(new, old) return x
return new end
return low[k]
end
})
return o
end end
local function asstring(o) local function asstring(o)
@ -50,7 +54,7 @@ end
local function concatpath(...) local function concatpath(...)
local p = table.concat({...}, "/") local p = table.concat({...}, "/")
return p:gsub("/+", "/"):gsub("^%./", "") return p:gsub("/+", "/"):gsub("^%./", ""):gsub("/%./", "/")
end end
local function basename(filename) local function basename(filename)
@ -144,6 +148,10 @@ local function uniquify(collection)
return o return o
end end
local function startswith(needle, haystack)
return haystack:sub(1, #needle) == needle
end
local function emit(...) local function emit(...)
local n = select("#", ...) local n = select("#", ...)
local args = {...} local args = {...}
@ -158,7 +166,7 @@ local function emit(...)
end end
local function templateexpand(list, vars) local function templateexpand(list, vars)
setmetatable(vars, { __index = globals }) vars = inherit(vars, globals)
local o = {} local o = {}
for _, s in ipairs(list) do for _, s in ipairs(list) do
@ -210,8 +218,18 @@ local function loadtarget(targetname)
local target local target
if not targetname:find(":") then 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 = { target = {
outs = {targetname}, outs = files,
is = { is = {
__implicitfile = true __implicitfile = true
} }
@ -251,11 +269,9 @@ local typeconverters = {
if (type(s) == "table") and s.is then if (type(s) == "table") and s.is then
o[#o+1] = s o[#o+1] = s
elseif (type(s) == "string") then elseif (type(s) == "string") then
if s:find("^//") then if s:find("^:") then
s = s:gsub("^//", "")
elseif s:find("^:") then
s = cwd..s s = cwd..s
elseif s:find("^[^/]") then elseif s:find("^%./") then
s = concatpath(cwd, s) s = concatpath(cwd, s)
end end
o[#o+1] = loadtarget(s) o[#o+1] = loadtarget(s)
@ -383,13 +399,10 @@ definerule("simplerule",
e.environment:label(cwd..":"..e.name, " ", e.label or "") e.environment:label(cwd..":"..e.name, " ", e.label or "")
e.environment:mkdirs(dirnames(e.outs)) e.environment:mkdirs(dirnames(e.outs))
local vars = { local vars = inherit(e.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:exec(templateexpand(e.commands, vars))
e.environment:endrule() e.environment:endrule()
@ -416,7 +429,9 @@ globals = {
emit = emit, emit = emit,
environment = environment, environment = environment,
filenamesof = filenamesof, filenamesof = filenamesof,
inherit = inherit,
selectof = selectof, selectof = selectof,
startswith = startswith,
uniquify = uniquify, uniquify = uniquify,
} }
setmetatable(globals, setmetatable(globals,

View file

@ -13,13 +13,17 @@ definerule("normalrule",
realouts[k] = concatpath(objpath, v) realouts[k] = concatpath(objpath, v)
end end
local vars = inherit(e.vars, {
dir = objpath
})
local result = 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, vars = vars,
} }
result.dir = objpath result.dir = objpath
return result return result
@ -29,10 +33,11 @@ definerule("normalrule",
definerule("cfile", definerule("cfile",
{ {
srcs = { type="targets" }, srcs = { type="targets" },
deps = { type="targets", default={} },
commands = { commands = {
type="strings", type="strings",
default={ default={
"$CC -c -o %{outs[1]} %{ins[1]} %{hdrpaths}" "$(CC) -c -o %{outs[1]} %{ins[1]} %{hdrpaths}"
}, },
} }
}, },
@ -42,18 +47,23 @@ definerule("cfile",
error("you must have exactly one .c file") error("you must have exactly one .c file")
end end
local htargets = selectof(e.srcs, "%.h$") local hsrcs = filenamesof(e.srcs, "%.h$")
local hdeps = selectof(e.deps, "%.h$")
local hdrpaths = {} local hdrpaths = {}
for _, t in pairs(htargets) do for _, t in pairs(hdeps) do
hdrpaths[#hdrpaths+1] = "-I"..t.dir hdrpaths[#hdrpaths+1] = "-I"..t.dir
end end
hdrpaths = uniquify(hdrpaths) hdrpaths = uniquify(hdrpaths)
for _, f in pairs(filenamesof(hdeps)) do
hsrcs[#hsrcs+1] = f
end
local outleaf = basename(csrcs[1]):gsub("%.c$", ".o") local outleaf = basename(csrcs[1]):gsub("%.c$", ".o")
return normalrule { return normalrule {
name = e.name, name = e.name,
ins = {csrcs[1], unpack(htargets)}, ins = {csrcs[1], unpack(hsrcs)},
outleaves = {outleaf}, outleaves = {outleaf},
label = e.label, label = e.label,
commands = e.commands, commands = e.commands,
@ -64,25 +74,85 @@ definerule("cfile",
end end
) )
normalrule { definerule("bundle",
name = "mkheader", {
ins = {}, srcs = { type="targets" },
outleaves = {"foo.h"}, commands = {
commands = { type="strings",
"echo 1 >> %{outs}" 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
return normalrule {
name = e.name,
ins = e.srcs,
outleaves = outleaves,
label = e.label,
commands = commands
}
end
)
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"
} }
} }
cfile {
name = "testfile-foo",
srcs = "foo.c",
}
cfile {
name = "testfile-bar",
srcs = {"bar.c", ":mkheader"},
}
--[[ --[[
-- --
-- Targets: -- Targets:

5
modules/build.lua Normal file
View file

@ -0,0 +1,5 @@
bundle {
name = "headers",
srcs = { "./h/*.h" }
}