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 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)
@ -50,7 +54,7 @@ end
local function concatpath(...)
local p = table.concat({...}, "/")
return p:gsub("/+", "/"):gsub("^%./", "")
return p:gsub("/+", "/"):gsub("^%./", ""):gsub("/%./", "/")
end
local function basename(filename)
@ -144,6 +148,10 @@ local function uniquify(collection)
return o
end
local function startswith(needle, haystack)
return haystack:sub(1, #needle) == needle
end
local function emit(...)
local n = select("#", ...)
local args = {...}
@ -158,7 +166,7 @@ local function emit(...)
end
local function templateexpand(list, vars)
setmetatable(vars, { __index = globals })
vars = inherit(vars, globals)
local o = {}
for _, s in ipairs(list) do
@ -210,8 +218,18 @@ local function loadtarget(targetname)
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
}
@ -251,11 +269,9 @@ local typeconverters = {
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)
@ -383,13 +399,10 @@ definerule("simplerule",
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()
@ -416,7 +429,9 @@ globals = {
emit = emit,
environment = environment,
filenamesof = filenamesof,
inherit = inherit,
selectof = selectof,
startswith = startswith,
uniquify = uniquify,
}
setmetatable(globals,

View file

@ -13,13 +13,17 @@ definerule("normalrule",
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
@ -29,10 +33,11 @@ definerule("normalrule",
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}"
},
}
},
@ -42,18 +47,23 @@ definerule("cfile",
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,
@ -64,25 +74,85 @@ definerule("cfile",
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
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:

5
modules/build.lua Normal file
View file

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