Ver código fonte

Multiple build files work. Use deps intelligently. clibraries.

David Given 8 anos atrás
pai
commit
f47bb49c1f
3 arquivos alterados com 130 adições e 40 exclusões
  1. 35 20
      first/ackbuilder.lua
  2. 90 20
      first/build.lua
  3. 5 0
      modules/build.lua

+ 35 - 20
first/ackbuilder.lua

@@ -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,

+ 90 - 20
first/build.lua

@@ -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,23 +74,83 @@ 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
 
-cfile {
-	name = "testfile-foo",
-	srcs = "foo.c",
-}
+		return normalrule {
+			name = e.name,
+			ins = e.srcs,
+			outleaves = outleaves,
+			label = e.label,
+			commands = commands
+		}
+	end
+)
 
-cfile {
-	name = "testfile-bar",
-	srcs = {"bar.c", ":mkheader"},
+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"
+	}
 }
 
 --[[

+ 5 - 0
modules/build.lua

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