|
|
@ -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,10 @@ class BuildObject |
|
|
|
|
|
|
|
|
|
|
|
error "Need Lua >=5.2" if setfenv |
|
|
|
error "Need Lua >=5.2" if setfenv |
|
|
|
|
|
|
|
|
|
|
|
targets={} |
|
|
|
targets = {} |
|
|
|
defaulttarget='all' |
|
|
|
defaulttarget = 'all' |
|
|
|
|
|
|
|
|
|
|
|
buildscope= |
|
|
|
buildscope = |
|
|
|
default: (target) -> |
|
|
|
default: (target) -> |
|
|
|
defaulttarget=target.name |
|
|
|
defaulttarget=target.name |
|
|
|
target |
|
|
|
target |
|
|
@ -139,27 +142,27 @@ 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 |
|
|
|
file = first {'Build.moon', 'Buildfile.moon', 'Build', 'Buildfile'}, exists |
|
|
|
error "No Build.moon or Buildfile found" unless file |
|
|
|
error "No Build.moon or Buildfile found" unless file |
|
|
|
buildfn=loadwithscope file, buildscope |
|
|
|
buildfn = loadwithscope file, buildscope |
|
|
|
error "Failed to load build function" unless buildfn |
|
|
|
error "Failed to load build function" unless buildfn |
|
|
|
ok, err=pcall buildfn |
|
|
|
ok, err = pcall buildfn |
|
|
|
unless ok |
|
|
|
unless ok |
|
|
|
if err |
|
|
|
if err |
|
|
|
io.stderr\write err, '\n' |
|
|
|
io.stderr\write err, '\n' |
|
|
|