From 015804afcef85e8cfeddceb24c074ef06dbdb0ef Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 9 Jun 2016 07:14:41 +0200 Subject: [PATCH] cprogram works. --- first/ackbuilder.lua | 5 +- first/build.lua | 306 ++++++------------------------------------- modules/build.lua | 6 + 3 files changed, 50 insertions(+), 267 deletions(-) diff --git a/first/ackbuilder.lua b/first/ackbuilder.lua index 33806b3be..866412848 100644 --- a/first/ackbuilder.lua +++ b/first/ackbuilder.lua @@ -60,7 +60,7 @@ end local function basename(filename) local _, _, b = filename:find("^.*/([^/]*)$") if not b then - return "" + return filename end return b end @@ -108,7 +108,8 @@ local function filenamesof(targets, pattern) end end else - error("list of targets contains something which isn't a target") + error(string.format("list of targets contains a %s which isn't a target", + type(r))) end end end diff --git a/first/build.lua b/first/build.lua index 6dc0e49cf..47faa7f56 100644 --- a/first/build.lua +++ b/first/build.lua @@ -143,274 +143,50 @@ definerule("clibrary", end ) -clibrary { - name = "mylib", +definerule("cprogram", + { + srcs = { type="targets", default={} }, + deps = { type="targets", default={} }, + commands = { + type="strings", + default={ + "$(CC) -o %{outs[1]} %{ins}" + }, + } + }, + function (e) + local libs = filenamesof(e.deps, "%.a$") + if (#e.srcs > 0) then + for _, f in pairs(filenamesof( + { + clibrary { + name = e.name .. "/main", + srcs = e.srcs, + deps = e.deps + } + }, + "%.a$" + )) do + libs[#libs+1] = f + end + end + + return normalrule { + name = e.name, + ins = libs, + outleaves = { e.name }, + commands = e.commands, + } + end +) + +cprogram { + name = "test", srcs = { - "modules/src/string/*.c", + "foo.c", }, deps = { - "modules:headers" + "modules:string" } } ---[[ --- --- Targets: --- --- { --- dir = target's build directory --- outs = target's object files --- is = { set of rule types which made the target } --- } -function M.subenv(p) - local e = p[1] - setmetable(p, {__index = e}) - return p -end - -local function check_filename(fn) - if type(fn) == "table" then - for _, f in ipairs(fn) do - check_filename(f) - end - else - if fn:find("%s") then - error("Filename '"+fn+"' contains spaces. This will make the build system sad.") - end - end -end - -function M.basename(fn) - if type(fn) == "table" then - local nfn = {} - for _, f in ipairs(fn) do - nfn[#nfn+1] = M.basename(f) - end - return nfn - else - local _, _, base = fn:find("([^/]*)$") - return base - end -end - -function M.flatten(t) - if t == nil then - return {} - end - - local tt = {} - for _, subt in ipairs(t) do - if type(subt) == "table" then - for _, subt in ipairs(M.flatten(subt)) do - tt[#tt+1] = subt - end - else - tt[#tt+1] = subt - end - end - return tt -end - -local function append(...) - local ts = {} - for _, t in ipairs({...}) do - for _, v in ipairs(t) do - ts[#ts+1] = v - end - end - return ts -end - -local function settotable(s) - local t = {} - for k in pairs(s) do - t[#t+1] = k - end - return t -end - -local function asstring(t) - return table.concat(M.flatten(t), " ") -end - -local function emit(...) - for _, s in ipairs({...}) do - io.stdout:write(s) - end -end - -function M.rawtarget(p) - local description = p.description or error("no description supplied") - local ins = M.flatten(p.ins) - local outs = M.flatten(p.outs) - - local cmd = p.command - if type(cmd) ~= "table" then - cmd = {cmd} - end - - for _, s in ipairs(ins) do - check_filename(s) - end - for _, s in ipairs(outs) do - check_filename(s) - end - - emit(outs[1], ":") - for _, s in ipairs(ins) do - emit(" ", s) - end - emit("\n") - - emit("\t@echo ", p.description, "\n") - - emit("\t$(hide) ", table.concat(cmd, " && "), "\n") - - for i = 2, #outs do - emit(outs[i], ": ", outs[1], "\n") - end - - emit("\n") -end - -function M.export(p) - local e = p[1] - local dest = p.dest or error("no export destination provided") - local deps = p.deps or error("nothing to export") - - local fdeps = M.flatten(deps) - - if #fdeps ~= 1 then - error("you can only export one thing at a time") - end - - return M.rawtarget {e, - ins=deps, - outs={dest}, - command="cp "..fdeps[1].." "..dest, - description="EXPORT "..dest - } -end - -function M.hermetic(p) - local e = p[1] - local ins = M.flatten(p.ins) - local deps = M.flatten(p.deps) - local baseouts = p.baseouts or error("you must specify some baseouts") - local description = p.description - - local absouts = {} - local path = e.PATH .. "/" .. p.baseouts[1] .. ".env" - - for _, s in ipairs(M.flatten(p.baseouts)) do - absouts[#absouts+1] = path .. "/" .. s - end - - local dirset = {} - for _, s in ipairs(absouts) do - local d = s:gsub("^(.*/).*$", "%1") - if d then - dirset[d] = true - end - end - - local newcmd = { - "rm -rf "..path, - "mkdir -p "..asstring(settotable(dirset)), - "ln -srf "..asstring(append(ins, deps)).." "..path, - "cd "..path - } - for _, s in ipairs(p.command) do - newcmd[#newcmd+1] = "(" .. s .. ")" - end - - M.rawtarget {e, - ins={ins, unpack(deps)}, - outs=absouts, - command=newcmd, - description=description - } - - return absouts -end - -function M.cfile(p) - local e = p[1] - local src = p.src - local deps = p.deps or {} - - local outfile = p.src:gsub("%.c$", ".o") - local basesrc = M.basename(p.src) - - return M.hermetic {e, - ins={src}, - deps=deps, - baseouts={outfile}, - command={e.CC.." "..e.CFLAGS.." -c -o "..outfile.." "..basesrc}, - description="CC "..src - } -end - -function M.cprogram(p) - local e = p[1] - local name = p.name or error("cprogram must have a name specified") - local deps = p.deps or {} - local libs = p.libraries or {} - local headers = p.headers or {} - - if p.srcs then - local mainlib = M.clibrary {e, - name=name..".a", - deps=deps, - srcs=p.srcs, - headers=headers - } - - deps = append(deps, {mainlib}) - end - - local libflags = {} - for _, s in ipairs(libs) do - libflags[#libflags+1] = "-l"..s - end - - return M.hermetic {e, - ins=deps, - baseouts={name}, - command={e.CC.." "..e.CFLAGS.." -o "..name.." "..asstring(M.basename(deps)).." "..asstring(libflags)}, - description="CLINK "..name - } -end - -function M.clibrary(p) - local e = p[1] - local name = p.name or error("clibrary must have a name specified") - local deps = M.flatten(p.deps) - local srcs = M.flatten(p.srcs) - local headers = M.flatten(p.headers) - - local baseouts = {name} - - local objs = deps - for _, f in ipairs(srcs) do - objs[#objs+1] = M.cfile {e, - src=f, - deps=headers - } - end - - return M.hermetic {e, - ins=append(objs, headers), - baseouts=baseouts, - command={ - e.AR.." q "..name.." "..asstring(M.basename(objs)), - e.RANLIB.." "..name, - }, - description="CLIBRARY "..name - } -end - -emit("hide = @\n") - -return M ---]] diff --git a/modules/build.lua b/modules/build.lua index 4297f59d0..4ad93bbea 100644 --- a/modules/build.lua +++ b/modules/build.lua @@ -3,3 +3,9 @@ bundle { srcs = { "./h/*.h" } } +clibrary { + name = "string", + srcs = { "./src/string/*.c" }, + deps = { ":headers" }, +} +