diff --git a/build.lua b/build.lua new file mode 100644 index 000000000..8c59429d0 --- /dev/null +++ b/build.lua @@ -0,0 +1,7 @@ +installable { + name = "ack", + map = { + "util/ack+ack-pkg" + } +} + diff --git a/first/ackbuilder.lua b/first/ackbuilder.lua index 525e6051c..2d198974b 100644 --- a/first/ackbuilder.lua +++ b/first/ackbuilder.lua @@ -3,6 +3,7 @@ local posix = require("posix") -- Targets: -- -- { +-- fullname = full name of target -- dir = target's build directory -- outs = target's object files -- is = { set of rule types which made the target } @@ -60,6 +61,10 @@ end local function filenamesof(targets, pattern) local f = {} if targets then + if targets.is then + targets = {targets} + end + for _, r in pairs(targets) do if (type(r) == "table") and r.is then if r.outs then @@ -141,7 +146,7 @@ end local function fpairs(collection) if (type(collection) == "string") or collection.is then - return tpairs({collection}) + return fpairs({collection}) end return pairs(filenamesof(collection)) @@ -249,7 +254,7 @@ local function loadtarget(targetname) end local target - if not targetname:find(":") then + if not targetname:find("%+") then local files if targetname:find("[?*]") then files = posix.glob(targetname) @@ -268,7 +273,7 @@ local function loadtarget(targetname) } targets[targetname] = target else - local _, _, filepart, targetpart = targetname:find("^([^:]*):([%w-_]+)$") + local _, _, filepart, targetpart = targetname:find("^([^+]*)%+([%w-_]+)$") if not filepart or not targetpart then error(string.format("malformed target name '%s'", targetname)) end @@ -297,16 +302,16 @@ local typeconverters = { end local o = {} - for _, s in ipairs(i) do + for k, s in pairs(i) do if (type(s) == "table") and s.is then - o[#o+1] = s + o[k] = s elseif (type(s) == "string") then - if s:find("^:") then + if s:find("^%+") then s = cwd..s elseif s:find("^%./") then s = concatpath(cwd, s) end - o[#o+1] = loadtarget(s) + o[k] = loadtarget(s) else error(string.format("member of target list '%s' is not a string or a target", propname)) @@ -374,11 +379,13 @@ local function definerule(rulename, types, cb) end args.environment = environment + args.fullname = cwd.."+"..args.name local result = cb(args) or {} result.is = result.is or {} result.is[rulename] = true - targets[cwd..":"..args.name] = result + result.fullname = args.fullname + targets[result.fullname] = result return result end end @@ -398,6 +405,11 @@ function environment:rule(ins, outs) emit(firstout..":\n") end +function environment:phony(ins, outs) + emit(".PHONY:", outs, "\n") + self:rule(ins, outs) +end + function environment:label(...) local s = table.concat({...}, " ") emit("\t@echo", s, "\n") @@ -411,7 +423,9 @@ function environment:mkdirs(dirs) end function environment:exec(commands) - emit("\t$(hide)", table.concat(commands, " && "), "\n") + for _, s in ipairs(commands) do + emit("\t$(hide)", s, "\n") + end end function environment:endrule() @@ -428,7 +442,7 @@ definerule("simplerule", }, function (e) 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)) local vars = inherit(e.vars, { @@ -445,6 +459,51 @@ definerule("simplerule", 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 -- ----------------------------------------------------------------------------- diff --git a/h/build.lua b/h/build.lua index 25b7e3324..aca6a8fd4 100644 --- a/h/build.lua +++ b/h/build.lua @@ -13,7 +13,7 @@ bundle { name = "emheaders", srcs = { "./em_*.h", - ":em_path", + "+em_path", } } diff --git a/modules/build.lua b/modules/build.lua index 4ad93bbea..e3fb471df 100644 --- a/modules/build.lua +++ b/modules/build.lua @@ -6,6 +6,6 @@ bundle { clibrary { name = "string", srcs = { "./src/string/*.c" }, - deps = { ":headers" }, + deps = { "#headers" }, } diff --git a/util/ack/build.lua b/util/ack/build.lua index 3e1b77167..f30eedf4a 100644 --- a/util/ack/build.lua +++ b/util/ack/build.lua @@ -7,7 +7,7 @@ normalrule { name = "tables", outleaves = { "dmach.c", "intable.c" }, ins = { - ":mktables", + "+mktables", "lib/descr/fe", }, commands = { @@ -20,11 +20,20 @@ cprogram { srcs = { "./*.c", "./*.h", - ":tables", + "+tables", }, deps = { - "h:emheaders", - "h:local", + "h+emheaders", + "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", } }