mirror of https://github.com/natnat-mc/moonbuild
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2522 lines
59 KiB
2522 lines
59 KiB
#!/usr/bin/env lua5.3
|
|
do
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild._" ] = function( ... ) local arg = _G.arg;
|
|
local gmatch, match, gsub
|
|
do
|
|
local _obj_0 = string
|
|
gmatch, match, gsub = _obj_0.gmatch, _obj_0.match, _obj_0.gsub
|
|
end
|
|
local insert, remove, concat, sub, sort
|
|
do
|
|
local _obj_0 = table
|
|
insert, remove, concat, sub, sort = _obj_0.insert, _obj_0.remove, _obj_0.concat, _obj_0.sub, _obj_0.sort
|
|
end
|
|
local _fs = require('moonbuild._fs')
|
|
local _cmd = require('moonbuild._cmd')
|
|
local _util = require('moonbuild._util')
|
|
local _common = require('moonbuild._common')
|
|
local _ = { }
|
|
for k, lib in pairs({
|
|
_fs = _fs,
|
|
_cmd = _cmd,
|
|
_util = _util,
|
|
_common = _common
|
|
}) do
|
|
_[k] = lib
|
|
local _list_0 = lib()
|
|
for _index_0 = 1, #_list_0 do
|
|
local n = _list_0[_index_0]
|
|
_[n] = lib[n]
|
|
end
|
|
end
|
|
return _
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild._cmd" ] = function( ... ) local arg = _G.arg;
|
|
local parseargs, escape
|
|
do
|
|
local _obj_0 = require('moonbuild._cmd.common')
|
|
parseargs, escape = _obj_0.parseargs, _obj_0.escape
|
|
end
|
|
local ok, cmd, backend = false, nil, nil
|
|
if not (ok) then
|
|
ok, cmd = pcall(function()
|
|
return require('moonbuild._cmd.posix')
|
|
end)
|
|
backend = 'posix'
|
|
end
|
|
if not (ok) then
|
|
ok, cmd = pcall(function()
|
|
return require('moonbuild._cmd.lua')
|
|
end)
|
|
backend = 'lua'
|
|
end
|
|
if not (ok) then
|
|
error("unable to load any cmd library, tried luaposix and posix commands")
|
|
end
|
|
do
|
|
local _tbl_0 = { }
|
|
for k, v in pairs(cmd) do
|
|
_tbl_0[k] = v
|
|
end
|
|
cmd = _tbl_0
|
|
end
|
|
cmd.backend = backend
|
|
cmd.parseargs = parseargs
|
|
cmd.escape = escape
|
|
return setmetatable(cmd, {
|
|
__call = function(self)
|
|
return {
|
|
'cmd',
|
|
'cmdrst',
|
|
'sh'
|
|
}
|
|
end
|
|
})
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild._cmd.common" ] = function( ... ) local arg = _G.arg;
|
|
local gsub, sub, match
|
|
do
|
|
local _obj_0 = string
|
|
gsub, sub, match = _obj_0.gsub, _obj_0.sub, _obj_0.match
|
|
end
|
|
local concat
|
|
concat = table.concat
|
|
local specialchars = {
|
|
['\"'] = '\\\"',
|
|
['\\'] = '\\\\',
|
|
['\''] = '\\\'',
|
|
['\n'] = '\\n',
|
|
['\r'] = '\\r',
|
|
['\t'] = '\\t'
|
|
}
|
|
local replacespecialchar
|
|
replacespecialchar = function(c)
|
|
return specialchars[c] or c
|
|
end
|
|
local escape
|
|
escape = function(arg)
|
|
if match(arg, "^[a-zA-Z0-9_.-]+$") then
|
|
return arg
|
|
end
|
|
return '"' .. (gsub(arg, "([\"\\\n\r\t])", replacespecialchar)) .. '"'
|
|
end
|
|
local parseargs
|
|
parseargs = function(argstr)
|
|
local state = 'normal'
|
|
local current, ci = { }, 1
|
|
local args, ai = { }, 1
|
|
local c = nil
|
|
local i = 0
|
|
local running = true
|
|
local add
|
|
add = function()
|
|
current[ci], ci = c, ci + 1
|
|
end
|
|
local push
|
|
push = function()
|
|
if ci ~= 1 then
|
|
args[ai], ai, current, ci = (concat(current)), ai + 1, { }, 1
|
|
end
|
|
end
|
|
local addv
|
|
addv = function(v)
|
|
current[ci], ci = v, ci + 1
|
|
end
|
|
local fail
|
|
fail = function(msg)
|
|
return error("failed to parse: " .. tostring(msg) .. " in state " .. tostring(state) .. " at pos " .. tostring(i), 2)
|
|
end
|
|
local finish
|
|
finish = function()
|
|
running = false
|
|
end
|
|
local EOF = ''
|
|
while running do
|
|
i = i + 1
|
|
c = sub(argstr, i, i)
|
|
local _exp_0 = state
|
|
if 'normal' == _exp_0 then
|
|
local _exp_1 = c
|
|
if '\"' == _exp_1 then
|
|
state = 'doublequote'
|
|
elseif '\'' == _exp_1 then
|
|
state = 'singlequote'
|
|
elseif ' ' == _exp_1 then
|
|
push()
|
|
elseif '\n' == _exp_1 then
|
|
push()
|
|
elseif '\t' == _exp_1 then
|
|
push()
|
|
elseif '\\' == _exp_1 then
|
|
state = 'backslashnormal'
|
|
elseif EOF == _exp_1 then
|
|
push()
|
|
finish()
|
|
else
|
|
add()
|
|
end
|
|
elseif 'doublequote' == _exp_0 then
|
|
local _exp_1 = c
|
|
if '\"' == _exp_1 then
|
|
state = 'normal'
|
|
elseif '\\' == _exp_1 then
|
|
state = 'backslashdoublequote'
|
|
elseif EOF == _exp_1 then
|
|
fail("unexpected EOF")
|
|
else
|
|
add()
|
|
end
|
|
elseif 'singlequote' == _exp_0 then
|
|
local _exp_1 = c
|
|
if '\'' == _exp_1 then
|
|
state = 'normal'
|
|
elseif EOF == _exp_1 then
|
|
fail("unexpected EOF")
|
|
else
|
|
add()
|
|
end
|
|
elseif 'backslashnormal' == _exp_0 then
|
|
local _exp_1 = c
|
|
if '\n' == _exp_1 then
|
|
state = 'normal'
|
|
elseif EOF == _exp_1 then
|
|
fail("unexpected EOF")
|
|
else
|
|
add()
|
|
state = 'normal'
|
|
end
|
|
elseif 'backslashdoublequote' == _exp_0 then
|
|
local _exp_1 = c
|
|
if '$' == _exp_1 then
|
|
add()
|
|
state = 'doublequote'
|
|
elseif '`' == _exp_1 then
|
|
add()
|
|
state = 'doublequote'
|
|
elseif '\"' == _exp_1 then
|
|
add()
|
|
state = 'doublequote'
|
|
elseif '\\' == _exp_1 then
|
|
add()
|
|
state = 'doublequote'
|
|
elseif '\n' == _exp_1 then
|
|
state = 'doublequote'
|
|
elseif EOF == _exp_1 then
|
|
fail("unexpected EOF")
|
|
else
|
|
addv('\\')
|
|
add()
|
|
state = 'doublequote'
|
|
end
|
|
end
|
|
end
|
|
return args
|
|
end
|
|
return {
|
|
escape = escape,
|
|
parseargs = parseargs
|
|
}
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild._cmd.lua" ] = function( ... ) local arg = _G.arg;
|
|
local escape
|
|
escape = require('moonbuild._cmd.common').escape
|
|
local flatten
|
|
flatten = require('moonbuild._common').flatten
|
|
local execute
|
|
execute = require('moonbuild.compat.execute').execute
|
|
local popen
|
|
popen = io.popen
|
|
local concat
|
|
concat = table.concat
|
|
local cmdline
|
|
cmdline = function(...)
|
|
return concat((function(...)
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
local _list_0 = flatten(...)
|
|
for _index_0 = 1, #_list_0 do
|
|
local arg = _list_0[_index_0]
|
|
_accum_0[_len_0] = escape(arg)
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
return _accum_0
|
|
end)(...), ' ')
|
|
end
|
|
local cmd
|
|
cmd = function(...)
|
|
local ok, ret, code = execute(cmdline(...))
|
|
if not (ok) then
|
|
return error("command " .. tostring(first(...)) .. " exited with " .. tostring(code) .. " (" .. tostring(ret) .. ")")
|
|
end
|
|
end
|
|
local cmdrst
|
|
cmdrst = function(...)
|
|
local fd, err = popen(cmdline(...))
|
|
if not (fd) then
|
|
error(err)
|
|
end
|
|
local data = fd:read('*a')
|
|
fd:close()
|
|
return data
|
|
end
|
|
local sh
|
|
sh = function(cli)
|
|
local ok, ret, code = execute(cli)
|
|
if not (ok) then
|
|
return error("command '" .. tostring(cli) .. "' exited with " .. tostring(code) .. " (" .. tostring(ret) .. ")")
|
|
end
|
|
end
|
|
return {
|
|
cmd = cmd,
|
|
cmdrst = cmdrst,
|
|
sh = sh
|
|
}
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild._cmd.posix" ] = function( ... ) local arg = _G.arg;
|
|
local spawn
|
|
spawn = require('posix').spawn
|
|
local fork, execp, pipe, dup2, _exit, close
|
|
do
|
|
local _obj_0 = require('posix.unistd')
|
|
fork, execp, pipe, dup2, _exit, close = _obj_0.fork, _obj_0.execp, _obj_0.pipe, _obj_0.dup2, _obj_0._exit, _obj_0.close
|
|
end
|
|
local fdopen
|
|
fdopen = require('posix.stdio').fdopen
|
|
local wait
|
|
wait = require('posix.sys.wait').wait
|
|
local flatten, first
|
|
do
|
|
local _obj_0 = require('moonbuild._common')
|
|
flatten, first = _obj_0.flatten, _obj_0.first
|
|
end
|
|
local remove
|
|
remove = table.remove
|
|
local cmd
|
|
cmd = function(...)
|
|
local code, ty = spawn(flatten(...))
|
|
if ty ~= 'exited' or code ~= 0 then
|
|
return error("command " .. tostring(first(...)) .. " " .. tostring(ty) .. " with code " .. tostring(code))
|
|
end
|
|
end
|
|
local cmdrst
|
|
cmdrst = function(...)
|
|
local rd, wr = pipe()
|
|
local pid, err = fork()
|
|
if pid == 0 then
|
|
dup2(wr, 1)
|
|
close(rd)
|
|
local args = flatten(...)
|
|
local c = remove(args, 1)
|
|
execp(c, args)
|
|
return _exit(1)
|
|
end
|
|
if pid == nil then
|
|
close(rd)
|
|
close(wr)
|
|
error("command " .. tostring(first(...)) .. " failed to start: couldn't fork(): " .. tostring(err))
|
|
end
|
|
close(wr)
|
|
local fd = fdopen(rd, 'r')
|
|
local data = fd:read('*a')
|
|
fd:close()
|
|
close(rd)
|
|
local _, ty, code = wait(pid)
|
|
if ty ~= 'exited' or code ~= 0 then
|
|
error("command " .. tostring(first(...)) .. " " .. tostring(ty) .. " with code " .. tostring(code))
|
|
end
|
|
return data
|
|
end
|
|
local sh
|
|
sh = function(cli)
|
|
return cmd('sh', '-c', cli)
|
|
end
|
|
return {
|
|
cmd = cmd,
|
|
cmdrst = cmdrst,
|
|
sh = sh
|
|
}
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild._common" ] = function( ... ) local arg = _G.arg;
|
|
local sort, concat
|
|
do
|
|
local _obj_0 = table
|
|
sort, concat = _obj_0.sort, _obj_0.concat
|
|
end
|
|
local huge
|
|
huge = math.huge
|
|
local match, sub
|
|
do
|
|
local _obj_0 = string
|
|
match, sub = _obj_0.match, _obj_0.sub
|
|
end
|
|
local common = { }
|
|
local flatten
|
|
flatten = function(list, ...)
|
|
if (select('#', ...)) ~= 0 then
|
|
return flatten({
|
|
list,
|
|
...
|
|
})
|
|
end
|
|
local t = type(list)
|
|
local _exp_0 = t
|
|
if 'nil' == _exp_0 then
|
|
return { }
|
|
elseif 'string' == _exp_0 then
|
|
return {
|
|
list
|
|
}
|
|
elseif 'number' == _exp_0 then
|
|
return {
|
|
tostring(list)
|
|
}
|
|
elseif 'boolean' == _exp_0 then
|
|
return {
|
|
list
|
|
}
|
|
elseif 'table' == _exp_0 then
|
|
local keys
|
|
do
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for k in pairs(list) do
|
|
_accum_0[_len_0] = k
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
keys = _accum_0
|
|
end
|
|
sort(keys)
|
|
local elements, i = { }, 1
|
|
for _index_0 = 1, #keys do
|
|
local k = keys[_index_0]
|
|
if (type(k)) == 'number' then
|
|
local _list_0 = (flatten(list[k]))
|
|
for _index_1 = 1, #_list_0 do
|
|
local e = _list_0[_index_1]
|
|
elements[i], i = e, i + 1
|
|
end
|
|
else
|
|
return {
|
|
list
|
|
}
|
|
end
|
|
end
|
|
return setmetatable(elements, {
|
|
__tostring = function(self)
|
|
return concat(self, ' ')
|
|
end
|
|
})
|
|
else
|
|
return error("can't flatten elements of type " .. tostring(t))
|
|
end
|
|
end
|
|
local first
|
|
first = function(list, ...)
|
|
local t = type(list)
|
|
local _exp_0 = t
|
|
if 'nil' == _exp_0 then
|
|
if (select('#', ...)) == 0 then
|
|
return nil
|
|
else
|
|
return first(...)
|
|
end
|
|
elseif 'string' == _exp_0 then
|
|
return list
|
|
elseif 'number' == _exp_0 then
|
|
return tostring(list)
|
|
elseif 'boolean' == _exp_0 then
|
|
return list
|
|
elseif 'table' == _exp_0 then
|
|
local min = huge
|
|
for k in pairs(list) do
|
|
if (type(k)) == 'number' then
|
|
if k < min then
|
|
min = k
|
|
end
|
|
else
|
|
return list
|
|
end
|
|
end
|
|
return first(list[min])
|
|
else
|
|
return error("can't find first of type " .. tostring(t))
|
|
end
|
|
end
|
|
local foreach
|
|
foreach = function(list, fn)
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
local _list_0 = flatten(list)
|
|
for _index_0 = 1, #_list_0 do
|
|
local v = _list_0[_index_0]
|
|
_accum_0[_len_0] = fn(v)
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
return _accum_0
|
|
end
|
|
local filter
|
|
filter = function(list, fn)
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
local _list_0 = flatten(list)
|
|
for _index_0 = 1, #_list_0 do
|
|
local v = _list_0[_index_0]
|
|
if fn(v) then
|
|
_accum_0[_len_0] = v
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
end
|
|
return _accum_0
|
|
end
|
|
local includes
|
|
includes = function(list, v)
|
|
if list == v then
|
|
return true
|
|
end
|
|
if (type(list)) == 'table' then
|
|
for k, e in pairs(list) do
|
|
if (type(k)) == 'number' then
|
|
if includes(e, v) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if (type(list)) == 'number' then
|
|
return (tostring(list)) == (tostring(v))
|
|
end
|
|
return false
|
|
end
|
|
local patget
|
|
patget = function(s, pat)
|
|
local prefix, suffix = match(pat, '^(.*)%%(.*)$')
|
|
if not (prefix) then
|
|
return s == pat and s or nil
|
|
end
|
|
if (sub(s, 1, #prefix)) == prefix and (suffix == '' or (sub(s, -#suffix)) == suffix) then
|
|
return sub(s, #prefix + 1, -#suffix - 1)
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
local patset
|
|
patset = function(s, rep)
|
|
local prefix, suffix = match(rep, '^(.*)%%(.*)$')
|
|
if prefix then
|
|
return prefix .. s .. suffix
|
|
else
|
|
return rep
|
|
end
|
|
end
|
|
local patsubst
|
|
patsubst = function(s, pat, rep)
|
|
local prefix, suffix = match(pat, '^(.*)%%(.*)$')
|
|
local rprefix, rsuffix = match(rep, '^(.*)%%(.*)$')
|
|
local t = type(s)
|
|
local f = false
|
|
if t == 'nil' then
|
|
return nil
|
|
end
|
|
if t == 'number' then
|
|
t = 'string'
|
|
s = tostring(s)
|
|
end
|
|
if t == 'string' then
|
|
t = 'table'
|
|
s = {
|
|
s
|
|
}
|
|
f = true
|
|
end
|
|
if t ~= 'table' then
|
|
error("can't substitute patterns on type " .. tostring(t))
|
|
end
|
|
local r, i = { }, 1
|
|
local _list_0 = flatten(s)
|
|
for _index_0 = 1, #_list_0 do
|
|
local s = _list_0[_index_0]
|
|
if not prefix then
|
|
if s == pat then
|
|
if rprefix then
|
|
r[i], i = rprefix .. s .. rsuffix, i + 1
|
|
else
|
|
r[i], i = rep, i + 1
|
|
end
|
|
end
|
|
elseif (sub(s, 1, #prefix)) == prefix and (suffix == '' or (sub(s, -#suffix)) == suffix) then
|
|
if rprefix then
|
|
r[i], i = rprefix .. (sub(s, #prefix + 1, -#suffix - 1)) .. rsuffix, i + 1
|
|
else
|
|
r[i], i = rep, i + 1
|
|
end
|
|
end
|
|
end
|
|
return f and r[1] or r
|
|
end
|
|
local exclude
|
|
exclude = function(list, ...)
|
|
local exclusions = flatten(...)
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
local _list_0 = flatten(list)
|
|
for _index_0 = 1, #_list_0 do
|
|
local v = _list_0[_index_0]
|
|
if not includes(exclusions, v) then
|
|
_accum_0[_len_0] = v
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
end
|
|
return _accum_0
|
|
end
|
|
local min
|
|
min = function(list)
|
|
local m = list[1]
|
|
for i = 2, #list do
|
|
local e = list[i]
|
|
if e < m then
|
|
m = e
|
|
end
|
|
end
|
|
return m
|
|
end
|
|
local max
|
|
max = function(list)
|
|
local m = list[1]
|
|
for i = 2, #list do
|
|
local e = list[i]
|
|
if e > m then
|
|
m = e
|
|
end
|
|
end
|
|
return m
|
|
end
|
|
local minmax
|
|
minmax = function(list)
|
|
local m = list[1]
|
|
local M = list[1]
|
|
for i = 2, #list do
|
|
local e = list[i]
|
|
if e < m then
|
|
m = e
|
|
end
|
|
if e > M then
|
|
M = e
|
|
end
|
|
end
|
|
return m, M
|
|
end
|
|
common.flatten = flatten
|
|
common.first = first
|
|
common.foreach = foreach
|
|
common.filter = filter
|
|
common.includes = includes
|
|
common.patget = patget
|
|
common.patset = patset
|
|
common.patsubst = patsubst
|
|
common.min = min
|
|
common.max = max
|
|
common.minmax = minmax
|
|
return setmetatable(common, {
|
|
__call = function(self)
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for k in pairs(common) do
|
|
_accum_0[_len_0] = k
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
return _accum_0
|
|
end
|
|
})
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild._fs" ] = function( ... ) local arg = _G.arg;
|
|
local remove, concat
|
|
do
|
|
local _obj_0 = table
|
|
remove, concat = _obj_0.remove, _obj_0.concat
|
|
end
|
|
local gmatch, match, gsub, sub
|
|
do
|
|
local _obj_0 = string
|
|
gmatch, match, gsub, sub = _obj_0.gmatch, _obj_0.match, _obj_0.gsub, _obj_0.sub
|
|
end
|
|
local ok, fs, backend = false, nil, nil
|
|
if not (ok) then
|
|
ok, fs = pcall(function()
|
|
return require('moonbuild._fs.posix')
|
|
end)
|
|
backend = 'posix'
|
|
end
|
|
if not (ok) then
|
|
ok, fs = pcall(function()
|
|
return require('moonbuild._fs.lfs')
|
|
end)
|
|
backend = 'lfs'
|
|
end
|
|
if not (ok) then
|
|
ok, fs = pcall(function()
|
|
return require('moonbuild._fs.cmd')
|
|
end)
|
|
backend = 'cmd'
|
|
end
|
|
if not (ok) then
|
|
error("unable to load any fs library, tried luaposix, luafilesystem and posix commands")
|
|
end
|
|
local DISABLED = (function()
|
|
return DISABLED
|
|
end)
|
|
local NIL = (function()
|
|
return NIL
|
|
end)
|
|
local cacheenabled = true
|
|
local caches = { }
|
|
local clearcache
|
|
clearcache = function()
|
|
for k, v in pairs(caches) do
|
|
v.clearcache()
|
|
end
|
|
end
|
|
local clearentry
|
|
clearentry = function(entry)
|
|
for k, v in pairs(caches) do
|
|
v.clearentry(entry)
|
|
end
|
|
end
|
|
local disableentry
|
|
disableentry = function(entry)
|
|
for k, v in pairs(caches) do
|
|
v.disableentry(entry)
|
|
end
|
|
end
|
|
local disablecache
|
|
disablecache = function()
|
|
cacheenabled = false
|
|
end
|
|
local enablecache
|
|
enablecache = function()
|
|
cacheenabled = true
|
|
end
|
|
local withcache
|
|
withcache = function(fn)
|
|
local opts = { }
|
|
opts.cache = { }
|
|
opts.clearcache = function()
|
|
opts.cache = { }
|
|
end
|
|
opts.clearentry = function(entry)
|
|
opts.cache[entry] = nil
|
|
end
|
|
opts.disableentry = function(entry)
|
|
opts.cache[entry] = DISABLED
|
|
end
|
|
caches[fn] = opts
|
|
return setmetatable(opts, {
|
|
__call = function(self, arg)
|
|
if not (cacheenabled) then
|
|
return fn(arg)
|
|
end
|
|
local cached = opts.cache[arg]
|
|
if cached == DISABLED then
|
|
return fn(arg)
|
|
end
|
|
if cached == NIL then
|
|
return nil
|
|
end
|
|
if cached ~= nil then
|
|
return cached
|
|
end
|
|
cached = fn(arg)
|
|
opts.cache[arg] = cached
|
|
if cached == nil then
|
|
opts.cache[arg] = NIL
|
|
end
|
|
return cached
|
|
end
|
|
})
|
|
end
|
|
fs = {
|
|
dir = withcache(fs.dir),
|
|
attributes = withcache(fs.attributes),
|
|
mkdir = fs.mkdir
|
|
}
|
|
local attributes, dir, mkdir
|
|
attributes, dir, mkdir = fs.attributes, fs.dir, fs.mkdir
|
|
local normalizepath
|
|
normalizepath = function(file)
|
|
local parts
|
|
do
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for part in gmatch(file, '[^/]+') do
|
|
_accum_0[_len_0] = part
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
parts = _accum_0
|
|
end
|
|
local absolute = (sub(file, 1, 1)) == '/'
|
|
local i = 1
|
|
while i <= #parts do
|
|
local _continue_0 = false
|
|
repeat
|
|
if parts[i] == '.' then
|
|
remove(parts, i)
|
|
_continue_0 = true
|
|
break
|
|
end
|
|
if parts[i] == '..' and i ~= 1 and parts[i - 1] ~= '..' then
|
|
remove(parts, i)
|
|
remove(parts, i - 1)
|
|
i = i - 1
|
|
_continue_0 = true
|
|
break
|
|
end
|
|
i = i + 1
|
|
_continue_0 = true
|
|
until true
|
|
if not _continue_0 then
|
|
break
|
|
end
|
|
end
|
|
if #parts == 0 then
|
|
return absolute and '/' or '.'
|
|
else
|
|
return (absolute and '/' or '') .. concat(parts, '/')
|
|
end
|
|
end
|
|
local ls
|
|
ls = function(d)
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
local _list_0 = dir(normalizepath(d))
|
|
for _index_0 = 1, #_list_0 do
|
|
local f = _list_0[_index_0]
|
|
if f ~= '.' and f ~= '..' then
|
|
_accum_0[_len_0] = f
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
end
|
|
return _accum_0
|
|
end
|
|
local lswithpath
|
|
lswithpath = function(d)
|
|
if d == '' then
|
|
return ls('.')
|
|
end
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
local _list_0 = dir(normalizepath(d))
|
|
for _index_0 = 1, #_list_0 do
|
|
local f = _list_0[_index_0]
|
|
if f ~= '.' and f ~= '..' then
|
|
_accum_0[_len_0] = d .. '/' .. f
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
end
|
|
return _accum_0
|
|
end
|
|
local matchglob
|
|
matchglob = function(str, glob)
|
|
glob = gsub(glob, '[%[%]%%+.?-]', function(self)
|
|
return '%' .. self
|
|
end)
|
|
local patt = '^' .. (gsub(glob, '%*%*?', function(self)
|
|
return self == '**' and '.*' or '[^/]*'
|
|
end)) .. '$'
|
|
local rst
|
|
if (type(str)) == 'table' then
|
|
local results, i = { }, 1
|
|
for _index_0 = 1, #str do
|
|
local s = str[_index_0]
|
|
rst = (match(s, patt)) and s
|
|
if rst then
|
|
results[i], i = rst, i + 1
|
|
end
|
|
end
|
|
rst = results
|
|
else
|
|
rst = (match(str, patt)) and str
|
|
end
|
|
return rst
|
|
end
|
|
local exists
|
|
exists = function(f)
|
|
return (attributes(normalizepath(f))) ~= nil
|
|
end
|
|
local isdir
|
|
isdir = function(f)
|
|
return ((attributes(normalizepath(f))) or { }).mode == 'directory'
|
|
end
|
|
local wildcard
|
|
wildcard = function(glob)
|
|
local parts
|
|
do
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for part in gmatch(glob, '[^/]+') do
|
|
_accum_0[_len_0] = part
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
parts = _accum_0
|
|
end
|
|
local absolute = (sub(glob, 1, 1)) == '/'
|
|
for i, part in ipairs(parts) do
|
|
local prevpath = (absolute and '/' or '') .. concat(parts, '/', 1, i - 1)
|
|
local currpath = (i == 1 and '' or (prevpath .. '/')) .. part
|
|
if match(part, '%*%*.*%*%*') then
|
|
error("Two '**' in the same path component in a wildcard")
|
|
end
|
|
if match(part, '%*%*') then
|
|
local prefix = match(currpath, '^(.*)%*%*')
|
|
local suffix = (match(part, '%*%*(.*)$')) .. (i == #parts and '' or ('/' .. concat(parts, '/', i + 1, #parts)))
|
|
if not (exists(prevpath)) then
|
|
return { }
|
|
end
|
|
local files = lswithpath(prevpath)
|
|
local results, ri = { }, 1
|
|
for _index_0 = 1, #files do
|
|
local file = files[_index_0]
|
|
if matchglob(file, currpath) then
|
|
if i == #parts then
|
|
results[ri], ri = file, ri + 1
|
|
elseif isdir(file) then
|
|
local _list_0 = wildcard(file .. '/' .. concat(parts, '/', i + 1, #parts))
|
|
for _index_1 = 1, #_list_0 do
|
|
local result = _list_0[_index_1]
|
|
results[ri], ri = result, ri + 1
|
|
end
|
|
end
|
|
end
|
|
if (matchglob(file, prefix .. '**')) and isdir(file) then
|
|
local _list_0 = wildcard(file .. '/**' .. suffix)
|
|
for _index_1 = 1, #_list_0 do
|
|
local result = _list_0[_index_1]
|
|
results[ri], ri = result, ri + 1
|
|
end
|
|
end
|
|
end
|
|
return results
|
|
end
|
|
if match(part, '%*') then
|
|
if not (exists(prevpath)) then
|
|
return { }
|
|
end
|
|
local files = lswithpath(prevpath)
|
|
if i == #parts then
|
|
return matchglob(files, glob)
|
|
end
|
|
local results, ri = { }, 1
|
|
for _index_0 = 1, #files do
|
|
local file = files[_index_0]
|
|
if (matchglob(file, currpath)) and isdir(file) then
|
|
local _list_0 = wildcard(file .. '/' .. concat(parts, '/', i + 1, #parts))
|
|
for _index_1 = 1, #_list_0 do
|
|
local result = _list_0[_index_1]
|
|
results[ri], ri = result, ri + 1
|
|
end
|
|
end
|
|
end
|
|
return results
|
|
end
|
|
end
|
|
if exists(glob) then
|
|
return {
|
|
glob
|
|
}
|
|
else
|
|
return { }
|
|
end
|
|
end
|
|
local parent
|
|
parent = function(file)
|
|
return normalizepath(file .. '/..')
|
|
end
|
|
local actualmkdir = mkdir
|
|
mkdir = function(dir)
|
|
actualmkdir(dir)
|
|
return clearentry(parent(dir))
|
|
end
|
|
local mkdirs
|
|
mkdirs = function(dir)
|
|
if isdir(dir) then
|
|
return
|
|
end
|
|
if exists(dir) then
|
|
error("Can't mkdirs " .. tostring(dir) .. ": file exists")
|
|
end
|
|
mkdirs(parent(dir))
|
|
return mkdir(dir)
|
|
end
|
|
do
|
|
local _tbl_0 = { }
|
|
for k, fn in pairs(fs) do
|
|
_tbl_0[k] = withcache(fn)
|
|
end
|
|
fs = _tbl_0
|
|
end
|
|
fs.normalizepath = normalizepath
|
|
fs.ls = ls
|
|
fs.lswithpath = lswithpath
|
|
fs.matchglob = matchglob
|
|
fs.exists = exists
|
|
fs.isdir = isdir
|
|
fs.wildcard = wildcard
|
|
fs.parent = parent
|
|
fs.mkdir = mkdir
|
|
fs.mkdirs = mkdirs
|
|
fs.clearcache = clearcache
|
|
fs.clearentry = clearentry
|
|
fs.disableentry = disableentry
|
|
fs.disablecache = disablecache
|
|
fs.enablecache = enablecache
|
|
fs.backend = backend
|
|
return setmetatable(fs, {
|
|
__call = function(self)
|
|
return {
|
|
'dir',
|
|
'ls',
|
|
'normalizepath',
|
|
'exists',
|
|
'isdir',
|
|
'wildcard',
|
|
'mkdir',
|
|
'mkdirs'
|
|
}
|
|
end
|
|
})
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild._fs.cmd" ] = function( ... ) local arg = _G.arg;
|
|
local escape
|
|
escape = require('moonbuild._cmd').escape
|
|
local execute
|
|
execute = require('moonbuild.compat.execute').execute
|
|
local popen
|
|
popen = io.popen
|
|
local gmatch, match, sub
|
|
do
|
|
local _obj_0 = string
|
|
gmatch, match, sub = _obj_0.gmatch, _obj_0.match, _obj_0.sub
|
|
end
|
|
if not ((execute("which ls >/dev/null 2>&1")) and (execute("which stat >/dev/null 2>&1"))) then
|
|
error("commands ls and stat aren't available")
|
|
end
|
|
return {
|
|
dir = function(path)
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for file in (popen("ls -1 " .. tostring(escape(path)))):lines() do
|
|
_accum_0[_len_0] = file
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
return _accum_0
|
|
end,
|
|
attributes = function(path)
|
|
local fd = popen("stat -c '%d %i %A %h %u %g %s %b %t %T %X %Y %Z' " .. tostring(escape(path)))
|
|
local stat
|
|
do
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for part in gmatch((fd:read('*a')), "%S+") do
|
|
_accum_0[_len_0] = part
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
stat = _accum_0
|
|
end
|
|
fd:close()
|
|
fd = popen("stat -f -c '%S' " .. tostring(escape(path)))
|
|
local blksize = match((fd:read('*a')), '%S+')
|
|
fd:close()
|
|
return {
|
|
dev = tonumber(stat[1]),
|
|
ino = tonumber(stat[2]),
|
|
nlink = tonumber(stat[4]),
|
|
uid = tonumber(stat[5]),
|
|
gid = tonumber(stat[6]),
|
|
size = tonumber(stat[7]),
|
|
blocks = tonumber(stat[8]),
|
|
blksize = tonumber(blksize),
|
|
access = tonumber(stat[11]),
|
|
modification = tonumber(stat[12]),
|
|
change = tonumber(stat[13]),
|
|
permissions = (function()
|
|
return sub(stat[3], 2)
|
|
end)(),
|
|
mode = (function()
|
|
local _exp_0 = sub(stat[3], 1, 1)
|
|
if '-' == _exp_0 then
|
|
return 'file'
|
|
elseif 'd' == _exp_0 then
|
|
return 'directory'
|
|
elseif 'l' == _exp_0 then
|
|
return 'link'
|
|
elseif 's' == _exp_0 then
|
|
return 'socket'
|
|
elseif 'p' == _exp_0 then
|
|
return 'named pipe'
|
|
elseif 'c' == _exp_0 then
|
|
return 'char device'
|
|
elseif 'b' == _exp_0 then
|
|
return 'block device'
|
|
else
|
|
return 'other'
|
|
end
|
|
end)(),
|
|
rdev = (function()
|
|
return (tonumber(stat[9])) * 256 + (tonumber(stat[10]))
|
|
end)()
|
|
}
|
|
end,
|
|
mkdir = function(path)
|
|
if not (execute("mkdir " .. tostring(escape(path)))) then
|
|
return error("Mkdir " .. tostring(path) .. " failed")
|
|
end
|
|
end
|
|
}
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild._fs.lfs" ] = function( ... ) local arg = _G.arg;
|
|
local dir, attributes, mkdir
|
|
do
|
|
local _obj_0 = require('lfs')
|
|
dir, attributes, mkdir = _obj_0.dir, _obj_0.attributes, _obj_0.mkdir
|
|
end
|
|
return {
|
|
dir = function(path)
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for v in dir(path) do
|
|
_accum_0[_len_0] = v
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
return _accum_0
|
|
end,
|
|
attributes = attributes,
|
|
mkdir = function(path)
|
|
local ok, err = mkdir(path)
|
|
if not (ok) then
|
|
return error("Failed to mkdir " .. tostring(path) .. ": " .. tostring(err))
|
|
end
|
|
end
|
|
}
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild._fs.posix" ] = function( ... ) local arg = _G.arg;
|
|
local dir
|
|
dir = require('posix.dirent').dir
|
|
local stat, mkdir, S_IFMT, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLINK, S_IFREG, S_IFSOCK
|
|
do
|
|
local _obj_0 = require('posix.sys.stat')
|
|
stat, mkdir, S_IFMT, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLINK, S_IFREG, S_IFSOCK = _obj_0.stat, _obj_0.mkdir, _obj_0.S_IFMT, _obj_0.S_IFBLK, _obj_0.S_IFCHR, _obj_0.S_IFDIR, _obj_0.S_IFIFO, _obj_0.S_IFLINK, _obj_0.S_IFREG, _obj_0.S_IFSOCK
|
|
end
|
|
local band, btest
|
|
do
|
|
local _obj_0 = require('moonbuild.compat.bit')
|
|
band, btest = _obj_0.band, _obj_0.btest
|
|
end
|
|
local concat
|
|
concat = table.concat
|
|
return {
|
|
dir = dir,
|
|
attributes = function(path)
|
|
local st = stat(path)
|
|
if not (st) then
|
|
return nil
|
|
end
|
|
local mode = st.st_mode
|
|
return {
|
|
mode = (function()
|
|
local ty = band(mode, S_IFMT)
|
|
local _exp_0 = ty
|
|
if S_IFREG == _exp_0 then
|
|
return 'file'
|
|
elseif S_IFDIR == _exp_0 then
|
|
return 'directory'
|
|
elseif S_IFLINK == _exp_0 then
|
|
return 'link'
|
|
elseif S_IFSOCK == _exp_0 then
|
|
return 'socket'
|
|
elseif S_IFIFO == _exp_0 then
|
|
return 'named pipe'
|
|
elseif S_IFCHR == _exp_0 then
|
|
return 'char device'
|
|
elseif S_IFBLK == _exp_0 then
|
|
return 'block device'
|
|
else
|
|
return 'other'
|
|
end
|
|
end)(),
|
|
permissions = (function()
|
|
local _suid = btest(mode, 2048)
|
|
local _sgid = btest(mode, 1024)
|
|
local _stic = btest(mode, 512)
|
|
local _ur = btest(mode, 256)
|
|
local _uw = btest(mode, 128)
|
|
local _ux = btest(mode, 64)
|
|
local _gr = btest(mode, 32)
|
|
local _gw = btest(mode, 16)
|
|
local _gx = btest(mode, 8)
|
|
local _or = btest(mode, 4)
|
|
local _ow = btest(mode, 2)
|
|
local _ox = btest(mode, 1)
|
|
return concat({
|
|
_ur and 'r' or '-',
|
|
_uw and 'w' or '-',
|
|
_suid and 's' or (_ux and 'x' or '-'),
|
|
_gr and 'r' or '-',
|
|
_gw and 'w' or '-',
|
|
_sgid and 's' or (_gx and 'x' or '-'),
|
|
_or and 'r' or '-',
|
|
_ow and 'w' or '-',
|
|
_stic and 't' or (_ox and 'x' or '-')
|
|
})
|
|
end)(),
|
|
dev = st.st_dev,
|
|
ino = st.st_ino,
|
|
nlink = st.st_nlink,
|
|
uid = st.st_uid,
|
|
gid = st.st_gid,
|
|
rdev = st.st_rdev,
|
|
access = st.st_atime,
|
|
modification = st.st_mtime,
|
|
change = st.st_ctime,
|
|
size = st.st_size,
|
|
blocks = st.st_blocks,
|
|
blksize = st.st_blksize
|
|
}
|
|
end,
|
|
mkdir = function(path)
|
|
local ok, err = mkdir(path)
|
|
if not (ok) then
|
|
return error("Failed to mkdir " .. tostring(path) .. ": " .. tostring(err))
|
|
end
|
|
end
|
|
}
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild._util" ] = function( ... ) local arg = _G.arg;
|
|
local to_lua
|
|
to_lua = require('moonscript.base').to_lua
|
|
local parseargs, cmdrst
|
|
do
|
|
local _obj_0 = require('moonbuild._cmd')
|
|
parseargs, cmdrst = _obj_0.parseargs, _obj_0.cmdrst
|
|
end
|
|
local gmatch, match, gsub
|
|
do
|
|
local _obj_0 = string
|
|
gmatch, match, gsub = _obj_0.gmatch, _obj_0.match, _obj_0.gsub
|
|
end
|
|
local open
|
|
open = io.open
|
|
local util = { }
|
|
local _pkgconfig
|
|
_pkgconfig = function(mode, ...)
|
|
return parseargs(cmdrst('pkg-config', "--" .. tostring(mode), ...))
|
|
end
|
|
local pkgconfig = setmetatable({ }, {
|
|
__index = function(self, mode)
|
|
return function(...)
|
|
return _pkgconfig(mode, ...)
|
|
end
|
|
end
|
|
})
|
|
local _cdeps
|
|
_cdeps = function(cc, cflags, path)
|
|
local raw = cmdrst(cc, cflags, '-M', path)
|
|
local rawlist = gsub((match(raw, ':(.+)')), '\\\n', ' ')
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for v in gmatch(rawlist, '%S+') do
|
|
_accum_0[_len_0] = v
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
return _accum_0
|
|
end
|
|
local cdeps = setmetatable({ }, {
|
|
__index = function(self, cc)
|
|
return function(cflags, path)
|
|
return _cdeps(cc, cflags, path)
|
|
end
|
|
end,
|
|
__call = function(self, cflags, path)
|
|
return _cdeps('cc', cflags, path)
|
|
end
|
|
})
|
|
local readfile
|
|
readfile = function(filename)
|
|
local fd, err = open(filename, 'rb')
|
|
if not (fd) then
|
|
error(err)
|
|
end
|
|
local data
|
|
data, err = fd:read('*a')
|
|
if not (data) then
|
|
error(err)
|
|
end
|
|
fd:close()
|
|
return data
|
|
end
|
|
local writefile
|
|
writefile = function(filename, data)
|
|
local fd, err = open(filename, 'wb')
|
|
if not (fd) then
|
|
error(err)
|
|
end
|
|
local ok
|
|
ok, err = fd:write(data)
|
|
if not (ok) then
|
|
error(err)
|
|
end
|
|
fd:close()
|
|
return nil
|
|
end
|
|
local moonc
|
|
moonc = function(infile, outfile)
|
|
local code, err = to_lua(readfile(infile))
|
|
if not (code) then
|
|
error("Failed to compile " .. tostring(self.infile) .. ": " .. tostring(err))
|
|
end
|
|
return writefile(outfile, code)
|
|
end
|
|
util.pkgconfig = pkgconfig
|
|
util.cdeps = cdeps
|
|
util.readfile = readfile
|
|
util.writefile = writefile
|
|
util.moonc = moonc
|
|
return setmetatable(util, {
|
|
__call = function(self)
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for k in pairs(util) do
|
|
_accum_0[_len_0] = k
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
return _accum_0
|
|
end
|
|
})
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.compat.bit" ] = function( ... ) local arg = _G.arg;
|
|
local loadstring = loadstring or load
|
|
local floor, ceil, pow
|
|
do
|
|
local _obj_0 = math
|
|
floor, ceil, pow = _obj_0.floor, _obj_0.ceil, _obj_0.pow
|
|
end
|
|
local band = loadstring([[local a, b = ...; return a & b ]])
|
|
local bor = loadstring([[local a, b = ...; return a | b ]])
|
|
local bxor = loadstring([[local a, b = ...; return a ~ b ]])
|
|
local bnot = loadstring([[local a = ...; return ~a ]])
|
|
local shl = loadstring([[local a, b = ...; return a << b]])
|
|
local shr = loadstring([[local a, b = ...; return a >> b]])
|
|
if not (band) then
|
|
local _checkint
|
|
_checkint = function(n)
|
|
if n % 1 == 0 then
|
|
return n
|
|
else
|
|
return error("not an int")
|
|
end
|
|
end
|
|
local _shl
|
|
_shl = function(a, b)
|
|
return a * pow(2, b)
|
|
end
|
|
local _shr
|
|
_shr = function(a, b)
|
|
local v = a / pow(2, b)
|
|
if v < 0 then
|
|
return ceil(v)
|
|
else
|
|
return floor(v)
|
|
end
|
|
end
|
|
local _shr1
|
|
_shr1 = function(n)
|
|
n = n / 2
|
|
if n < 0 then
|
|
return ceil(v)
|
|
else
|
|
return floor(v)
|
|
end
|
|
end
|
|
local _band
|
|
_band = function(a, b)
|
|
local v = 0
|
|
local n = 1
|
|
for i = 0, 63 do
|
|
if a % 2 == 1 and b % 2 == 1 then
|
|
v = v + n
|
|
end
|
|
if i ~= 63 then
|
|
a = _shr1(a)
|
|
b = _shr1(b)
|
|
n = n * 2
|
|
end
|
|
end
|
|
return v
|
|
end
|
|
local _bor
|
|
_bor = function(a, b)
|
|
local v = 0
|
|
local n = 1
|
|
for i = 0, 63 do
|
|
if a % 2 == 1 or b % 2 == 1 then
|
|
v = v + n
|
|
end
|
|
if i ~= 63 then
|
|
a = _shr1(a)
|
|
b = _shr1(b)
|
|
n = n * 2
|
|
end
|
|
end
|
|
return v
|
|
end
|
|
local _bxor
|
|
_bxor = function(a, b)
|
|
local v = 0
|
|
local n = 1
|
|
for i = 0, 63 do
|
|
if a % 2 ~= b % 2 then
|
|
v = v + n
|
|
end
|
|
if i ~= 63 then
|
|
a = _shr1(a)
|
|
b = _shr1(b)
|
|
n = n * 2
|
|
end
|
|
end
|
|
return v
|
|
end
|
|
local _bnot
|
|
_bnot = function(a)
|
|
local v = 0
|
|
local n = 1
|
|
for i = 0, 63 do
|
|
if a % 2 == 0 then
|
|
v = v + n
|
|
end
|
|
if i ~= 63 then
|
|
a = _shr1(a)
|
|
n = n * 2
|
|
end
|
|
end
|
|
return v
|
|
end
|
|
band = function(a, b)
|
|
return _band((_checkint(a)), (_checkint(b)))
|
|
end
|
|
bor = function(a, b)
|
|
return _bor((_checkint(a)), (_checkint(b)))
|
|
end
|
|
bxor = function(a, b)
|
|
return _bxor((_checkint(a)), (_checkint(b)))
|
|
end
|
|
bnot = function(a)
|
|
return _bnot((_checkint(a)))
|
|
end
|
|
shl = function(a, b)
|
|
return _shl((_checkint(a)), (_checkint(b)))
|
|
end
|
|
shr = function(a, b)
|
|
return _shr((_checkint(a)), (_checkint(b)))
|
|
end
|
|
end
|
|
local btest
|
|
btest = function(a, b)
|
|
return (band(a, b)) == b
|
|
end
|
|
return {
|
|
band = band,
|
|
bor = bor,
|
|
bxor = bxor,
|
|
bnot = bnot,
|
|
shl = shl,
|
|
shr = shr,
|
|
btest = btest
|
|
}
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.compat.ctx" ] = function( ... ) local arg = _G.arg;
|
|
local pcall = require('moonbuild.compat.pcall')
|
|
local runwithcontext
|
|
if setfenv then
|
|
runwithcontext = function(fn, ctx, ...)
|
|
local env = getfenv(fn)
|
|
setfenv(fn, ctx)
|
|
local data, ndata, ok
|
|
local acc
|
|
acc = function(succ, ...)
|
|
ok = succ
|
|
if succ then
|
|
data = {
|
|
...
|
|
}
|
|
ndata = select('#', ...)
|
|
else
|
|
data = ...
|
|
end
|
|
end
|
|
acc(pcall(fn, ...))
|
|
setfenv(fn, env)
|
|
if ok then
|
|
return unpack(data, 1, ndata)
|
|
else
|
|
return error(data)
|
|
end
|
|
end
|
|
else
|
|
local dump
|
|
dump = string.dump
|
|
runwithcontext = function(fn, ctx, ...)
|
|
local code = dump(fn, false)
|
|
fn = load(code, 'runwithcontext', 'b', ctx)
|
|
return fn(...)
|
|
end
|
|
end
|
|
return {
|
|
runwithcontext = runwithcontext
|
|
}
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.compat.execute" ] = function( ... ) local arg = _G.arg;
|
|
local execute
|
|
execute = os.execute
|
|
return {
|
|
execute = function(cmd)
|
|
local a, b, c = execute(cmd)
|
|
if (type(a)) == 'boolean' then
|
|
return a, b, c
|
|
else
|
|
return a == 0 or nil, 'exit', a
|
|
end
|
|
end
|
|
}
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.compat.pcall" ] = function( ... ) local arg = _G.arg;
|
|
local pcall = _G.pcall
|
|
local unpack = _G.unpack or table.unpack
|
|
local testfn
|
|
testfn = function(a, b)
|
|
return a == b and a == 1 and true or error()
|
|
end
|
|
local testok, testrst = pcall(testfn, 1, 1)
|
|
if not (testok and testrst) then
|
|
local realpcall = pcall
|
|
pcall = function(fn, ...)
|
|
local args = {
|
|
n = (select('#', ...)),
|
|
...
|
|
}
|
|
return realpcall(function()
|
|
return fn(unpack(args, 1, args.n))
|
|
end)
|
|
end
|
|
end
|
|
return pcall
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.context" ] = function( ... ) local arg = _G.arg;
|
|
local runwithcontext
|
|
runwithcontext = require('moonbuild.compat.ctx').runwithcontext
|
|
local topenv = require('moonbuild.env.top')
|
|
local initenv = require('moonbuild.env.init')
|
|
local includes
|
|
includes = require('moonbuild._common').includes
|
|
local insert
|
|
insert = table.insert
|
|
local Context
|
|
do
|
|
local _class_0
|
|
local _base_0 = {
|
|
addvar = function(self, var)
|
|
self.variables[var.name] = var
|
|
end,
|
|
addinit = function(self, fn)
|
|
return insert(self.inits, fn)
|
|
end,
|
|
addtarget = function(self, target)
|
|
return insert(self.targets, target)
|
|
end,
|
|
resetexecuted = function(self)
|
|
self.executedtargets = { }
|
|
end,
|
|
adddefault = function(self, target)
|
|
if not (includes(self.targets, target)) then
|
|
error("not a target of the current context: " .. tostring(target))
|
|
end
|
|
if not ((type(target.name)) == 'string') then
|
|
error("not a named target")
|
|
end
|
|
return insert(self.defaulttargets, target.name)
|
|
end,
|
|
load = function(self, code, overrides)
|
|
return runwithcontext(code, (topenv(self, overrides)))
|
|
end,
|
|
init = function(self)
|
|
if self.inits[1] then
|
|
local env = (initenv(self))
|
|
local _list_0 = self.inits
|
|
for _index_0 = 1, #_list_0 do
|
|
local init = _list_0[_index_0]
|
|
runwithcontext(code, env)
|
|
end
|
|
end
|
|
end
|
|
}
|
|
_base_0.__index = _base_0
|
|
_class_0 = setmetatable({
|
|
__init = function(self)
|
|
self.targets = { }
|
|
self.defaulttargets = { }
|
|
self.variables = { }
|
|
self.inits = { }
|
|
end,
|
|
__base = _base_0,
|
|
__name = "Context"
|
|
}, {
|
|
__index = _base_0,
|
|
__call = function(cls, ...)
|
|
local _self_0 = setmetatable({}, _base_0)
|
|
cls.__init(_self_0, ...)
|
|
return _self_0
|
|
end
|
|
})
|
|
_base_0.__class = _class_0
|
|
Context = _class_0
|
|
return _class_0
|
|
end
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.core.DAG" ] = function( ... ) local arg = _G.arg;
|
|
local filter, foreach, flatten, patsubst
|
|
do
|
|
local _obj_0 = require('moonbuild._common')
|
|
filter, foreach, flatten, patsubst = _obj_0.filter, _obj_0.foreach, _obj_0.flatten, _obj_0.patsubst
|
|
end
|
|
local runwithcontext
|
|
runwithcontext = require('moonbuild.compat.ctx').runwithcontext
|
|
local globalenv = require('moonbuild.env.global')
|
|
local exists, parent, mkdirs, clearentry, disableentry, attributes
|
|
do
|
|
local _obj_0 = require('moonbuild._fs')
|
|
exists, parent, mkdirs, clearentry, disableentry, attributes = _obj_0.exists, _obj_0.parent, _obj_0.mkdirs, _obj_0.clearentry, _obj_0.disableentry, _obj_0.attributes
|
|
end
|
|
local sort
|
|
sort = table.sort
|
|
local huge
|
|
huge = math.huge
|
|
local DepNode, FileTarget
|
|
local nodepriority
|
|
nodepriority = function(a, b)
|
|
local ta = type(a.name)
|
|
local tb = type(b.name)
|
|
local da = #a.deps
|
|
local db = #b.deps
|
|
if ta == 'string' and tb ~= 'string' then
|
|
return true
|
|
elseif ta ~= 'string' and tb == 'string' then
|
|
return false
|
|
elseif a.priority > b.priority then
|
|
return true
|
|
elseif a.priority < b.priority then
|
|
return false
|
|
else
|
|
return da < db
|
|
end
|
|
end
|
|
local transclosure
|
|
transclosure = function(obj, prop)
|
|
local elems = { }
|
|
local i = 1
|
|
local set = { }
|
|
local imp
|
|
imp = function(e)
|
|
local _list_0 = e[prop]
|
|
for _index_0 = 1, #_list_0 do
|
|
local v = _list_0[_index_0]
|
|
if not set[v] then
|
|
elems[i], i = v, i + 1
|
|
set[v] = i
|
|
imp(v)
|
|
end
|
|
end
|
|
end
|
|
imp(obj)
|
|
return elems
|
|
end
|
|
local mtime
|
|
mtime = function(path)
|
|
local attr = attributes(path)
|
|
return attr and attr.modification
|
|
end
|
|
local DepGraph
|
|
do
|
|
local _class_0
|
|
local _base_0 = {
|
|
addnode = function(self, name)
|
|
if self.nodes[name] then
|
|
return
|
|
end
|
|
local elected = self:resolvedeps(name)
|
|
self.nodes[name] = elected
|
|
local _list_0 = (transclosure(elected, 'deps'))
|
|
for _index_0 = 1, #_list_0 do
|
|
local dep = _list_0[_index_0]
|
|
self.nodes[dep.name] = dep
|
|
dep.deps = nil
|
|
end
|
|
elected.deps = nil
|
|
end,
|
|
resolvedeps = function(self, name)
|
|
do
|
|
local node = self.nodes[name]
|
|
if node then
|
|
return node, { }
|
|
end
|
|
end
|
|
local candidates = filter({
|
|
self.ctx.targets,
|
|
FileTarget()
|
|
}, function(target)
|
|
return target:matches(name)
|
|
end)
|
|
local nodes = foreach(candidates, function(candidate)
|
|
return {
|
|
a = {
|
|
pcall(function()
|
|
return DepNode(self, candidate, name)
|
|
end)
|
|
}
|
|
}
|
|
end)
|
|
local resolved = foreach((filter(nodes, function(node)
|
|
return node.a[1]
|
|
end)), function(node)
|
|
return node.a[2]
|
|
end)
|
|
sort(resolved, nodepriority)
|
|
return resolved[1] or error("Cannot resolve target " .. tostring(name))
|
|
end,
|
|
buildablenodes = function(self)
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for k, v in pairs(self.nodes) do
|
|
if v:canbuild() and not v.built then
|
|
_accum_0[_len_0] = v
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
end
|
|
return _accum_0
|
|
end
|
|
}
|
|
_base_0.__index = _base_0
|
|
_class_0 = setmetatable({
|
|
__init = function(self, ctx, names)
|
|
if names == nil then
|
|
names = { }
|
|
end
|
|
self.ctx = ctx
|
|
self.nodes = { }
|
|
self.env = globalenv(self.ctx)
|
|
for _index_0 = 1, #names do
|
|
local name = names[_index_0]
|
|
self:addnode(name)
|
|
end
|
|
end,
|
|
__base = _base_0,
|
|
__name = "DepGraph"
|
|
}, {
|
|
__index = _base_0,
|
|
__call = function(cls, ...)
|
|
local _self_0 = setmetatable({}, _base_0)
|
|
cls.__init(_self_0, ...)
|
|
return _self_0
|
|
end
|
|
})
|
|
_base_0.__class = _class_0
|
|
DepGraph = _class_0
|
|
end
|
|
do
|
|
local _class_0
|
|
local _base_0 = {
|
|
canbuild = function(self)
|
|
local _list_0 = flatten({
|
|
self.ins,
|
|
self.after
|
|
})
|
|
for _index_0 = 1, #_list_0 do
|
|
local node = _list_0[_index_0]
|
|
if not self.dag.nodes[node].built then
|
|
return false
|
|
end
|
|
end
|
|
local _list_1 = self.ins
|
|
for _index_0 = 1, #_list_1 do
|
|
local file = _list_1[_index_0]
|
|
if not exists(file) then
|
|
error("Node " .. tostring(name) .. " has ran all of its parents, but can't run since " .. tostring(file) .. " doesn't exist")
|
|
end
|
|
end
|
|
return true
|
|
end,
|
|
build = function(self, opts)
|
|
if opts == nil then
|
|
opts = { }
|
|
end
|
|
local force = opts.force or false
|
|
local quiet = opts.quiet or false
|
|
if self.built then
|
|
return
|
|
end
|
|
if not (force or self:shouldbuild()) then
|
|
return
|
|
end
|
|
if not (quiet or #self.buildfunctions == 0) then
|
|
print(tostring(self.type == 'virtual' and "Running" or "Building") .. " " .. tostring(self.name))
|
|
end
|
|
return self:actuallybuild()
|
|
end,
|
|
shouldbuild = function(self)
|
|
if #self.outs == 0 or #self.ins == 0 or self.type == 'virtual' then
|
|
return true
|
|
end
|
|
local minout = huge
|
|
local _list_0 = self.outs
|
|
for _index_0 = 1, #_list_0 do
|
|
local file = _list_0[_index_0]
|
|
local time = mtime(file)
|
|
if not time then
|
|
return true
|
|
end
|
|
if time < minout then
|
|
minout = time
|
|
end
|
|
end
|
|
local maxin = 0
|
|
local _list_1 = self.ins
|
|
for _index_0 = 1, #_list_1 do
|
|
local file = _list_1[_index_0]
|
|
local time = mtime(file)
|
|
if time > maxin then
|
|
maxin = time
|
|
end
|
|
end
|
|
return maxin > minout
|
|
end,
|
|
actuallybuild = function(self)
|
|
if self.mkdirs then
|
|
local _list_0 = self.outs
|
|
for _index_0 = 1, #_list_0 do
|
|
local file = _list_0[_index_0]
|
|
mkdirs(parent(file))
|
|
end
|
|
end
|
|
local _list_0 = self.outs
|
|
for _index_0 = 1, #_list_0 do
|
|
local file = _list_0[_index_0]
|
|
disableentry(file)
|
|
end
|
|
local ctx = setmetatable({ }, {
|
|
__index = function(_, k)
|
|
local _exp_0 = k
|
|
if 'infile' == _exp_0 then
|
|
return self.ins[1]
|
|
elseif 'infiles' == _exp_0 then
|
|
return self.ins
|
|
elseif 'outfile' == _exp_0 then
|
|
return self.outs[1]
|
|
elseif 'outfiles' == _exp_0 then
|
|
return self.outs
|
|
elseif 'name' == _exp_0 then
|
|
return self.name
|
|
else
|
|
return error("No such field in TargetContext: " .. tostring(k))
|
|
end
|
|
end,
|
|
__newindex = function(self, k)
|
|
return error("Attempt to set field " .. tostring(k) .. " of TargetContext")
|
|
end
|
|
})
|
|
local _list_1 = self.buildfunctions
|
|
for _index_0 = 1, #_list_1 do
|
|
local fn = _list_1[_index_0]
|
|
runwithcontext(fn, self.dag.env, ctx)
|
|
end
|
|
end,
|
|
updatecache = function(self)
|
|
local _list_0 = self.outs
|
|
for _index_0 = 1, #_list_0 do
|
|
local file = _list_0[_index_0]
|
|
clearentry(file)
|
|
end
|
|
end
|
|
}
|
|
_base_0.__index = _base_0
|
|
_class_0 = setmetatable({
|
|
__init = function(self, dag, target, name)
|
|
self.dag, self.name = dag, name
|
|
self.priority = target.priority
|
|
self.buildfunctions = target.buildfunctions
|
|
self.mkdirs = target._mkdirs
|
|
self.sync = target._sync
|
|
self.type = target._type
|
|
self.outs = foreach(target.outfiles, function(name)
|
|
return patsubst(self.name, target.pattern, name)
|
|
end)
|
|
if #self.outs == 0 then
|
|
self.type = 'virtual'
|
|
end
|
|
self.built = false
|
|
local resolve
|
|
resolve = function(name)
|
|
return self.dag:resolvedeps(patsubst(self.name, target.pattern, name))
|
|
end
|
|
local after = flatten(foreach(target.needtargets, resolve))
|
|
local deps = flatten(foreach(target.infiles, resolve))
|
|
if #target.depfunctions ~= 0 then
|
|
local ctx = setmetatable({ }, {
|
|
__index = function(_, k)
|
|
local _exp_0 = k
|
|
if 'infile' == _exp_0 then
|
|
return first(deps)
|
|
elseif 'infiles' == _exp_0 then
|
|
return flatten(deps)
|
|
elseif 'outfile' == _exp_0 then
|
|
return first(self.outs)
|
|
elseif 'outfiles' == _exp_0 then
|
|
return flatten(self.outs)
|
|
elseif 'name' == _exp_0 then
|
|
return self.name
|
|
else
|
|
return error("No such field in TargetDepsContext: " .. tostring(k))
|
|
end
|
|
end,
|
|
__newindex = function(self, k)
|
|
return error("Attempt to set field " .. tostring(k) .. " of TargetDepsContext")
|
|
end
|
|
})
|
|
local _list_0 = target.depfunctions
|
|
for _index_0 = 1, #_list_0 do
|
|
local depfn = _list_0[_index_0]
|
|
deps = flatten(deps, foreach(depfn, function(fn)
|
|
return resolve(runwithcontext(fn, self.dag.env, ctx))
|
|
end))
|
|
end
|
|
end
|
|
self.ins = foreach(deps, function(dep)
|
|
return dep.name
|
|
end)
|
|
self.after = foreach(after, function(dep)
|
|
return dep.name
|
|
end)
|
|
self.deps = flatten({
|
|
deps,
|
|
after
|
|
})
|
|
if #self.deps == 0 and #self.buildfunctions == 0 then
|
|
self.built = true
|
|
end
|
|
end,
|
|
__base = _base_0,
|
|
__name = "DepNode"
|
|
}, {
|
|
__index = _base_0,
|
|
__call = function(cls, ...)
|
|
local _self_0 = setmetatable({}, _base_0)
|
|
cls.__init(_self_0, ...)
|
|
return _self_0
|
|
end
|
|
})
|
|
_base_0.__class = _class_0
|
|
DepNode = _class_0
|
|
end
|
|
do
|
|
local _class_0
|
|
local _base_0 = {
|
|
matches = function(self, name)
|
|
return exists(name)
|
|
end
|
|
}
|
|
_base_0.__index = _base_0
|
|
_class_0 = setmetatable({
|
|
__init = function(self)
|
|
self.priority = -huge
|
|
self.buildfunctions = { }
|
|
self._mkdirs = false
|
|
self._sync = false
|
|
self._type = 'file'
|
|
self.needtargets = { }
|
|
self.infiles = { }
|
|
self.depfunctions = { }
|
|
self.outfiles = {
|
|
'%'
|
|
}
|
|
self.pattern = '%'
|
|
end,
|
|
__base = _base_0,
|
|
__name = "FileTarget"
|
|
}, {
|
|
__index = _base_0,
|
|
__call = function(cls, ...)
|
|
local _self_0 = setmetatable({}, _base_0)
|
|
cls.__init(_self_0, ...)
|
|
return _self_0
|
|
end
|
|
})
|
|
_base_0.__class = _class_0
|
|
FileTarget = _class_0
|
|
end
|
|
return DepGraph
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.core.Target" ] = function( ... ) local arg = _G.arg;
|
|
local flatten, includes, patget
|
|
do
|
|
local _obj_0 = require('moonbuild._common')
|
|
flatten, includes, patget = _obj_0.flatten, _obj_0.includes, _obj_0.patget
|
|
end
|
|
local insert
|
|
insert = table.insert
|
|
local Target
|
|
do
|
|
local _class_0
|
|
local _base_0 = {
|
|
matches = function(self, name)
|
|
if self.name == name then
|
|
return true
|
|
end
|
|
if (includes(self.name, name)) and patget(name, self.pattern) then
|
|
return true
|
|
end
|
|
return false
|
|
end,
|
|
produces = function(self, ...)
|
|
local n = #self.outfiles + 1
|
|
local _list_0 = flatten(...)
|
|
for _index_0 = 1, #_list_0 do
|
|
local obj = _list_0[_index_0]
|
|
self.outfiles[n], n = obj, n + 1
|
|
end
|
|
end,
|
|
depends = function(self, ...)
|
|
if (type(...)) == 'function' then
|
|
return insert(self.depfunctions, (...))
|
|
else
|
|
local n = #self.infiles + 1
|
|
local _list_0 = flatten(...)
|
|
for _index_0 = 1, #_list_0 do
|
|
local obj = _list_0[_index_0]
|
|
self.infiles[n], n = obj, n + 1
|
|
end
|
|
end
|
|
end,
|
|
after = function(self, ...)
|
|
local n = #self.needtargets + 1
|
|
local _list_0 = flatten(...)
|
|
for _index_0 = 1, #_list_0 do
|
|
local tgt = _list_0[_index_0]
|
|
self.needtargets[n], n = tgt, n + 1
|
|
end
|
|
end,
|
|
fn = function(self, fn)
|
|
return insert(self.buildfunctions, fn)
|
|
end,
|
|
sync = function(self)
|
|
self._sync = true
|
|
end,
|
|
mkdirs = function(self)
|
|
self._mkdirs = true
|
|
end
|
|
}
|
|
_base_0.__index = _base_0
|
|
_class_0 = setmetatable({
|
|
__init = function(self, ctx, name, opts)
|
|
if opts == nil then
|
|
opts = { }
|
|
end
|
|
self.ctx, self.name = ctx, name
|
|
if (type(self.name)) ~= 'string' then
|
|
self.name = flatten(self.name)
|
|
end
|
|
self.pattern = opts.pattern or ((type(self.name)) == 'string' and self.name or '%')
|
|
self.priority = opts.priority or 0
|
|
if not ((type(self.pattern)) == 'string') then
|
|
error("pattern must be a string")
|
|
end
|
|
if not ((type(self.priority)) == 'number' and self.priority % 1 == 0) then
|
|
error("priority must be an int")
|
|
end
|
|
self.outfiles = { }
|
|
self.infiles = { }
|
|
self.needtargets = { }
|
|
self.depfunctions = { }
|
|
self.buildfunctions = { }
|
|
self._mkdirs = false
|
|
self._sync = false
|
|
self._type = 'normal'
|
|
self.public = false
|
|
end,
|
|
__base = _base_0,
|
|
__name = "Target"
|
|
}, {
|
|
__index = _base_0,
|
|
__call = function(cls, ...)
|
|
local _self_0 = setmetatable({}, _base_0)
|
|
cls.__init(_self_0, ...)
|
|
return _self_0
|
|
end
|
|
})
|
|
_base_0.__class = _class_0
|
|
Target = _class_0
|
|
return _class_0
|
|
end
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.core.Variable" ] = function( ... ) local arg = _G.arg;
|
|
local flatten
|
|
flatten = require('moonbuild._common').flatten
|
|
local Variable
|
|
do
|
|
local _class_0
|
|
local _base_0 = { }
|
|
_base_0.__index = _base_0
|
|
_class_0 = setmetatable({
|
|
__init = function(self, name, ...)
|
|
self.name = name
|
|
self.public = false
|
|
if (select('#', ...)) ~= 1 or (type(...)) == 'table' then
|
|
self.value = flatten(...)
|
|
else
|
|
self.value = ...
|
|
end
|
|
end,
|
|
__base = _base_0,
|
|
__name = "Variable"
|
|
}, {
|
|
__index = _base_0,
|
|
__call = function(cls, ...)
|
|
local _self_0 = setmetatable({}, _base_0)
|
|
cls.__init(_self_0, ...)
|
|
return _self_0
|
|
end
|
|
})
|
|
_base_0.__class = _class_0
|
|
local self = _class_0
|
|
self.NIL = function() end
|
|
Variable = _class_0
|
|
return _class_0
|
|
end
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.core.multiprocessexecutor" ] = function( ... ) local arg = _G.arg;
|
|
local fork, _exit
|
|
do
|
|
local _obj_0 = require('posix.unistd')
|
|
fork, _exit = _obj_0.fork, _obj_0._exit
|
|
end
|
|
local wait
|
|
wait = require('posix.sys.wait').wait
|
|
local open, stderr
|
|
do
|
|
local _obj_0 = io
|
|
open, stderr = _obj_0.open, _obj_0.stderr
|
|
end
|
|
local match
|
|
match = string.match
|
|
local Executor
|
|
do
|
|
local _class_0
|
|
local _base_0 = {
|
|
execute = function(self, opts)
|
|
local block = self.dag:buildablenodes()
|
|
while #block ~= 0 do
|
|
for _index_0 = 1, #block do
|
|
local node = block[_index_0]
|
|
self:addprocess(node, opts)
|
|
if self.nprocesses == self.nparallel then
|
|
self:waitprocess()
|
|
end
|
|
end
|
|
do
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
local _list_0 = self.dag:buildablenodes()
|
|
for _index_0 = 1, #_list_0 do
|
|
local node = _list_0[_index_0]
|
|
if not self.building[node] then
|
|
_accum_0[_len_0] = node
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
end
|
|
block = _accum_0
|
|
end
|
|
while #block == 0 and self.nprocesses ~= 0 do
|
|
self:waitprocess()
|
|
do
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
local _list_0 = self.dag:buildablenodes()
|
|
for _index_0 = 1, #_list_0 do
|
|
local node = _list_0[_index_0]
|
|
if not self.building[node] then
|
|
_accum_0[_len_0] = node
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
end
|
|
block = _accum_0
|
|
end
|
|
end
|
|
end
|
|
while self.nprocesses ~= 0 do
|
|
self:waitprocess()
|
|
end
|
|
for name, node in pairs(self.dag.nodes) do
|
|
if not (node.built) then
|
|
error("Node " .. tostring(name) .. " wasn't built")
|
|
end
|
|
end
|
|
end,
|
|
addprocess = function(self, node, opts)
|
|
local pid = fork()
|
|
if not (pid) then
|
|
error("Failed to fork")
|
|
end
|
|
if pid ~= 0 then
|
|
self.processes[pid] = node
|
|
self.nprocesses = self.nprocesses + 1
|
|
self.building[node] = true
|
|
else
|
|
local ok, err = pcall(function()
|
|
return node:build(opts)
|
|
end)
|
|
if ok then
|
|
return _exit(0)
|
|
else
|
|
stderr:write(err)
|
|
return _exit(1)
|
|
end
|
|
end
|
|
end,
|
|
waitprocess = function(self)
|
|
local pid, ty, status = wait()
|
|
if not (pid) then
|
|
error("Failed to wait")
|
|
end
|
|
if ty ~= 'exited' or status ~= 0 then
|
|
error("Failed to build " .. tostring(self.processes[pid].name))
|
|
end
|
|
self.processes[pid].built = true
|
|
self.processes[pid]:updatecache()
|
|
self.processes[pid] = nil
|
|
self.nprocesses = self.nprocesses - 1
|
|
end
|
|
}
|
|
_base_0.__index = _base_0
|
|
_class_0 = setmetatable({
|
|
__init = function(self, dag, nparallel)
|
|
self.dag, self.nparallel = dag, nparallel
|
|
self.processes = { }
|
|
self.nprocesses = 0
|
|
self.building = { }
|
|
end,
|
|
__base = _base_0,
|
|
__name = "Executor"
|
|
}, {
|
|
__index = _base_0,
|
|
__call = function(cls, ...)
|
|
local _self_0 = setmetatable({}, _base_0)
|
|
cls.__init(_self_0, ...)
|
|
return _self_0
|
|
end
|
|
})
|
|
_base_0.__class = _class_0
|
|
local self = _class_0
|
|
self.getmaxparallel = function(self)
|
|
local fd = open('/proc/cpuinfo', 'r')
|
|
if not (fd) then
|
|
return 1
|
|
end
|
|
local ncpu = 0
|
|
for line in fd:lines() do
|
|
if match(line, '^processor%s*:') then
|
|
ncpu = ncpu + 1
|
|
end
|
|
end
|
|
fd:close()
|
|
return ncpu == 0 and 1 or ncpu
|
|
end
|
|
Executor = _class_0
|
|
return _class_0
|
|
end
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.core.singleprocessexecutor" ] = function( ... ) local arg = _G.arg;
|
|
local Executor
|
|
do
|
|
local _class_0
|
|
local _base_0 = {
|
|
execute = function(self, opts)
|
|
local block = self.dag:buildablenodes()
|
|
while #block ~= 0 do
|
|
for _index_0 = 1, #block do
|
|
local node = block[_index_0]
|
|
node:build(opts)
|
|
node:updatecache()
|
|
node.built = true
|
|
end
|
|
block = self.dag:buildablenodes()
|
|
end
|
|
for name, node in pairs(self.dag.nodes) do
|
|
if not (node.built) then
|
|
error("Node " .. tostring(name) .. " wasn't built")
|
|
end
|
|
end
|
|
end
|
|
}
|
|
_base_0.__index = _base_0
|
|
_class_0 = setmetatable({
|
|
__init = function(self, dag, nparallel)
|
|
self.dag, self.nparallel = dag, nparallel
|
|
end,
|
|
__base = _base_0,
|
|
__name = "Executor"
|
|
}, {
|
|
__index = _base_0,
|
|
__call = function(cls, ...)
|
|
local _self_0 = setmetatable({}, _base_0)
|
|
cls.__init(_self_0, ...)
|
|
return _self_0
|
|
end
|
|
})
|
|
_base_0.__class = _class_0
|
|
local self = _class_0
|
|
self.getmaxparallel = function(self)
|
|
return 1
|
|
end
|
|
Executor = _class_0
|
|
return _class_0
|
|
end
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.env.global" ] = function( ... ) local arg = _G.arg;
|
|
local _ = require('moonbuild._')
|
|
return function(ctx)
|
|
local varlayer = setmetatable({ }, {
|
|
__index = _G
|
|
})
|
|
for name, var in pairs(ctx.variables) do
|
|
rawset(varlayer, name, var.value)
|
|
end
|
|
local env = setmetatable({ }, {
|
|
__index = varlayer,
|
|
__newindex = function(self, k)
|
|
return error("attempt to assign to global variable '" .. tostring(k) .. "', which is disabled in the global env")
|
|
end
|
|
})
|
|
rawset(env, '_', _)
|
|
rawset(env, '_G', env)
|
|
rawset(env, '_ENV', env)
|
|
return env, varlayer
|
|
end
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.env.init" ] = function( ... ) local arg = _G.arg;
|
|
local Target = require('moonbuild.core.Target')
|
|
local Variable = require('moonbuild.core.Variable')
|
|
local _ = require('moonbuild._')
|
|
local flatten
|
|
flatten = _.flatten
|
|
return function(ctx)
|
|
local varlayer = setmetatable({ }, {
|
|
__index = _G
|
|
})
|
|
for name, var in pairs(ctx.variables) do
|
|
rawset(varlayer, name, var.value)
|
|
end
|
|
local env = setmetatable({ }, {
|
|
__index = varlayer,
|
|
__newindex = function(self, k)
|
|
return error("attempt to assign to global variable '" .. tostring(k) .. "', use the function 'var' instead")
|
|
end
|
|
})
|
|
rawset(env, '_', _)
|
|
rawset(env, '_G', env)
|
|
rawset(env, '_ENV', env)
|
|
rawset(env, 'var', function(name, ...)
|
|
local var = Variable(name, ...)
|
|
ctx:addvar(var)
|
|
rawset(varlayer, name, var.value)
|
|
return var
|
|
end)
|
|
rawset(env, 'target', function(name, opts)
|
|
local target = Target(ctx, name, opts)
|
|
ctx:addtarget(target)
|
|
return target
|
|
end)
|
|
return env, varlayer
|
|
end
|
|
end
|
|
end
|
|
|
|
do
|
|
local _ENV = _ENV
|
|
package.preload[ "moonbuild.env.top" ] = function( ... ) local arg = _G.arg;
|
|
local initenv = require('moonbuild.env.init')
|
|
local Target = require('moonbuild.core.Target')
|
|
local Variable = require('moonbuild.core.Variable')
|
|
return function(ctx, overrides)
|
|
local env, varlayer = initenv(ctx)
|
|
rawset(env, 'default', function(target)
|
|
ctx:adddefault(target)
|
|
return target
|
|
end)
|
|
rawset(env, 'public', function(e)
|
|
local clazz = ((getmetatable(e)) or { }).__class
|
|
if clazz == Target then
|
|
e.public = true
|
|
elseif clazz == Variable then
|
|
e.public = true
|
|
local override = overrides[e.name]
|
|
if override then
|
|
if override == Variable.NIL then
|
|
override = nil
|
|
end
|
|
e.value = override
|
|
rawset(varlayer, e.name, override)
|
|
end
|
|
else
|
|
error("cannot set an object of type " .. tostring(clazz and clazz.__name or type(e)) .. " public")
|
|
end
|
|
return e
|
|
end)
|
|
rawset(env, 'init', function(fn)
|
|
if not ((type(fn)) == 'function') then
|
|
error("you can only add functions to init")
|
|
end
|
|
return ctx:addinit(fn)
|
|
end)
|
|
return env, varlayer
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
local loadfile
|
|
loadfile = require('moonscript.base').loadfile
|
|
local Context = require('moonbuild.context')
|
|
local Variable = require('moonbuild.core.Variable')
|
|
local DepGraph = require('moonbuild.core.DAG')
|
|
local sort, concat
|
|
do
|
|
local _obj_0 = table
|
|
sort, concat = _obj_0.sort, _obj_0.concat
|
|
end
|
|
return {
|
|
tasks = {
|
|
moonbuild = function(self)
|
|
local args = {
|
|
nparallel = self.parallel or self.j,
|
|
quiet = self.quiet or self.q,
|
|
buildfile = self.buildfile or self.b,
|
|
force = self.force or self.f
|
|
}
|
|
local ctx = Context()
|
|
ctx:load((loadfile(args.buildfile or 'Build.moon')), self)
|
|
ctx:init()
|
|
local dag = DepGraph(ctx, #self == 0 and ctx.defaulttargets or self)
|
|
local executor
|
|
do
|
|
local Executor
|
|
do
|
|
local ok
|
|
ok, Executor = pcall(function()
|
|
return require('moonbuild.core.multiprocessexecutor')
|
|
end)
|
|
Executor = ok and Executor or require('moonbuild.core.singleprocessexecutor')
|
|
end
|
|
if args.nparallel == true then
|
|
args.nparallel = Executor:getmaxparallel()
|
|
end
|
|
executor = Executor(dag, args.nparallel)
|
|
end
|
|
return executor:execute(args)
|
|
end
|
|
}
|
|
} |