master setup.lua
  1#!/bin/lua
  2
  3-- prevent accidental use of undefined globals
  4setmetatable(_G, {__index=function(_, var) error('undefined global \''..var..'\'') end})
  5
  6-- Lua 5.1 compatibility
  7do
  8	local os_execute = os.execute
  9	os.execute = function(cmd)
 10		local ret = os_execute(cmd)
 11		return ret == true or ret == 0
 12	end
 13end
 14
 15basedir = arg[0]:match('(.*)/') or '.'
 16
 17if not os.execute('exec test -f config.lua') then
 18	os.execute('exec cp '..basedir..'/config.def.lua config.lua')
 19end
 20
 21dofile(basedir..'/ninja.lua')
 22config = dofile 'config.lua'
 23if not config.prefix then
 24	config.prefix = ''
 25end
 26if not config.distdir then
 27	config.distdir = 'dist'
 28end
 29
 30local function shellpath(path, base)
 31	if path == '.' then return base end
 32	local abs = path:find('^/')
 33	path = "'"..path:gsub([[']], [['\'']]).."'"
 34	if abs then return path end
 35	return base..'/'..path
 36end
 37local f = io.open('paths.sh', 'w')
 38f:write(string.format([[
 39basedir=%s
 40builddir=%s
 41distdir=%s
 42]], shellpath(basedir, '$PWD'), shellpath(config.builddir, '$PWD'), shellpath(config.distdir, '$basedir')))
 43f:close()
 44
 45local function gen(gendir)
 46	local dir = basedir..'/'..gendir
 47	local outdir = config.builddir..'/'..gendir
 48	pkg={
 49		name=gendir:match('[^/]*$'),
 50		dir=dir,
 51		gendir=gendir,
 52		srcdir=dir..'/src',
 53		outdir=outdir,
 54		inputs={
 55			index={},
 56			fspec={},
 57			gen={},
 58			fetch={},
 59		},
 60		fspec={},
 61	}
 62	assert(os.execute(('exec mkdir -p %s %s'):format(gendir, outdir)))
 63	io.output(gendir..'/local.ninja.tmp')
 64	set('gendir', gendir)
 65	if gendir ~= '.' then
 66		set('dir', '$basedir/$gendir')
 67		set('outdir', '$builddir/$gendir')
 68		set('srcdir', '$dir/src')
 69	end
 70	load('gen.lua')
 71
 72	build('phony', '$gendir/gen', pkg.inputs.gen)
 73
 74	if pkg.hdrs then
 75		phony('headers', pkg.hdrs)
 76		if pkg.hdrs.install then
 77			for hdr in iterstrings(pkg.hdrs) do
 78				if not hdr:hasprefix('$outdir/include/') then
 79					error('header is not in $outdir/include: '..hdr)
 80				end
 81				file(hdr:sub(9), '644', hdr)
 82			end
 83		end
 84	end
 85	if pkg.deps then
 86		phony('deps', pkg.deps)
 87	end
 88
 89	if next(pkg.fspec) then
 90		local out = outdir..'/local.fspec'
 91		local tmp = out..'.tmp'
 92		local f = assert(io.open(tmp, 'w'))
 93		local srcs = {}
 94		for _, path, fspec in sortedpairs(pkg.fspec) do
 95			f:write(('/%s\n'):format(path))
 96			for _, k in ipairs{'type', 'mode', 'source', 'target'} do
 97				local v = fspec[k]
 98				if v then
 99					f:write(('%s=%s\n'):format(k, v))
100				end
101			end
102			f:write('\n')
103			local src = fspec.source
104			if src then
105				srcs[#srcs + 1] = src
106			end
107		end
108		f:close()
109		if os.execute(('exec cmp -s %s %s'):format(tmp, out)) then
110			os.remove(tmp)
111		else
112			os.rename(tmp, out)
113		end
114		build('fspec-hash', '$outdir/local-hashed.fspec', {'$outdir/local.fspec', '|', '$builddir/pkg/fspec-sync/host/fspec-hash', srcs})
115		table.insert(pkg.inputs.fspec, '$outdir/local-hashed.fspec')
116	end
117	if next(pkg.inputs.index) then
118		build('cat', '$outdir/root.index', pkg.inputs.index, {
119			description='	INDEX	$outdir/root.index',
120		})
121	else
122		build('empty', '$outdir/root.index')
123	end
124	if next(pkg.inputs.fspec) then
125		build('cat', '$outdir/tree.fspec', pkg.inputs.fspec, {
126			description = '	FSPEC	$outdir/tree.fspec',
127		})
128	else
129		build('empty', '$outdir/tree.fspec')
130	end
131	build('phony', '$dir/root', pkg.inputs.root)
132	io.close()
133	os.rename(gendir..'/local.ninja.tmp', gendir..'/local.ninja')
134	if gendir == '.' then
135		os.execute('exec ln -sf local.ninja build.ninja')
136	end
137end
138
139function subgen(dir)
140	local file = '$gendir/'..dir..'/local.ninja'
141	subninja(file)
142	table.insert(pkg.inputs.gen, '$gendir/'..dir..'/gen')
143	table.insert(pkg.inputs.index, '$outdir/'..dir..'/root.index')
144	table.insert(pkg.inputs.fspec, '$outdir/'..dir..'/tree.fspec')
145	local oldpkg, oldout = pkg, io.output()
146	if pkg.gendir ~= '.' then
147		dir = pkg.gendir..'/'..dir
148	end
149	gen(dir)
150	pkg = oldpkg
151	io.output(oldout)
152end
153
154gen('.')