Skip to content

Instantly share code, notes, and snippets.

@davidm
Last active December 14, 2015 17:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidm/5125764 to your computer and use it in GitHub Desktop.
Save davidm/5125764 to your computer and use it in GitHub Desktop.
Lua makefile generator in < 100 lines of code.
--[[
Simple Makefile generator in Lua 5.1.
With gcc include dependency support.
WARNING: proof of concept; not well tested. GNU style Makefile.
See premake for a more complete implementation.
(c) David Manura, 2013-03. MIT license (same as Lua).
--]]
local M = {}
-- Replaces file name extension on path s with e. Example: ext('foo.c','.o')
function M.ext(s, e) return (s:gsub('%.[^%.]+', e)) end
-- Convenience list class.
local array_mt = {}
array_mt.__index = array_mt
function array_mt.__add(a, b)
local t = {}
for _,x in ipairs(a) do t[#t+1] = x end
for _,x in ipairs(b) do t[#t+1] = x end
return setmetatable(t, array_mt)
end
function array_mt.ext(self, e)
local t = {}
for _,x in ipairs(self) do t[#t+1] = M.ext(x, e) end
return setmetatable(t, array_mt)
end
function array_mt:string() return table.concat(self, ' ') end
function array_mt.iter(self)
local i=0
return function() i = i + 1; return self[i] end
end
function M.qw(s) -- Perl-like quote operator
s = s or ''
local t = {}
for x in s:gmatch'%S+' do t[#t+1] = x end
return setmetatable(t, array_mt)
end
function M.builder()
local preambles = {'# warning: this file is autogenerated'}
local postambles = {}
local rules = {}
local default_rule
local all_outputs = M.qw()
local phonies = {}
local b = {}
local function rule_helper(cmd, output, input, default)
table.insert(rules, default and 1 or #rules+1,
array_mt.string(output)..' : '..array_mt.string(input)..
(cmd and '\n\t'..cmd or ''))
end
function b:rule(cmd, output, input, opt)
opt = opt or ''
local phony = opt:match'p'; local default = opt:match'd'
rule_helper(cmd, output, input, default)
if phony then table.insert(phonies, output[1])
else all_outputs = all_outputs + output end
end
local function helper(t, k, v) if not t[k] then table.insert(t, v); t[k] = #t end end
function b:preamble(text, name) helper(preambles, name, text) end
function b:postamble(text, name) helper(postambles, name, text) end
function b:gcc(gcc, cmd, output, input)
b:preamble([[
__MAKEDEPEND=\
@cp $*.d $*.P; \
sed -e 's/\#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \
rm -f $*.d # http://mad-scientist.net/make/autodep.html]], 'gcc')
b:rule(gcc .. ' -MD -MF ' .. output[1]:gsub('%.[^%.]+', '.d')
.. ' -c -o ' .. output[1] .. ' ' .. input[1] .. ' ' .. cmd .. '\n\t$(__MAKEDEPEND)',
output, input)
postambles[#postambles+1] = '-include ' .. M.ext(output[1], '.P')
all_outputs = all_outputs + {M.ext(output[1], '.P')}
end
function b:gen_preamble() for _, text in ipairs(preambles) do b:writeln(text) end end
function b:gen_postamble() for _, text in ipairs(postambles) do b:writeln(text) end end
function b:write(s) io.stdout:write(s) end
function b:writeln(s) io.stdout:write(s, '\n') end
function b:generate()
if #all_outputs > 0 then
b:rule('rm -f ' .. array_mt.string(all_outputs), {'clean'}, {}, 'p') end
if #phonies > 0 then rule_helper(nil, {'.PHONY'} , phonies) end
b:gen_preamble()
if default_rule then b:writeln(default_rule) end
for _, rule in ipairs(rules) do b:writeln(rule) end
b:gen_postamble()
end
return b
end
return M
-- test_lua52.lua - Example of building Lua 5.2 using makebuild.lua.
local B = dofile 'lmake.lua'
local qw = B.qw; local ext = B.ext
local CORE_SRC = qw[[
lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c
lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c
ltm.c lundump.c lvm.c lzio.c
]]
local LIB_SRC = qw[[
lauxlib.c lbaselib.c lbitlib.c lcorolib.c ldblib.c liolib.c
lmathlib.c loslib.c lstrlib.c ltablib.c loadlib.c linit.c
]]
local BASE_SRC = CORE_SRC + LIB_SRC
local ALL_SRC = BASE_SRC + qw'lua.c luac.c'
local b = B.builder()
for src in ALL_SRC:iter() do
b:gcc('gcc', '', {ext(src, '.o')}, {src})
end
b:rule('ar rcu liblua.a '..BASE_SRC:ext('.o'):string(), {'liblua.a'}, BASE_SRC:ext('.o'))
b:rule('gcc -o lua lua.c liblua.a -lm', {'lua'}, {'lua.c', 'liblua.a'})
b:rule('gcc -o luac luac.c liblua.a -lm', {'luac'}, {'luac.c', 'liblua.a'})
b:rule(nil, {'all'}, {'lua'}, 'dp')
b:generate()
# example output of running test_lua52.lua
# warning: this file is autogenerated
__MAKEDEPEND=\
@cp $*.d $*.P; \
sed -e 's/\#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \
rm -f $*.d # http://mad-scientist.net/make/autodep.html
all : lua
lapi.o : lapi.c
gcc -MD -MF lapi.d -c -o lapi.o lapi.c
$(__MAKEDEPEND)
lcode.o : lcode.c
gcc -MD -MF lcode.d -c -o lcode.o lcode.c
$(__MAKEDEPEND)
lctype.o : lctype.c
gcc -MD -MF lctype.d -c -o lctype.o lctype.c
$(__MAKEDEPEND)
ldebug.o : ldebug.c
gcc -MD -MF ldebug.d -c -o ldebug.o ldebug.c
$(__MAKEDEPEND)
ldo.o : ldo.c
gcc -MD -MF ldo.d -c -o ldo.o ldo.c
$(__MAKEDEPEND)
ldump.o : ldump.c
gcc -MD -MF ldump.d -c -o ldump.o ldump.c
$(__MAKEDEPEND)
lfunc.o : lfunc.c
gcc -MD -MF lfunc.d -c -o lfunc.o lfunc.c
$(__MAKEDEPEND)
lgc.o : lgc.c
gcc -MD -MF lgc.d -c -o lgc.o lgc.c
$(__MAKEDEPEND)
llex.o : llex.c
gcc -MD -MF llex.d -c -o llex.o llex.c
$(__MAKEDEPEND)
lmem.o : lmem.c
gcc -MD -MF lmem.d -c -o lmem.o lmem.c
$(__MAKEDEPEND)
lobject.o : lobject.c
gcc -MD -MF lobject.d -c -o lobject.o lobject.c
$(__MAKEDEPEND)
lopcodes.o : lopcodes.c
gcc -MD -MF lopcodes.d -c -o lopcodes.o lopcodes.c
$(__MAKEDEPEND)
lparser.o : lparser.c
gcc -MD -MF lparser.d -c -o lparser.o lparser.c
$(__MAKEDEPEND)
lstate.o : lstate.c
gcc -MD -MF lstate.d -c -o lstate.o lstate.c
$(__MAKEDEPEND)
lstring.o : lstring.c
gcc -MD -MF lstring.d -c -o lstring.o lstring.c
$(__MAKEDEPEND)
ltable.o : ltable.c
gcc -MD -MF ltable.d -c -o ltable.o ltable.c
$(__MAKEDEPEND)
ltm.o : ltm.c
gcc -MD -MF ltm.d -c -o ltm.o ltm.c
$(__MAKEDEPEND)
lundump.o : lundump.c
gcc -MD -MF lundump.d -c -o lundump.o lundump.c
$(__MAKEDEPEND)
lvm.o : lvm.c
gcc -MD -MF lvm.d -c -o lvm.o lvm.c
$(__MAKEDEPEND)
lzio.o : lzio.c
gcc -MD -MF lzio.d -c -o lzio.o lzio.c
$(__MAKEDEPEND)
lauxlib.o : lauxlib.c
gcc -MD -MF lauxlib.d -c -o lauxlib.o lauxlib.c
$(__MAKEDEPEND)
lbaselib.o : lbaselib.c
gcc -MD -MF lbaselib.d -c -o lbaselib.o lbaselib.c
$(__MAKEDEPEND)
lbitlib.o : lbitlib.c
gcc -MD -MF lbitlib.d -c -o lbitlib.o lbitlib.c
$(__MAKEDEPEND)
lcorolib.o : lcorolib.c
gcc -MD -MF lcorolib.d -c -o lcorolib.o lcorolib.c
$(__MAKEDEPEND)
ldblib.o : ldblib.c
gcc -MD -MF ldblib.d -c -o ldblib.o ldblib.c
$(__MAKEDEPEND)
liolib.o : liolib.c
gcc -MD -MF liolib.d -c -o liolib.o liolib.c
$(__MAKEDEPEND)
lmathlib.o : lmathlib.c
gcc -MD -MF lmathlib.d -c -o lmathlib.o lmathlib.c
$(__MAKEDEPEND)
loslib.o : loslib.c
gcc -MD -MF loslib.d -c -o loslib.o loslib.c
$(__MAKEDEPEND)
lstrlib.o : lstrlib.c
gcc -MD -MF lstrlib.d -c -o lstrlib.o lstrlib.c
$(__MAKEDEPEND)
ltablib.o : ltablib.c
gcc -MD -MF ltablib.d -c -o ltablib.o ltablib.c
$(__MAKEDEPEND)
loadlib.o : loadlib.c
gcc -MD -MF loadlib.d -c -o loadlib.o loadlib.c
$(__MAKEDEPEND)
linit.o : linit.c
gcc -MD -MF linit.d -c -o linit.o linit.c
$(__MAKEDEPEND)
lua.o : lua.c
gcc -MD -MF lua.d -c -o lua.o lua.c
$(__MAKEDEPEND)
luac.o : luac.c
gcc -MD -MF luac.d -c -o luac.o luac.c
$(__MAKEDEPEND)
liblua.a : lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o lmathlib.o loslib.o lstrlib.o ltablib.o loadlib.o linit.o
ar rcu liblua.a lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o lmathlib.o loslib.o lstrlib.o ltablib.o loadlib.o linit.o
lua : lua.c liblua.a
gcc -o lua lua.c liblua.a -lm
luac : luac.c liblua.a
gcc -o luac luac.c liblua.a -lm
clean :
rm -f lapi.o lapi.P lcode.o lcode.P lctype.o lctype.P ldebug.o ldebug.P ldo.o ldo.P ldump.o ldump.P lfunc.o lfunc.P lgc.o lgc.P llex.o llex.P lmem.o lmem.P lobject.o lobject.P lopcodes.o lopcodes.P lparser.o lparser.P lstate.o lstate.P lstring.o lstring.P ltable.o ltable.P ltm.o ltm.P lundump.o lundump.P lvm.o lvm.P lzio.o lzio.P lauxlib.o lauxlib.P lbaselib.o lbaselib.P lbitlib.o lbitlib.P lcorolib.o lcorolib.P ldblib.o ldblib.P liolib.o liolib.P lmathlib.o lmathlib.P loslib.o loslib.P lstrlib.o lstrlib.P ltablib.o ltablib.P loadlib.o loadlib.P linit.o linit.P lua.o lua.P luac.o luac.P liblua.a lua luac
.PHONY : all clean
-include lapi.P
-include lcode.P
-include lctype.P
-include ldebug.P
-include ldo.P
-include ldump.P
-include lfunc.P
-include lgc.P
-include llex.P
-include lmem.P
-include lobject.P
-include lopcodes.P
-include lparser.P
-include lstate.P
-include lstring.P
-include ltable.P
-include ltm.P
-include lundump.P
-include lvm.P
-include lzio.P
-include lauxlib.P
-include lbaselib.P
-include lbitlib.P
-include lcorolib.P
-include ldblib.P
-include liolib.P
-include lmathlib.P
-include loslib.P
-include lstrlib.P
-include ltablib.P
-include loadlib.P
-include linit.P
-include lua.P
-include luac.P
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment