installable works, although it's a bit kludgy. Change the : separator to +

because : is special in make and non of the others I could think of would work.
This commit is contained in:
David Given 2016-06-14 07:34:14 +02:00
parent 605651776e
commit 09554cb324
5 changed files with 91 additions and 16 deletions

7
build.lua Normal file
View file

@ -0,0 +1,7 @@
installable {
name = "ack",
map = {
"util/ack+ack-pkg"
}
}

View file

@ -3,6 +3,7 @@ local posix = require("posix")
-- Targets: -- Targets:
-- --
-- { -- {
-- fullname = full name of target
-- dir = target's build directory -- dir = target's build directory
-- outs = target's object files -- outs = target's object files
-- is = { set of rule types which made the target } -- is = { set of rule types which made the target }
@ -60,6 +61,10 @@ end
local function filenamesof(targets, pattern) local function filenamesof(targets, pattern)
local f = {} local f = {}
if targets then if targets then
if targets.is then
targets = {targets}
end
for _, r in pairs(targets) do for _, r in pairs(targets) do
if (type(r) == "table") and r.is then if (type(r) == "table") and r.is then
if r.outs then if r.outs then
@ -141,7 +146,7 @@ end
local function fpairs(collection) local function fpairs(collection)
if (type(collection) == "string") or collection.is then if (type(collection) == "string") or collection.is then
return tpairs({collection}) return fpairs({collection})
end end
return pairs(filenamesof(collection)) return pairs(filenamesof(collection))
@ -249,7 +254,7 @@ local function loadtarget(targetname)
end end
local target local target
if not targetname:find(":") then if not targetname:find("%+") then
local files local files
if targetname:find("[?*]") then if targetname:find("[?*]") then
files = posix.glob(targetname) files = posix.glob(targetname)
@ -268,7 +273,7 @@ local function loadtarget(targetname)
} }
targets[targetname] = target targets[targetname] = target
else else
local _, _, filepart, targetpart = targetname:find("^([^:]*):([%w-_]+)$") local _, _, filepart, targetpart = targetname:find("^([^+]*)%+([%w-_]+)$")
if not filepart or not targetpart then if not filepart or not targetpart then
error(string.format("malformed target name '%s'", targetname)) error(string.format("malformed target name '%s'", targetname))
end end
@ -297,16 +302,16 @@ local typeconverters = {
end end
local o = {} local o = {}
for _, s in ipairs(i) do for k, s in pairs(i) do
if (type(s) == "table") and s.is then if (type(s) == "table") and s.is then
o[#o+1] = s o[k] = s
elseif (type(s) == "string") then elseif (type(s) == "string") then
if s:find("^:") then if 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[k] = loadtarget(s)
else else
error(string.format("member of target list '%s' is not a string or a target", error(string.format("member of target list '%s' is not a string or a target",
propname)) propname))
@ -374,11 +379,13 @@ local function definerule(rulename, types, cb)
end end
args.environment = environment args.environment = environment
args.fullname = cwd.."+"..args.name
local result = cb(args) or {} local result = cb(args) or {}
result.is = result.is or {} result.is = result.is or {}
result.is[rulename] = true result.is[rulename] = true
targets[cwd..":"..args.name] = result result.fullname = args.fullname
targets[result.fullname] = result
return result return result
end end
end end
@ -398,6 +405,11 @@ function environment:rule(ins, outs)
emit(firstout..":\n") emit(firstout..":\n")
end end
function environment:phony(ins, outs)
emit(".PHONY:", outs, "\n")
self:rule(ins, outs)
end
function environment:label(...) function environment:label(...)
local s = table.concat({...}, " ") local s = table.concat({...}, " ")
emit("\t@echo", s, "\n") emit("\t@echo", s, "\n")
@ -411,7 +423,9 @@ function environment:mkdirs(dirs)
end end
function environment:exec(commands) function environment:exec(commands)
emit("\t$(hide)", table.concat(commands, " && "), "\n") for _, s in ipairs(commands) do
emit("\t$(hide)", s, "\n")
end
end end
function environment:endrule() function environment:endrule()
@ -428,7 +442,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(e.fullname, " ", e.label or "")
e.environment:mkdirs(dirname(e.outs)) e.environment:mkdirs(dirname(e.outs))
local vars = inherit(e.vars, { local vars = inherit(e.vars, {
@ -445,6 +459,51 @@ definerule("simplerule",
end end
) )
definerule("installable",
{
map = { type="targets", default={} },
},
function (e)
local deps = {}
local commands = {}
local srcs = {}
local dests = {}
for dest, src in pairs(e.map) do
if src.is.installable then
if (type(dest) ~= "number") then
error("can't specify a destination filename when installing an installable")
end
deps[#deps+1] = src.fullname
elseif (type(dest) == "number") then
error("only references to other installables can be missing a destination")
else
local f = filenamesof(src)
if (#f ~= 1) then
error("installable can only cope with targets emitting single files")
end
srcs[#srcs+1] = src
dests[#dests+1] = dest
commands[#commands+1] = "cp "..f[1].." "..dest
deps[#deps+1] = dest
end
end
if (#dests > 0) then
e.environment:rule(srcs, dests)
e.environment:label(e.fullname, " ", e.label or "")
if (#commands > 0) then
e.environment:mkdirs(dirname(dests))
e.environment:exec(commands)
end
e.environment:endrule()
end
e.environment:phony(deps, {cwd.."+"..e.name})
e.environment:endrule()
end
)
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- MAIN PROGRAM -- -- MAIN PROGRAM --
----------------------------------------------------------------------------- -----------------------------------------------------------------------------

View file

@ -13,7 +13,7 @@ bundle {
name = "emheaders", name = "emheaders",
srcs = { srcs = {
"./em_*.h", "./em_*.h",
":em_path", "+em_path",
} }
} }

View file

@ -6,6 +6,6 @@ bundle {
clibrary { clibrary {
name = "string", name = "string",
srcs = { "./src/string/*.c" }, srcs = { "./src/string/*.c" },
deps = { ":headers" }, deps = { "#headers" },
} }

View file

@ -7,7 +7,7 @@ normalrule {
name = "tables", name = "tables",
outleaves = { "dmach.c", "intable.c" }, outleaves = { "dmach.c", "intable.c" },
ins = { ins = {
":mktables", "+mktables",
"lib/descr/fe", "lib/descr/fe",
}, },
commands = { commands = {
@ -20,11 +20,20 @@ cprogram {
srcs = { srcs = {
"./*.c", "./*.c",
"./*.h", "./*.h",
":tables", "+tables",
}, },
deps = { deps = {
"h:emheaders", "h+emheaders",
"h:local", "h+local",
}
}
installable {
name = "ack-pkg",
map = {
["$(INSDIR)/bin/ack"] = "+ack",
["$(INSDIR)/share/man/man1/ack.1"] = "./ack.1.X",
["$(PLATIND)/descr/fe"] = "lib/descr/fe",
} }
} }