mirror of
https://github.com/natnat-mc/moonbuild
synced 2026-05-28 14:19:39 +02:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0779ea3ad4 | |||
| e3e185110a | |||
| 7b4973f0b4 | |||
| c96b2ece70 | |||
| 0e23ccecfb | |||
| ccce358155 | |||
| a125eab22f | |||
| 0c43e3a5b1 | |||
| cf252749f4 | |||
| 16673afc61 | |||
| a26a1500df | |||
| d2db470347 | |||
| b80e9d38bb | |||
| 61f32c0675 | |||
| 04ca1f5a10 | |||
| ffce216a34 |
+2
-1
@@ -1 +1,2 @@
|
|||||||
/*/**.lua
|
/moonbuild/*.lua
|
||||||
|
/bin/*.lua
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
tasks:
|
tasks:
|
||||||
build: =>
|
build: =>
|
||||||
sh "moon bin/moonbuild.moon compile"
|
sh "moon bin/moonbuild.moon compile"
|
||||||
|
install: =>
|
||||||
|
sh "moon bin/moonbuild.moon install"
|
||||||
release: =>
|
release: =>
|
||||||
error "no version provided" unless @v
|
error "no version provided" unless @v
|
||||||
tasks.build!
|
tasks.build!
|
||||||
|
|||||||
+16
-3
@@ -5,15 +5,28 @@ BINARY_LUA = patsubst BINARY, '%.moon', '%.lua'
|
|||||||
OUT_AMALG = 'moonbuild.lua'
|
OUT_AMALG = 'moonbuild.lua'
|
||||||
|
|
||||||
public target 'clean', fn: =>
|
public target 'clean', fn: =>
|
||||||
-rm '-f', OUT_LUA
|
-rm '-f', OUT_LUA, BINARY_LUA
|
||||||
|
|
||||||
public target 'info', fn: =>
|
public target 'info', fn: =>
|
||||||
#echo "Moonscript sources:", SOURCES_MOON
|
#echo "Moonscript sources:", SOURCES_MOON
|
||||||
#echo "Compiled lua:", OUT_LUA
|
#echo "Compiled lua:", OUT_LUA
|
||||||
|
|
||||||
default target 'compile', from: OUT_AMALG
|
public target 'compile', deps: OUT_AMALG
|
||||||
|
|
||||||
target OUT_AMALG, from: {BINARY_LUA, OUT_LUA}, out: OUT_AMALG, fn: =>
|
public target 'install', from: OUT_AMALG, out: '/usr/local/bin/moonbuild', fn: =>
|
||||||
|
dfd, err = io.open @outfile, 'w'
|
||||||
|
error err unless dfd
|
||||||
|
ifd, err = io.open @infile, 'r'
|
||||||
|
error err unless ifd
|
||||||
|
dfd\write '#!/usr/bin/env lua5.3\n'
|
||||||
|
for line in ifd\lines!
|
||||||
|
dfd\write line, '\n'
|
||||||
|
ifd\close!
|
||||||
|
dfd\close!
|
||||||
|
-chmod '+x', @outfile
|
||||||
|
#echo "Installed at:", @outfile
|
||||||
|
|
||||||
|
default target OUT_AMALG, from: {BINARY_LUA, OUT_LUA}, out: OUT_AMALG, fn: =>
|
||||||
modules = foreach (patsubst OUT_LUA, '%.lua', '%'), => @gsub '/', '.'
|
modules = foreach (patsubst OUT_LUA, '%.lua', '%'), => @gsub '/', '.'
|
||||||
-Command 'amalg.lua', '-o', @outfile, '-s', 'bin/moonbuild.lua', modules
|
-Command 'amalg.lua', '-o', @outfile, '-s', 'bin/moonbuild.lua', modules
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ Basically like `make`, but in [Moonscript](https://moonscript.org) and with expl
|
|||||||
It's fast, based on lua, and it's easy to write DSLs with it, so the build instructions can be readable. Also, it's a full programming language, so there are no arbitrary restrictions.
|
It's fast, based on lua, and it's easy to write DSLs with it, so the build instructions can be readable. Also, it's a full programming language, so there are no arbitrary restrictions.
|
||||||
|
|
||||||
## How do I install it?
|
## How do I install it?
|
||||||
|
Any of these will work
|
||||||
- `luarocks install moonbuild` (probably as root)
|
- `luarocks install moonbuild` (probably as root)
|
||||||
|
- `moon bin/moonbuild.moon install` (probably as root, in the cloned repo)
|
||||||
|
- `alfons install` (probably as root, in the cloned repo, requires alfons)
|
||||||
|
|
||||||
## Now, how do I use it?
|
## Now, how do I use it?
|
||||||
First, you'll need a `Build.moon`, `Buildfile.moon`, `Build` or `Buildfile` in the root of your project.
|
First, you'll need a `Build.moon`, `Buildfile.moon`, `Build` or `Buildfile` in the root of your project.
|
||||||
|
|||||||
@@ -1,429 +0,0 @@
|
|||||||
local argparse = require('argparse')
|
|
||||||
require('moonscript')
|
|
||||||
local loadfile
|
|
||||||
loadfile = require('moonscript.base').loadfile
|
|
||||||
local truncate_traceback, rewrite_traceback
|
|
||||||
do
|
|
||||||
local _obj_0 = require('moonscript.errors')
|
|
||||||
truncate_traceback, rewrite_traceback = _obj_0.truncate_traceback, _obj_0.rewrite_traceback
|
|
||||||
end
|
|
||||||
local trim
|
|
||||||
trim = require('moonscript.util').trim
|
|
||||||
local util = require('moonbuild.util')
|
|
||||||
local exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs
|
|
||||||
exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs = util.exists, util.mtime, util.run, util.min, util.max, util.first, util.flatten, util.match, util.patsubst, util.sortedpairs
|
|
||||||
local insert, concat
|
|
||||||
do
|
|
||||||
local _obj_0 = table
|
|
||||||
insert, concat = _obj_0.insert, _obj_0.concat
|
|
||||||
end
|
|
||||||
local parser = argparse('moonbuild')
|
|
||||||
parser:argument('targets', "Targets to run"):args('*')
|
|
||||||
parser:flag('-a --noskip', "Always run targets")
|
|
||||||
parser:flag('-l --list', "List available targets")
|
|
||||||
parser:flag('-d --deps', "List targets and their dependancies")
|
|
||||||
local args = parser:parse()
|
|
||||||
local loadwithscope
|
|
||||||
loadwithscope = function(file, scope)
|
|
||||||
local fn, err = loadfile(file)
|
|
||||||
if not (fn) then
|
|
||||||
error(err or "failed to load code")
|
|
||||||
end
|
|
||||||
local dumped
|
|
||||||
dumped, err = string.dump(fn)
|
|
||||||
if not (dumped) then
|
|
||||||
error(err or "failed to dump function")
|
|
||||||
end
|
|
||||||
return load(dumped, file, 'b', scope)
|
|
||||||
end
|
|
||||||
local pcall
|
|
||||||
pcall = function(fn, ...)
|
|
||||||
local rewrite
|
|
||||||
rewrite = function(err)
|
|
||||||
local trace = debug.traceback('', 2)
|
|
||||||
local trunc = truncate_traceback(trim(trace))
|
|
||||||
return rewrite_traceback(trunc, err)
|
|
||||||
end
|
|
||||||
return xpcall(fn, rewrite, ...)
|
|
||||||
end
|
|
||||||
local Command
|
|
||||||
do
|
|
||||||
local _class_0
|
|
||||||
local _base_0 = {
|
|
||||||
__unm = function(self)
|
|
||||||
return self:run({
|
|
||||||
error = true,
|
|
||||||
print = true
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
__len = function(self)
|
|
||||||
return self:run({
|
|
||||||
error = true
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
__tostring = function(self)
|
|
||||||
return self.cmd
|
|
||||||
end,
|
|
||||||
run = function(self, params)
|
|
||||||
return run(self.cmd, self.args, params)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
_base_0.__index = _base_0
|
|
||||||
_class_0 = setmetatable({
|
|
||||||
__init = function(self, cmd, ...)
|
|
||||||
self.cmd = cmd
|
|
||||||
self.args = {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
__base = _base_0,
|
|
||||||
__name = "Command"
|
|
||||||
}, {
|
|
||||||
__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.run = function(self, ...)
|
|
||||||
return -self(...)
|
|
||||||
end
|
|
||||||
Command = _class_0
|
|
||||||
end
|
|
||||||
local BuildObject
|
|
||||||
do
|
|
||||||
local _class_0
|
|
||||||
local all, skip
|
|
||||||
local _base_0 = {
|
|
||||||
__tostring = function(self)
|
|
||||||
return "Target " .. tostring(self.name) .. " (" .. tostring(concat(self.deps, ', ')) .. ")"
|
|
||||||
end,
|
|
||||||
build = function(self, name, upper)
|
|
||||||
if upper == nil then
|
|
||||||
upper = { }
|
|
||||||
end
|
|
||||||
if skip[name] then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if upper[self] then
|
|
||||||
error("Cycle detected on " .. tostring(self.name))
|
|
||||||
end
|
|
||||||
upper = setmetatable({
|
|
||||||
[self] = true
|
|
||||||
}, {
|
|
||||||
__index = upper
|
|
||||||
})
|
|
||||||
if self.name ~= name then
|
|
||||||
local _list_0 = self.deps
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local dep = _list_0[_index_0]
|
|
||||||
self.__class:build((patsubst(name, self.name, dep)), upper)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local _list_0 = self.deps
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local dep = _list_0[_index_0]
|
|
||||||
self.__class:build(dep, upper)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not (self:shouldbuild(name)) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local ins = self.ins
|
|
||||||
local outs = self.outs
|
|
||||||
if self.name ~= name then
|
|
||||||
do
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
local _list_0 = self.ins
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local elem = _list_0[_index_0]
|
|
||||||
_accum_0[_len_0] = patsubst(name, self.name, elem)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
|
||||||
ins = _accum_0
|
|
||||||
end
|
|
||||||
do
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
local _list_0 = self.outs
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local elem = _list_0[_index_0]
|
|
||||||
_accum_0[_len_0] = patsubst(name, self.name, elem)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
|
||||||
outs = _accum_0
|
|
||||||
end
|
|
||||||
print("Building " .. tostring(self.name) .. " as " .. tostring(name))
|
|
||||||
else
|
|
||||||
print("Building " .. tostring(name))
|
|
||||||
end
|
|
||||||
local ok, err = pcall(function()
|
|
||||||
return self.fn({
|
|
||||||
ins = ins,
|
|
||||||
outs = outs,
|
|
||||||
infile = ins[1],
|
|
||||||
outfile = outs[1],
|
|
||||||
name = name
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
if not (ok) then
|
|
||||||
error("Can't build " .. tostring(self.name) .. ": lua error\n" .. tostring(err))
|
|
||||||
end
|
|
||||||
for _index_0 = 1, #outs do
|
|
||||||
local f = outs[_index_0]
|
|
||||||
if not (exists(f)) then
|
|
||||||
error("Can't build " .. tostring(self.name) .. ": output file " .. tostring(f) .. " not created")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
skip[name] = true
|
|
||||||
end,
|
|
||||||
shouldbuild = function(self, name)
|
|
||||||
if args.noskip then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
if #self.ins == 0 or #self.outs == 0 then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
local ins
|
|
||||||
if self.name ~= name then
|
|
||||||
do
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
local _list_0 = self.ins
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local elem = _list_0[_index_0]
|
|
||||||
_accum_0[_len_0] = patsubst(name, self.name, elem)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
|
||||||
ins = _accum_0
|
|
||||||
end
|
|
||||||
else
|
|
||||||
ins = self.ins
|
|
||||||
end
|
|
||||||
local itimes
|
|
||||||
do
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
for _index_0 = 1, #ins do
|
|
||||||
local f = ins[_index_0]
|
|
||||||
_accum_0[_len_0] = mtime(f)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
|
||||||
itimes = _accum_0
|
|
||||||
end
|
|
||||||
for i = 1, #self.ins do
|
|
||||||
if not (itimes[i]) then
|
|
||||||
error("Can't build " .. tostring(self.name) .. ": missing inputs")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local outs
|
|
||||||
if self.name ~= name then
|
|
||||||
do
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
local _list_0 = self.outs
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local elem = _list_0[_index_0]
|
|
||||||
_accum_0[_len_0] = patsubst(name, self.name, elem)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
|
||||||
outs = _accum_0
|
|
||||||
end
|
|
||||||
else
|
|
||||||
outs = self.outs
|
|
||||||
end
|
|
||||||
local otimes
|
|
||||||
do
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
for _index_0 = 1, #outs do
|
|
||||||
local f = outs[_index_0]
|
|
||||||
_accum_0[_len_0] = mtime(f)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
|
||||||
otimes = _accum_0
|
|
||||||
end
|
|
||||||
for i = 1, #self.outs do
|
|
||||||
if not otimes[i] then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return (max(itimes)) > (min(otimes))
|
|
||||||
end
|
|
||||||
}
|
|
||||||
_base_0.__index = _base_0
|
|
||||||
_class_0 = setmetatable({
|
|
||||||
__init = function(self, name, outs, ins, deps, fn)
|
|
||||||
if outs == nil then
|
|
||||||
outs = { }
|
|
||||||
end
|
|
||||||
if ins == nil then
|
|
||||||
ins = { }
|
|
||||||
end
|
|
||||||
if deps == nil then
|
|
||||||
deps = { }
|
|
||||||
end
|
|
||||||
if fn == nil then
|
|
||||||
fn = function(self) end
|
|
||||||
end
|
|
||||||
self.name, self.outs, self.ins, self.deps, self.fn = name, outs, ins, deps, fn
|
|
||||||
self.skip = false
|
|
||||||
if all[self.name] then
|
|
||||||
error("Duplicate build name " .. tostring(self.name))
|
|
||||||
end
|
|
||||||
all[self.name] = self
|
|
||||||
end,
|
|
||||||
__base = _base_0,
|
|
||||||
__name = "BuildObject"
|
|
||||||
}, {
|
|
||||||
__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
|
|
||||||
all = { }
|
|
||||||
skip = { }
|
|
||||||
self.find = function(self, name)
|
|
||||||
local target = all[name]
|
|
||||||
if target then
|
|
||||||
return target
|
|
||||||
end
|
|
||||||
for glob, tgt in pairs(all) do
|
|
||||||
if match(name, glob) then
|
|
||||||
return tgt
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
self.list = function(self)
|
|
||||||
local _tbl_0 = { }
|
|
||||||
for name, target in pairs(all) do
|
|
||||||
do
|
|
||||||
local _tbl_1 = { }
|
|
||||||
local _list_0 = target.deps
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local dep = _list_0[_index_0]
|
|
||||||
_tbl_1[dep] = self:find(dep)
|
|
||||||
end
|
|
||||||
_tbl_0[target] = _tbl_1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return _tbl_0
|
|
||||||
end
|
|
||||||
self.build = function(self, name, upper)
|
|
||||||
local target = (self:find(name)) or error("No such target: " .. tostring(name))
|
|
||||||
return target:build(name, upper)
|
|
||||||
end
|
|
||||||
BuildObject = _class_0
|
|
||||||
end
|
|
||||||
if setfenv then
|
|
||||||
error("Need Lua >=5.2")
|
|
||||||
end
|
|
||||||
local targets = { }
|
|
||||||
local defaulttarget = 'all'
|
|
||||||
local buildscope = {
|
|
||||||
default = function(target)
|
|
||||||
defaulttarget = target.name
|
|
||||||
return target
|
|
||||||
end,
|
|
||||||
public = function(target)
|
|
||||||
insert(targets, target.name)
|
|
||||||
return target
|
|
||||||
end,
|
|
||||||
target = function(name, params)
|
|
||||||
local tout = flatten(params.out)
|
|
||||||
local tin = flatten(params["in"])
|
|
||||||
local tdeps = flatten(params.deps)
|
|
||||||
local _list_0 = flatten(params.from)
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local f = _list_0[_index_0]
|
|
||||||
insert(tin, f)
|
|
||||||
insert(tdeps, f)
|
|
||||||
end
|
|
||||||
return BuildObject(name, tout, tin, tdeps, params.fn)
|
|
||||||
end,
|
|
||||||
Command = Command
|
|
||||||
}
|
|
||||||
for k, fn in pairs(util) do
|
|
||||||
buildscope[k] = fn
|
|
||||||
end
|
|
||||||
setmetatable(buildscope, {
|
|
||||||
__index = function(self, k)
|
|
||||||
local global = rawget(_G, k)
|
|
||||||
if global then
|
|
||||||
return global
|
|
||||||
end
|
|
||||||
return function(...)
|
|
||||||
return Command(k, ...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
local file = first({
|
|
||||||
'Build.moon',
|
|
||||||
'Buildfile.moon',
|
|
||||||
'Build',
|
|
||||||
'Buildfile'
|
|
||||||
}, exists)
|
|
||||||
if not (file) then
|
|
||||||
error("No Build.moon or Buildfile found")
|
|
||||||
end
|
|
||||||
local buildfn = loadwithscope(file, buildscope)
|
|
||||||
if not (buildfn) then
|
|
||||||
error("Failed to load build function")
|
|
||||||
end
|
|
||||||
local ok, err = pcall(buildfn)
|
|
||||||
if not (ok) then
|
|
||||||
if err then
|
|
||||||
io.stderr:write(err, '\n')
|
|
||||||
else
|
|
||||||
io.stderr:write("Unknown error\n")
|
|
||||||
end
|
|
||||||
os.exit(1)
|
|
||||||
end
|
|
||||||
if args.list then
|
|
||||||
io.write("Available targets:\n")
|
|
||||||
io.write("\t" .. tostring(concat(targets, ', ')) .. "\n")
|
|
||||||
os.exit(0)
|
|
||||||
end
|
|
||||||
if args.deps then
|
|
||||||
io.write("Targets:\n")
|
|
||||||
for target, deps in sortedpairs(BuildObject:list(), function(a, b)
|
|
||||||
return a.name < b.name
|
|
||||||
end) do
|
|
||||||
io.write("\t" .. tostring(target.name) .. " ")
|
|
||||||
if #target.ins == 0 then
|
|
||||||
if #target.outs == 0 then
|
|
||||||
io.write("[no in/out]")
|
|
||||||
else
|
|
||||||
io.write("[spontaneous generation]")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if #target.outs == 0 then
|
|
||||||
io.write("[consumer]")
|
|
||||||
else
|
|
||||||
io.write("(" .. tostring(concat(target.ins, ', ')) .. " -> " .. tostring(concat(target.outs, ', ')) .. ")")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
io.write("\n")
|
|
||||||
for name, dep in sortedpairs(deps) do
|
|
||||||
io.write("\t\t" .. tostring(name) .. " (" .. tostring(dep.name) .. ")\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
os.exit(0)
|
|
||||||
end
|
|
||||||
if #args.targets == 0 then
|
|
||||||
BuildObject:build(defaulttarget)
|
|
||||||
end
|
|
||||||
local _list_0 = args.targets
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local target = _list_0[_index_0]
|
|
||||||
BuildObject:build(target)
|
|
||||||
end
|
|
||||||
+61
-48
@@ -1,43 +1,44 @@
|
|||||||
#!/usr/bin/env moon
|
#!/usr/bin/env moon
|
||||||
|
|
||||||
argparse=require 'argparse'
|
argparse = require 'argparse'
|
||||||
|
|
||||||
require 'moonscript'
|
require 'moonscript'
|
||||||
import loadfile from require 'moonscript.base'
|
import loadfile from require 'moonscript.base'
|
||||||
import truncate_traceback, rewrite_traceback from require 'moonscript.errors'
|
import truncate_traceback, rewrite_traceback from require 'moonscript.errors'
|
||||||
import trim from require 'moonscript.util'
|
import trim from require 'moonscript.util'
|
||||||
|
|
||||||
util=require 'moonbuild.util'
|
util = require 'moonbuild.util'
|
||||||
|
import freezecache, invalidatecache from require 'moonbuild.fsutil'
|
||||||
import exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs from util
|
import exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs from util
|
||||||
|
|
||||||
import insert, concat from table
|
import insert, concat from table
|
||||||
|
|
||||||
parser=argparse 'moonbuild'
|
parser = argparse 'moonbuild'
|
||||||
parser\argument('targets', "Targets to run")\args '*'
|
parser\argument('targets', "Targets to run")\args '*'
|
||||||
parser\flag '-a --noskip', "Always run targets"
|
parser\flag '-a --noskip', "Always run targets"
|
||||||
parser\flag '-l --list', "List available targets"
|
parser\flag '-l --list', "List available targets"
|
||||||
parser\flag '-d --deps', "List targets and their dependancies"
|
parser\flag '-d --deps', "List targets and their dependancies"
|
||||||
args=parser\parse!
|
args = parser\parse!
|
||||||
|
|
||||||
-- util functions
|
-- util functions
|
||||||
loadwithscope= (file, scope) ->
|
loadwithscope = (file, scope) ->
|
||||||
fn, err=loadfile file
|
fn, err = loadfile file
|
||||||
error err or "failed to load code" unless fn
|
error err or "failed to load code" unless fn
|
||||||
dumped, err=string.dump fn
|
dumped, err = string.dump fn
|
||||||
error err or "failed to dump function" unless dumped
|
error err or "failed to dump function" unless dumped
|
||||||
load dumped, file, 'b', scope
|
load dumped, file, 'b', scope
|
||||||
pcall= (fn, ...) ->
|
pcall = (fn, ...) ->
|
||||||
rewrite=(err) ->
|
rewrite = (err) ->
|
||||||
trace=debug.traceback '', 2
|
trace = debug.traceback '', 2
|
||||||
trunc=truncate_traceback trim trace
|
trunc = truncate_traceback trim trace
|
||||||
rewrite_traceback trunc, err
|
(rewrite_traceback trunc, err) or trace
|
||||||
xpcall fn, rewrite, ...
|
xpcall fn, rewrite, ...
|
||||||
|
|
||||||
-- command object
|
-- command object
|
||||||
-- represents a command that can be called
|
-- represents a command that can be called
|
||||||
class Command
|
class Command
|
||||||
new: (@cmd, ...) =>
|
new: (@cmd, ...) =>
|
||||||
@args={...}
|
@args = {...}
|
||||||
|
|
||||||
__unm: => @run error: true, print: true
|
__unm: => @run error: true, print: true
|
||||||
__len: => @run error: true
|
__len: => @run error: true
|
||||||
@@ -49,11 +50,11 @@ class Command
|
|||||||
-- build object
|
-- build object
|
||||||
-- represents a target
|
-- represents a target
|
||||||
class BuildObject
|
class BuildObject
|
||||||
all={}
|
all = {}
|
||||||
skip={}
|
skip = {}
|
||||||
|
|
||||||
@find: (name) =>
|
@find: (name) =>
|
||||||
target=all[name]
|
target = all[name]
|
||||||
return target if target
|
return target if target
|
||||||
for glob, tgt in pairs all
|
for glob, tgt in pairs all
|
||||||
return tgt if match name, glob
|
return tgt if match name, glob
|
||||||
@@ -63,16 +64,16 @@ class BuildObject
|
|||||||
{target, {dep, @find dep for dep in *target.deps} for name, target in pairs all}
|
{target, {dep, @find dep for dep in *target.deps} for name, target in pairs all}
|
||||||
|
|
||||||
@build: (name, upper) =>
|
@build: (name, upper) =>
|
||||||
target=(@find name) or error "No such target: #{name}"
|
target = (@find name) or error "No such target: #{name}"
|
||||||
target\build name, upper
|
target\build name, upper
|
||||||
|
|
||||||
__tostring: =>
|
__tostring: =>
|
||||||
"Target #{@name} (#{concat @deps, ', '})"
|
"Target #{@name} (#{concat @deps, ', '})"
|
||||||
|
|
||||||
new: (@name, @outs={}, @ins={}, @deps={}, @fn= =>) =>
|
new: (@name, @outs={}, @ins={}, @deps={}, @fn= =>) =>
|
||||||
@skip=false
|
@skip = false
|
||||||
error "Duplicate build name #{@name}" if all[@name]
|
error "Duplicate build name #{@name}" if all[@name]
|
||||||
all[@name]=@
|
all[@name] = @
|
||||||
|
|
||||||
build: (name, upper={}) =>
|
build: (name, upper={}) =>
|
||||||
return if skip[name]
|
return if skip[name]
|
||||||
@@ -84,43 +85,45 @@ class BuildObject
|
|||||||
@@build dep, upper for dep in *@deps
|
@@build dep, upper for dep in *@deps
|
||||||
return unless @shouldbuild name
|
return unless @shouldbuild name
|
||||||
|
|
||||||
ins=@ins
|
ins = @ins
|
||||||
outs=@outs
|
outs = @outs
|
||||||
if @name!=name
|
if @name!=name
|
||||||
ins=[patsubst name, @name, elem for elem in *@ins]
|
ins = [patsubst name, @name, elem for elem in *@ins]
|
||||||
outs=[patsubst name, @name, elem for elem in *@outs]
|
outs = [patsubst name, @name, elem for elem in *@outs]
|
||||||
print "Building #{@name} as #{name}"
|
print "Building #{@name} as #{name}"
|
||||||
else
|
else
|
||||||
print "Building #{name}"
|
print "Building #{name}"
|
||||||
ok, err=pcall ->
|
freezecache file for file in *outs
|
||||||
|
ok, err = pcall ->
|
||||||
@.fn
|
@.fn
|
||||||
ins: ins
|
ins: ins
|
||||||
outs: outs
|
outs: outs
|
||||||
infile: ins[1]
|
infile: ins[1]
|
||||||
outfile: outs[1]
|
outfile: outs[1]
|
||||||
name: name
|
name: name
|
||||||
|
invalidatecache file for file in *outs
|
||||||
error "Can't build #{@name}: lua error\n#{err}" unless ok
|
error "Can't build #{@name}: lua error\n#{err}" unless ok
|
||||||
for f in *outs
|
for f in *outs
|
||||||
error "Can't build #{@name}: output file #{f} not created" unless exists f
|
error "Can't build #{@name}: output file #{f} not created" unless exists f
|
||||||
skip[name]=true
|
skip[name] = true
|
||||||
|
|
||||||
shouldbuild: (name) =>
|
shouldbuild: (name) =>
|
||||||
return true if args.noskip
|
return true if args.noskip
|
||||||
return true if #@ins==0 or #@outs==0
|
return true if #@ins==0 or #@outs==0
|
||||||
|
|
||||||
ins=if @name!=name
|
ins = if @name!=name
|
||||||
[patsubst name, @name, elem for elem in *@ins]
|
[patsubst name, @name, elem for elem in *@ins]
|
||||||
else
|
else
|
||||||
@ins
|
@ins
|
||||||
itimes=[mtime f for f in *ins]
|
itimes = [mtime f for f in *ins]
|
||||||
for i=1, #@ins
|
for i=1, #@ins
|
||||||
error "Can't build #{@name}: missing inputs" unless itimes[i]
|
error "Can't build #{@name}: missing inputs" unless itimes[i]
|
||||||
|
|
||||||
outs=if @name!=name
|
outs = if @name!=name
|
||||||
[patsubst name, @name, elem for elem in *@outs]
|
[patsubst name, @name, elem for elem in *@outs]
|
||||||
else
|
else
|
||||||
@outs
|
@outs
|
||||||
otimes=[mtime f for f in *outs]
|
otimes = [mtime f for f in *outs]
|
||||||
for i=1, #@outs
|
for i=1, #@outs
|
||||||
return true if not otimes[i]
|
return true if not otimes[i]
|
||||||
|
|
||||||
@@ -128,10 +131,9 @@ class BuildObject
|
|||||||
|
|
||||||
error "Need Lua >=5.2" if setfenv
|
error "Need Lua >=5.2" if setfenv
|
||||||
|
|
||||||
targets={}
|
local targets, defaulttarget
|
||||||
defaulttarget='all'
|
|
||||||
|
|
||||||
buildscope=
|
buildscope =
|
||||||
default: (target) ->
|
default: (target) ->
|
||||||
defaulttarget=target.name
|
defaulttarget=target.name
|
||||||
target
|
target
|
||||||
@@ -139,30 +141,41 @@ buildscope=
|
|||||||
insert targets, target.name
|
insert targets, target.name
|
||||||
target
|
target
|
||||||
target: (name, params) ->
|
target: (name, params) ->
|
||||||
tout=flatten params.out
|
tout = flatten params.out
|
||||||
tin=flatten params.in
|
tin = flatten params.in
|
||||||
tdeps=flatten params.deps
|
tdeps = flatten params.deps
|
||||||
for f in *flatten params.from
|
for f in *flatten params.from
|
||||||
insert tin, f
|
insert tin, f
|
||||||
insert tdeps, f
|
insert tdeps, f
|
||||||
BuildObject name, tout, tin, tdeps, params.fn
|
BuildObject name, tout, tin, tdeps, params.fn
|
||||||
:Command
|
:Command
|
||||||
buildscope[k]=fn for k, fn in pairs util
|
buildscope[k] = fn for k, fn in pairs util
|
||||||
|
|
||||||
setmetatable buildscope,
|
setmetatable buildscope,
|
||||||
__index: (k) =>
|
__index: (k) =>
|
||||||
global=rawget _G, k
|
global = rawget _G, k
|
||||||
return global if global
|
return global if global
|
||||||
(...) -> Command k, ...
|
(...) -> Command k, ...
|
||||||
|
|
||||||
file=first {'Build.moon', 'Buildfile.moon', 'Build', 'Buildfile'}, exists
|
loadtargets = ->
|
||||||
error "No Build.moon or Buildfile found" unless file
|
targets = {}
|
||||||
buildfn=loadwithscope file, buildscope
|
defaulttarget = 'all'
|
||||||
error "Failed to load build function" unless buildfn
|
file = first {'Build.moon', 'Buildfile.moon', 'Build', 'Buildfile'}, exists
|
||||||
ok, err=pcall buildfn
|
error "No Build.moon or Buildfile found" unless file
|
||||||
|
buildfn = loadwithscope file, buildscope
|
||||||
|
error "Failed to load build function" unless buildfn
|
||||||
|
buildfn!
|
||||||
|
|
||||||
|
buildtargets = ->
|
||||||
|
if #args.targets==0
|
||||||
|
BuildObject\build defaulttarget
|
||||||
|
for target in *args.targets
|
||||||
|
BuildObject\build target
|
||||||
|
|
||||||
|
ok, err = pcall loadtargets
|
||||||
unless ok
|
unless ok
|
||||||
if err
|
if err
|
||||||
io.stderr\write err, '\n'
|
io.stderr\write "Error while loading build file: ", err, '\n'
|
||||||
else
|
else
|
||||||
io.stderr\write "Unknown error\n"
|
io.stderr\write "Unknown error\n"
|
||||||
os.exit 1
|
os.exit 1
|
||||||
@@ -188,10 +201,10 @@ if args.deps
|
|||||||
io.write "(#{concat target.ins, ', '} -> #{concat target.outs, ', '})"
|
io.write "(#{concat target.ins, ', '} -> #{concat target.outs, ', '})"
|
||||||
io.write "\n"
|
io.write "\n"
|
||||||
for name, dep in sortedpairs deps
|
for name, dep in sortedpairs deps
|
||||||
io.write "\t\t#{name} (#{dep.name})\n"
|
io.write "\t\t#{name}"
|
||||||
|
if name!=dep.name
|
||||||
|
io.write " (#{dep.name})"
|
||||||
|
io.write "\n"
|
||||||
os.exit 0
|
os.exit 0
|
||||||
|
|
||||||
if #args.targets==0
|
buildtargets!
|
||||||
BuildObject\build defaulttarget
|
|
||||||
for target in *args.targets
|
|
||||||
BuildObject\build target
|
|
||||||
|
|||||||
+196
-32
@@ -1,11 +1,78 @@
|
|||||||
do
|
do
|
||||||
|
|
||||||
|
do
|
||||||
|
local _ENV = _ENV
|
||||||
|
package.preload[ "moonbuild.fscache" ] = function( ... ) local arg = _G.arg;
|
||||||
|
local attributes, dir
|
||||||
|
do
|
||||||
|
local _obj_0 = require('lfs')
|
||||||
|
attributes, dir = _obj_0.attributes, _obj_0.dir
|
||||||
|
end
|
||||||
|
local unpack = unpack or table.unpack
|
||||||
|
local FROZEN
|
||||||
|
FROZEN = function() end
|
||||||
|
local makecached
|
||||||
|
makecached = function(fn)
|
||||||
|
local cache = { }
|
||||||
|
local invalidate
|
||||||
|
invalidate = function(val)
|
||||||
|
cache[val] = nil
|
||||||
|
end
|
||||||
|
local freeze
|
||||||
|
freeze = function(val)
|
||||||
|
cache[val] = FROZEN
|
||||||
|
end
|
||||||
|
local clear
|
||||||
|
clear = function()
|
||||||
|
cache = { }
|
||||||
|
end
|
||||||
|
local get
|
||||||
|
get = function(val)
|
||||||
|
local cached = cache[val]
|
||||||
|
if cached ~= FROZEN and cached ~= nil then
|
||||||
|
return unpack(cached)
|
||||||
|
end
|
||||||
|
local ret = {
|
||||||
|
fn(val)
|
||||||
|
}
|
||||||
|
if cached ~= FROZEN then
|
||||||
|
cache[val] = ret
|
||||||
|
end
|
||||||
|
return unpack(ret)
|
||||||
|
end
|
||||||
|
return setmetatable({
|
||||||
|
get = get,
|
||||||
|
invalidate = invalidate,
|
||||||
|
freeze = freeze,
|
||||||
|
clear = clear
|
||||||
|
}, {
|
||||||
|
__call = function(self, val)
|
||||||
|
return get(val)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
return {
|
||||||
|
attributes = makecached(attributes),
|
||||||
|
dir = makecached(function(file)
|
||||||
|
local _accum_0 = { }
|
||||||
|
local _len_0 = 1
|
||||||
|
for k in dir(file) do
|
||||||
|
_accum_0[_len_0] = k
|
||||||
|
_len_0 = _len_0 + 1
|
||||||
|
end
|
||||||
|
return _accum_0
|
||||||
|
end)
|
||||||
|
}
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
do
|
do
|
||||||
local _ENV = _ENV
|
local _ENV = _ENV
|
||||||
package.preload[ "moonbuild.fsutil" ] = function( ... ) local arg = _G.arg;
|
package.preload[ "moonbuild.fsutil" ] = function( ... ) local arg = _G.arg;
|
||||||
local dir, attributes
|
local dir, attributes
|
||||||
do
|
do
|
||||||
local _obj_0 = require('lfs')
|
local _obj_0 = require('moonbuild.fscache')
|
||||||
dir, attributes = _obj_0.dir, _obj_0.attributes
|
dir, attributes = _obj_0.dir, _obj_0.attributes
|
||||||
end
|
end
|
||||||
local gmatch, match, gsub, sub
|
local gmatch, match, gsub, sub
|
||||||
@@ -13,16 +80,59 @@ do
|
|||||||
local _obj_0 = string
|
local _obj_0 = string
|
||||||
gmatch, match, gsub, sub = _obj_0.gmatch, _obj_0.match, _obj_0.gsub, _obj_0.sub
|
gmatch, match, gsub, sub = _obj_0.gmatch, _obj_0.match, _obj_0.gsub, _obj_0.sub
|
||||||
end
|
end
|
||||||
local insert, concat
|
local insert, remove, concat
|
||||||
do
|
do
|
||||||
local _obj_0 = table
|
local _obj_0 = table
|
||||||
insert, concat = _obj_0.insert, _obj_0.concat
|
insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat
|
||||||
|
end
|
||||||
|
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)) == '/'
|
||||||
|
for i = 1, #parts do
|
||||||
|
local _continue_0 = false
|
||||||
|
repeat
|
||||||
|
if parts[i] == '.' then
|
||||||
|
remove(parts, i)
|
||||||
|
i = i - 1
|
||||||
|
_continue_0 = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
if parts[i] == '..' and i ~= 1 then
|
||||||
|
remove(parts, i)
|
||||||
|
remove(parts, i - 1)
|
||||||
|
i = i - 2
|
||||||
|
_continue_0 = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
_continue_0 = true
|
||||||
|
until true
|
||||||
|
if not _continue_0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #parts == 0 then
|
||||||
|
return '.'
|
||||||
|
else
|
||||||
|
return (absolute and '/' or '') .. concat(parts, '/')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
local ls
|
local ls
|
||||||
ls = function(d)
|
ls = function(d)
|
||||||
local _accum_0 = { }
|
local _accum_0 = { }
|
||||||
local _len_0 = 1
|
local _len_0 = 1
|
||||||
for f in dir(d) do
|
local _list_0 = dir(normalizepath(d))
|
||||||
|
for _index_0 = 1, #_list_0 do
|
||||||
|
local f = _list_0[_index_0]
|
||||||
if f ~= '.' and f ~= '..' then
|
if f ~= '.' and f ~= '..' then
|
||||||
_accum_0[_len_0] = f
|
_accum_0[_len_0] = f
|
||||||
_len_0 = _len_0 + 1
|
_len_0 = _len_0 + 1
|
||||||
@@ -37,7 +147,9 @@ lswithpath = function(d)
|
|||||||
end
|
end
|
||||||
local _accum_0 = { }
|
local _accum_0 = { }
|
||||||
local _len_0 = 1
|
local _len_0 = 1
|
||||||
for f in dir(d) do
|
local _list_0 = dir(normalizepath(d))
|
||||||
|
for _index_0 = 1, #_list_0 do
|
||||||
|
local f = _list_0[_index_0]
|
||||||
if f ~= '.' and f ~= '..' then
|
if f ~= '.' and f ~= '..' then
|
||||||
_accum_0[_len_0] = d .. '/' .. f
|
_accum_0[_len_0] = d .. '/' .. f
|
||||||
_len_0 = _len_0 + 1
|
_len_0 = _len_0 + 1
|
||||||
@@ -47,16 +159,16 @@ lswithpath = function(d)
|
|||||||
end
|
end
|
||||||
local exists
|
local exists
|
||||||
exists = function(f)
|
exists = function(f)
|
||||||
return (attributes(f)) ~= nil
|
return (attributes(normalizepath(f))) ~= nil
|
||||||
end
|
end
|
||||||
local isdir
|
local isdir
|
||||||
isdir = function(f)
|
isdir = function(f)
|
||||||
local a = attributes(f)
|
local a = attributes(normalizepath(f))
|
||||||
return a and a.mode == 'directory' or false
|
return a and a.mode == 'directory' or false
|
||||||
end
|
end
|
||||||
local mtime
|
local mtime
|
||||||
mtime = function(f)
|
mtime = function(f)
|
||||||
local a = attributes(f)
|
local a = attributes(normalizepath(f))
|
||||||
return a and a.modification
|
return a and a.modification
|
||||||
end
|
end
|
||||||
local matchglob
|
local matchglob
|
||||||
@@ -93,7 +205,7 @@ wildcard = function(glob)
|
|||||||
local absolute = (sub(glob, 1, 1)) == '/'
|
local absolute = (sub(glob, 1, 1)) == '/'
|
||||||
for i, part in ipairs(parts) do
|
for i, part in ipairs(parts) do
|
||||||
local prevpath = (absolute and '/' or '') .. concat(parts, '/', 1, i - 1)
|
local prevpath = (absolute and '/' or '') .. concat(parts, '/', 1, i - 1)
|
||||||
local currpath = prevpath .. '/' .. part
|
local currpath = (i == 1 and '' or (prevpath .. '/')) .. part
|
||||||
if match(part, '%*%*.*%*%*') then
|
if match(part, '%*%*.*%*%*') then
|
||||||
error("Two '**' in the same path component in a wildcard")
|
error("Two '**' in the same path component in a wildcard")
|
||||||
end
|
end
|
||||||
@@ -152,11 +264,37 @@ wildcard = function(glob)
|
|||||||
return { }
|
return { }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local parentdir
|
||||||
|
parentdir = function(file)
|
||||||
|
return normalizepath(file .. '/..')
|
||||||
|
end
|
||||||
|
local freezecache
|
||||||
|
freezecache = function(file)
|
||||||
|
dir.freeze(file)
|
||||||
|
dir.freeze(parentdir(file))
|
||||||
|
return attributes.invalidate(file)
|
||||||
|
end
|
||||||
|
local invalidatecache
|
||||||
|
invalidatecache = function(file)
|
||||||
|
dir.invalidate(file)
|
||||||
|
dir.invalidate(parentdir(file))
|
||||||
|
return attributes.invalidate(file)
|
||||||
|
end
|
||||||
|
local clearcache
|
||||||
|
clearcache = function()
|
||||||
|
dir.clear()
|
||||||
|
return attributes.clear()
|
||||||
|
end
|
||||||
return {
|
return {
|
||||||
wildcard = wildcard,
|
wildcard = wildcard,
|
||||||
exists = exists,
|
exists = exists,
|
||||||
isdir = isdir,
|
isdir = isdir,
|
||||||
mtime = mtime
|
mtime = mtime,
|
||||||
|
normalizepath = normalizepath,
|
||||||
|
parentdir = parentdir,
|
||||||
|
freezecache = freezecache,
|
||||||
|
invalidatecache = invalidatecache,
|
||||||
|
clearcache = clearcache
|
||||||
}
|
}
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -260,7 +398,7 @@ min = function(table, cmp)
|
|||||||
local val = table[1]
|
local val = table[1]
|
||||||
for i = 2, #table do
|
for i = 2, #table do
|
||||||
local elem = table[i]
|
local elem = table[i]
|
||||||
if cmp(val, elem) then
|
if cmp(elem, val) then
|
||||||
val = elem
|
val = elem
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -276,7 +414,7 @@ max = function(table, cmp)
|
|||||||
local val = table[1]
|
local val = table[1]
|
||||||
for i = 2, #table do
|
for i = 2, #table do
|
||||||
local elem = table[i]
|
local elem = table[i]
|
||||||
if not cmp(val, elem) then
|
if not cmp(elem, val) then
|
||||||
val = elem
|
val = elem
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -570,6 +708,11 @@ end
|
|||||||
local trim
|
local trim
|
||||||
trim = require('moonscript.util').trim
|
trim = require('moonscript.util').trim
|
||||||
local util = require('moonbuild.util')
|
local util = require('moonbuild.util')
|
||||||
|
local freezecache, invalidatecache
|
||||||
|
do
|
||||||
|
local _obj_0 = require('moonbuild.fsutil')
|
||||||
|
freezecache, invalidatecache = _obj_0.freezecache, _obj_0.invalidatecache
|
||||||
|
end
|
||||||
local exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs
|
local exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs
|
||||||
exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs = util.exists, util.mtime, util.run, util.min, util.max, util.first, util.flatten, util.match, util.patsubst, util.sortedpairs
|
exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs = util.exists, util.mtime, util.run, util.min, util.max, util.first, util.flatten, util.match, util.patsubst, util.sortedpairs
|
||||||
local insert, concat
|
local insert, concat
|
||||||
@@ -602,7 +745,7 @@ pcall = function(fn, ...)
|
|||||||
rewrite = function(err)
|
rewrite = function(err)
|
||||||
local trace = debug.traceback('', 2)
|
local trace = debug.traceback('', 2)
|
||||||
local trunc = truncate_traceback(trim(trace))
|
local trunc = truncate_traceback(trim(trace))
|
||||||
return rewrite_traceback(trunc, err)
|
return (rewrite_traceback(trunc, err)) or trace
|
||||||
end
|
end
|
||||||
return xpcall(fn, rewrite, ...)
|
return xpcall(fn, rewrite, ...)
|
||||||
end
|
end
|
||||||
@@ -721,6 +864,10 @@ do
|
|||||||
else
|
else
|
||||||
print("Building " .. tostring(name))
|
print("Building " .. tostring(name))
|
||||||
end
|
end
|
||||||
|
for _index_0 = 1, #outs do
|
||||||
|
local file = outs[_index_0]
|
||||||
|
freezecache(file)
|
||||||
|
end
|
||||||
local ok, err = pcall(function()
|
local ok, err = pcall(function()
|
||||||
return self.fn({
|
return self.fn({
|
||||||
ins = ins,
|
ins = ins,
|
||||||
@@ -730,6 +877,10 @@ do
|
|||||||
name = name
|
name = name
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
for _index_0 = 1, #outs do
|
||||||
|
local file = outs[_index_0]
|
||||||
|
invalidatecache(file)
|
||||||
|
end
|
||||||
if not (ok) then
|
if not (ok) then
|
||||||
error("Can't build " .. tostring(self.name) .. ": lua error\n" .. tostring(err))
|
error("Can't build " .. tostring(self.name) .. ": lua error\n" .. tostring(err))
|
||||||
end
|
end
|
||||||
@@ -887,8 +1038,7 @@ end
|
|||||||
if setfenv then
|
if setfenv then
|
||||||
error("Need Lua >=5.2")
|
error("Need Lua >=5.2")
|
||||||
end
|
end
|
||||||
local targets = { }
|
local targets, defaulttarget
|
||||||
local defaulttarget = 'all'
|
|
||||||
local buildscope = {
|
local buildscope = {
|
||||||
default = function(target)
|
default = function(target)
|
||||||
defaulttarget = target.name
|
defaulttarget = target.name
|
||||||
@@ -926,23 +1076,40 @@ setmetatable(buildscope, {
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
local file = first({
|
local loadtargets
|
||||||
|
loadtargets = function()
|
||||||
|
targets = { }
|
||||||
|
defaulttarget = 'all'
|
||||||
|
local file = first({
|
||||||
'Build.moon',
|
'Build.moon',
|
||||||
'Buildfile.moon',
|
'Buildfile.moon',
|
||||||
'Build',
|
'Build',
|
||||||
'Buildfile'
|
'Buildfile'
|
||||||
}, exists)
|
}, exists)
|
||||||
if not (file) then
|
if not (file) then
|
||||||
error("No Build.moon or Buildfile found")
|
error("No Build.moon or Buildfile found")
|
||||||
end
|
end
|
||||||
local buildfn = loadwithscope(file, buildscope)
|
local buildfn = loadwithscope(file, buildscope)
|
||||||
if not (buildfn) then
|
if not (buildfn) then
|
||||||
error("Failed to load build function")
|
error("Failed to load build function")
|
||||||
|
end
|
||||||
|
return buildfn()
|
||||||
end
|
end
|
||||||
local ok, err = pcall(buildfn)
|
local buildtargets
|
||||||
|
buildtargets = function()
|
||||||
|
if #args.targets == 0 then
|
||||||
|
BuildObject:build(defaulttarget)
|
||||||
|
end
|
||||||
|
local _list_0 = args.targets
|
||||||
|
for _index_0 = 1, #_list_0 do
|
||||||
|
local target = _list_0[_index_0]
|
||||||
|
BuildObject:build(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local ok, err = pcall(loadtargets)
|
||||||
if not (ok) then
|
if not (ok) then
|
||||||
if err then
|
if err then
|
||||||
io.stderr:write(err, '\n')
|
io.stderr:write("Error while loading build file: ", err, '\n')
|
||||||
else
|
else
|
||||||
io.stderr:write("Unknown error\n")
|
io.stderr:write("Unknown error\n")
|
||||||
end
|
end
|
||||||
@@ -974,16 +1141,13 @@ if args.deps then
|
|||||||
end
|
end
|
||||||
io.write("\n")
|
io.write("\n")
|
||||||
for name, dep in sortedpairs(deps) do
|
for name, dep in sortedpairs(deps) do
|
||||||
io.write("\t\t" .. tostring(name) .. " (" .. tostring(dep.name) .. ")\n")
|
io.write("\t\t" .. tostring(name))
|
||||||
|
if name ~= dep.name then
|
||||||
|
io.write(" (" .. tostring(dep.name) .. ")")
|
||||||
|
end
|
||||||
|
io.write("\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
os.exit(0)
|
os.exit(0)
|
||||||
end
|
end
|
||||||
if #args.targets == 0 then
|
return buildtargets()
|
||||||
BuildObject:build(defaulttarget)
|
|
||||||
end
|
|
||||||
local _list_0 = args.targets
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local target = _list_0[_index_0]
|
|
||||||
BuildObject:build(target)
|
|
||||||
end
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import attributes, dir from require 'lfs'
|
||||||
|
unpack or= table.unpack
|
||||||
|
|
||||||
|
FROZEN = ->
|
||||||
|
|
||||||
|
makecached = (fn) ->
|
||||||
|
cache = {}
|
||||||
|
|
||||||
|
invalidate = (val) ->
|
||||||
|
cache[val] = nil
|
||||||
|
|
||||||
|
freeze = (val) ->
|
||||||
|
cache[val] = FROZEN
|
||||||
|
|
||||||
|
clear = ->
|
||||||
|
cache = {}
|
||||||
|
|
||||||
|
get = (val) ->
|
||||||
|
cached = cache[val]
|
||||||
|
if cached!=FROZEN and cached!=nil
|
||||||
|
return unpack cached
|
||||||
|
ret = {fn val}
|
||||||
|
if cached!=FROZEN
|
||||||
|
cache[val] = ret
|
||||||
|
unpack ret
|
||||||
|
|
||||||
|
setmetatable { :get, :invalidate, :freeze, :clear },
|
||||||
|
__call: (val) => get val
|
||||||
|
|
||||||
|
{
|
||||||
|
attributes: makecached attributes
|
||||||
|
dir: makecached (file) -> [k for k in dir file]
|
||||||
|
}
|
||||||
+46
-10
@@ -1,25 +1,42 @@
|
|||||||
import dir, attributes from require 'lfs'
|
import dir, attributes from require 'moonbuild.fscache'
|
||||||
|
|
||||||
import gmatch, match, gsub, sub from string
|
import gmatch, match, gsub, sub from string
|
||||||
import insert, concat from table
|
import insert, remove, concat from table
|
||||||
|
|
||||||
|
normalizepath = (file) ->
|
||||||
|
parts = [part for part in gmatch file, '[^/]+']
|
||||||
|
absolute = (sub file, 1, 1)=='/'
|
||||||
|
for i=1, #parts
|
||||||
|
if parts[i]=='.'
|
||||||
|
remove parts, i
|
||||||
|
i -= 1
|
||||||
|
continue
|
||||||
|
if parts[i]=='..' and i!=1
|
||||||
|
remove parts, i
|
||||||
|
remove parts, i-1
|
||||||
|
i -= 2
|
||||||
|
continue
|
||||||
|
if #parts==0
|
||||||
|
'.'
|
||||||
|
else
|
||||||
|
(absolute and '/' or '') .. concat parts, '/'
|
||||||
|
|
||||||
ls = (d) ->
|
ls = (d) ->
|
||||||
[f for f in dir d when f!='.' and f!='..']
|
[f for f in *dir normalizepath d when f!='.' and f!='..']
|
||||||
|
|
||||||
lswithpath = (d) ->
|
lswithpath = (d) ->
|
||||||
if d==''
|
return ls '.' if d==''
|
||||||
return ls '.'
|
[d..'/'..f for f in *dir normalizepath d when f!='.' and f!='..']
|
||||||
[d..'/'..f for f in dir d when f!='.' and f!='..']
|
|
||||||
|
|
||||||
exists = (f) ->
|
exists = (f) ->
|
||||||
(attributes f) != nil
|
(attributes normalizepath f) != nil
|
||||||
|
|
||||||
isdir = (f) ->
|
isdir = (f) ->
|
||||||
a = attributes f
|
a = attributes normalizepath f
|
||||||
a and a.mode == 'directory' or false
|
a and a.mode == 'directory' or false
|
||||||
|
|
||||||
mtime = (f) ->
|
mtime = (f) ->
|
||||||
a = attributes f
|
a = attributes normalizepath f
|
||||||
a and a.modification
|
a and a.modification
|
||||||
|
|
||||||
matchglob = (str, glob) ->
|
matchglob = (str, glob) ->
|
||||||
@@ -40,7 +57,7 @@ wildcard = (glob) ->
|
|||||||
|
|
||||||
for i, part in ipairs parts
|
for i, part in ipairs parts
|
||||||
prevpath = (absolute and '/' or '') .. concat parts, '/', 1, i-1
|
prevpath = (absolute and '/' or '') .. concat parts, '/', 1, i-1
|
||||||
currpath = prevpath .. '/' .. part
|
currpath = (i==1 and '' or (prevpath .. '/')) .. part
|
||||||
|
|
||||||
if match part, '%*%*.*%*%*'
|
if match part, '%*%*.*%*%*'
|
||||||
error "Two '**' in the same path component in a wildcard"
|
error "Two '**' in the same path component in a wildcard"
|
||||||
@@ -81,8 +98,27 @@ wildcard = (glob) ->
|
|||||||
else
|
else
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
parentdir = (file) ->
|
||||||
|
normalizepath file..'/..'
|
||||||
|
|
||||||
|
freezecache = (file) ->
|
||||||
|
dir.freeze file
|
||||||
|
dir.freeze parentdir file
|
||||||
|
attributes.invalidate file
|
||||||
|
|
||||||
|
invalidatecache = (file) ->
|
||||||
|
dir.invalidate file
|
||||||
|
dir.invalidate parentdir file
|
||||||
|
attributes.invalidate file
|
||||||
|
|
||||||
|
clearcache = ->
|
||||||
|
dir.clear!
|
||||||
|
attributes.clear!
|
||||||
|
|
||||||
{
|
{
|
||||||
:wildcard
|
:wildcard
|
||||||
:exists, :isdir
|
:exists, :isdir
|
||||||
:mtime
|
:mtime
|
||||||
|
:normalizepath, :parentdir
|
||||||
|
:freezecache, :invalidatecache, :clearcache
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ min = (table, cmp=(a, b) -> a<b) ->
|
|||||||
val = table[1]
|
val = table[1]
|
||||||
for i=2, #table
|
for i=2, #table
|
||||||
elem = table[i]
|
elem = table[i]
|
||||||
if cmp val, elem
|
if cmp elem, val
|
||||||
val = elem
|
val = elem
|
||||||
val
|
val
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ max = (table, cmp=(a, b) -> a<b) ->
|
|||||||
val = table[1]
|
val = table[1]
|
||||||
for i=2, #table
|
for i=2, #table
|
||||||
elem = table[i]
|
elem = table[i]
|
||||||
if not cmp val, elem
|
if not cmp elem, val
|
||||||
val = elem
|
val = elem
|
||||||
val
|
val
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
build = {
|
||||||
|
install = {
|
||||||
|
bin = {
|
||||||
|
moonbuild = "moonbuild.lua"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type = "builtin"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.3",
|
||||||
|
"luafilesystem >= 1.7.0"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
detailed = "moonbuild is a small build system that simplifies your build definitions by allowing you to use declarative as well as imperative rules. It represents the build as a DAG with explicit ordering, and doesn't give you any default confusing rules (unlike make)\n",
|
||||||
|
summary = "Small build system in between make and a build.sh"
|
||||||
|
}
|
||||||
|
package = "moonbuild"
|
||||||
|
rockspec_format = "3.0"
|
||||||
|
source = {
|
||||||
|
tag = "v1.0.3",
|
||||||
|
url = "git://github.com/natnat-mc/moonbuild"
|
||||||
|
}
|
||||||
|
version = "1.0.3-1"
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
build = {
|
||||||
|
install = {
|
||||||
|
bin = {
|
||||||
|
moonbuild = "moonbuild.lua"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type = "builtin"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.3",
|
||||||
|
"luafilesystem >= 1.7.0"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
detailed = "moonbuild is a small build system that simplifies your build definitions by allowing you to use declarative as well as imperative rules. It represents the build as a DAG with explicit ordering, and doesn't give you any default confusing rules (unlike make)\n",
|
||||||
|
summary = "Small build system in between make and a build.sh"
|
||||||
|
}
|
||||||
|
package = "moonbuild"
|
||||||
|
rockspec_format = "3.0"
|
||||||
|
source = {
|
||||||
|
tag = "v1.0.3",
|
||||||
|
url = "git://github.com/natnat-mc/moonbuild"
|
||||||
|
}
|
||||||
|
version = "1.0.3-2"
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
build = {
|
||||||
|
install = {
|
||||||
|
bin = {
|
||||||
|
moonbuild = "moonbuild.lua"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type = "builtin"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.3",
|
||||||
|
"luafilesystem >= 1.7.0"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
detailed = "moonbuild is a small build system that simplifies your build definitions by allowing you to use declarative as well as imperative rules. It represents the build as a DAG with explicit ordering, and doesn't give you any default confusing rules (unlike make)\n",
|
||||||
|
summary = "Small build system in between make and a build.sh"
|
||||||
|
}
|
||||||
|
package = "moonbuild"
|
||||||
|
rockspec_format = "3.0"
|
||||||
|
source = {
|
||||||
|
tag = "v1.0.3",
|
||||||
|
url = "git://github.com/natnat-mc/moonbuild"
|
||||||
|
}
|
||||||
|
version = "1.0.3-3"
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
build = {
|
||||||
|
install = {
|
||||||
|
bin = {
|
||||||
|
moonbuild = "moonbuild.lua"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type = "builtin"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.3",
|
||||||
|
"luafilesystem >= 1.7.0"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
detailed = "moonbuild is a small build system that simplifies your build definitions by allowing you to use declarative as well as imperative rules. It represents the build as a DAG with explicit ordering, and doesn't give you any default confusing rules (unlike make)\n",
|
||||||
|
summary = "Small build system in between make and a build.sh"
|
||||||
|
}
|
||||||
|
package = "moonbuild"
|
||||||
|
rockspec_format = "3.0"
|
||||||
|
source = {
|
||||||
|
tag = "v1.1.0",
|
||||||
|
url = "git://github.com/natnat-mc/moonbuild"
|
||||||
|
}
|
||||||
|
version = "1.1.0-1"
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
build = {
|
||||||
|
install = {
|
||||||
|
bin = {
|
||||||
|
moonbuild = "moonbuild.lua"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type = "builtin"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.3",
|
||||||
|
"luafilesystem >= 1.7.0"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
detailed = "moonbuild is a small build system that simplifies your build definitions by allowing you to use declarative as well as imperative rules. It represents the build as a DAG with explicit ordering, and doesn't give you any default confusing rules (unlike make)\n",
|
||||||
|
summary = "Small build system in between make and a build.sh"
|
||||||
|
}
|
||||||
|
package = "moonbuild"
|
||||||
|
rockspec_format = "3.0"
|
||||||
|
source = {
|
||||||
|
tag = "v1.1.1",
|
||||||
|
url = "git://github.com/natnat-mc/moonbuild"
|
||||||
|
}
|
||||||
|
version = "1.1.1-1"
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
build = {
|
||||||
|
install = {
|
||||||
|
bin = {
|
||||||
|
moonbuild = "moonbuild.lua"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type = "builtin"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.3",
|
||||||
|
"luafilesystem >= 1.7.0"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
detailed = "moonbuild is a small build system that simplifies your build definitions by allowing you to use declarative as well as imperative rules. It represents the build as a DAG with explicit ordering, and doesn't give you any default confusing rules (unlike make)\n",
|
||||||
|
summary = "Small build system in between make and a build.sh"
|
||||||
|
}
|
||||||
|
package = "moonbuild"
|
||||||
|
rockspec_format = "3.0"
|
||||||
|
source = {
|
||||||
|
tag = "v1.1.2",
|
||||||
|
url = "git://github.com/natnat-mc/moonbuild"
|
||||||
|
}
|
||||||
|
version = "1.1.2-1"
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
build = {
|
||||||
|
install = {
|
||||||
|
bin = {
|
||||||
|
moonbuild = "moonbuild.lua"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type = "builtin"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.3",
|
||||||
|
"luafilesystem >= 1.7.0"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
detailed = "moonbuild is a small build system that simplifies your build definitions by allowing you to use declarative as well as imperative rules. It represents the build as a DAG with explicit ordering, and doesn't give you any default confusing rules (unlike make)\n",
|
||||||
|
summary = "Small build system in between make and a build.sh"
|
||||||
|
}
|
||||||
|
package = "moonbuild"
|
||||||
|
rockspec_format = "3.0"
|
||||||
|
source = {
|
||||||
|
tag = "v1.1.3",
|
||||||
|
url = "git://github.com/natnat-mc/moonbuild"
|
||||||
|
}
|
||||||
|
version = "1.1.3-1"
|
||||||
Reference in New Issue
Block a user