diff --git a/moonbuild.moon b/moonbuild.moon index 6cd0452..ccc4160 100755 --- a/moonbuild.moon +++ b/moonbuild.moon @@ -8,7 +8,7 @@ import truncate_traceback, rewrite_traceback from require 'moonscript.errors' import trim from require 'moonscript.util' util=require 'util' -import exists, mtime, run, min, max, first, flatten, match, patsubst from util +import exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs from util import insert, concat from table @@ -16,12 +16,15 @@ 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" args=parser\parse! -- util functions loadwithscope= (file, scope) -> - fn=loadfile file - dumped=string.dump fn + fn, err=loadfile file + error err or "failed to load code" unless fn + dumped, err=string.dump fn + error err or "failed to dump function" unless dumped load dumped, file, 'b', scope pcall= (fn, ...) -> rewrite=(err) -> @@ -48,7 +51,6 @@ class Command class BuildObject all={} skip={} - cycle={} @find: (name) => target=all[name] @@ -57,9 +59,11 @@ class BuildObject return tgt if match name, glob nil + @list: => + {target, {dep, @find dep for dep in *target.deps} for name, target in pairs all} @build: (name) => - target=@find name or error "No such target: #{name}" + target=(@find name) or error "No such target: #{name}" target\build name __tostring: => @@ -72,8 +76,6 @@ class BuildObject build: (name) => return if skip[name] - error "Can't build #{name}: cyclic depenancies found" if cycle[name] - cycle[name]=true if @name!=name @@build patsubst name, @name, dep for dep in *@deps else @@ -153,6 +155,7 @@ setmetatable buildscope, file=first {'Build.moon', 'Buildfile.moon', 'Build', 'Buildfile'}, exists error "No Build.moon or Buildfile found" unless file buildfn=loadwithscope file, buildscope +error "Failed to load build function" unless buildfn ok, err=pcall buildfn unless ok if err @@ -166,6 +169,25 @@ if args.list io.write "\t#{concat targets, ', '}\n" os.exit 0 +if args.deps + io.write "Targets:\n" + for target, deps in sortedpairs BuildObject\list!, (a, b) -> a.name #{concat target.outs, ', '})" + io.write "\n" + for name, dep in sortedpairs deps + io.write "\t\t#{name} (#{dep.name})\n" + os.exit 0 + if #args.targets==0 BuildObject\build defaulttarget for target in *args.targets diff --git a/util.moon b/util.moon index f2445b5..863adf9 100644 --- a/util.moon +++ b/util.moon @@ -1,6 +1,6 @@ import attributes, dir from require 'lfs' -import insert, concat from table +import insert, concat, sort from table unpack or=table.unpack GLOB_PATT='^([^%%]*)%%([^%%]*)$' @@ -65,7 +65,8 @@ escapecmdpart= (p) -> '"'..p\gsub('\\', '\\\\')\gsub('"', '\\"')..'"' escapecmd= (c, args={}) -> c=escapecmdpart c - c..=' '..escapecmdpart a for a in *args + for a in *flatten args + c..=' '..escapecmdpart a if a c run= (c, args, params={}) -> escaped=escapecmd c, args @@ -120,6 +121,9 @@ patsubst= (str, pattern, replacement) -> return reprefix..(str\sub #prefix+1, -#suffix-1)..resuffix str +splitsp= (str) -> + [elem for elem in str\gmatch '%S+'] + -- glob match match= (str, glob) -> prefix, suffix=glob\match GLOB_PATT @@ -137,14 +141,22 @@ isglob= (glob) -> env= (key, def) -> (os.getenv key) or def +sortedpairs= (table, cmp) -> + keys = [k for k in pairs table] + sort keys, cmp + coroutine.wrap -> + for key in *keys + coroutine.yield key, table[key] + { -- table functions :min, :max :foreach :first - :insert, :unpack, :concat + :insert, :unpack, :concat, :sort :exclude :flatten + :sortedpairs -- file functions :wildcard @@ -156,4 +168,5 @@ env= (key, def) -> -- string functions :patsubst, :match, :isglob :env + :splitsp }