Archival non-working checkin of the experimental build tool.
This commit is contained in:
parent
ffc03090ea
commit
d0bfee142b
254
first/ackbuilder.lua
Normal file
254
first/ackbuilder.lua
Normal file
|
@ -0,0 +1,254 @@
|
|||
local M = {}
|
||||
|
||||
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
|
||||
|
32
first/bouncer
Executable file
32
first/bouncer
Executable file
|
@ -0,0 +1,32 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
set -x
|
||||
|
||||
logfile=/tmp/bouncer.$$
|
||||
trap "rm -f $logfile" EXIT
|
||||
|
||||
if [ S"$1" = S"" ]; then
|
||||
>&2 echo "bouncer: syntax error: BOUNCER_WHITELIST=... bouncer <command>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
strace -eopen,chdir -o $logfile -f "$@"
|
||||
|
||||
awk -f- -F '[ "()]+' $logfile <<"EOF"
|
||||
|
||||
BEGIN {
|
||||
split(ENVIRON["BOUNCER_WHITELIST"], whitelist_array, " +");
|
||||
for (i in whitelist_array)
|
||||
whitelist[whitelist_array[i]] = 1;
|
||||
}
|
||||
|
||||
$2 == "chdir" {
|
||||
print "pid ", $1, " chdir: ", $3;
|
||||
}
|
||||
|
||||
($2 == "open") && ($5 !~ /O_CREAT/) && ($7 != -1) {
|
||||
print "pid ", $1, " open: ", $3, $7;
|
||||
}
|
||||
|
||||
EOF
|
||||
|
Loading…
Reference in a new issue