From 3ed6844a9f02e15fb2e84c0879e58b6c3935b52a Mon Sep 17 00:00:00 2001 From: Nathan DECHER Date: Sun, 13 Sep 2020 16:14:51 +0200 Subject: [PATCH] Producing rockspec 1.0.0-2 --- Alfons.moon | 7 + Build.moon | 20 +- bin/moonbuild.lua | 428 +++++++++++++++++++++++++++ moonbuild.moon => bin/moonbuild.moon | 2 +- fsutil.moon | 88 ------ rock.yml | 26 ++ rockspecs/moonbuild-1.0.0-1.rockspec | 29 ++ rockspecs/moonbuild-1.0.0-2.rockspec | 29 ++ stringutil.moon | 25 -- tableutil.moon | 66 ----- util.moon | 95 ------ 11 files changed, 522 insertions(+), 293 deletions(-) create mode 100644 Alfons.moon create mode 100644 bin/moonbuild.lua rename moonbuild.moon => bin/moonbuild.moon (99%) delete mode 100644 fsutil.moon create mode 100644 rock.yml create mode 100644 rockspecs/moonbuild-1.0.0-1.rockspec create mode 100644 rockspecs/moonbuild-1.0.0-2.rockspec delete mode 100644 stringutil.moon delete mode 100644 tableutil.moon delete mode 100644 util.moon diff --git a/Alfons.moon b/Alfons.moon new file mode 100644 index 0000000..c37d7e3 --- /dev/null +++ b/Alfons.moon @@ -0,0 +1,7 @@ +tasks: + build: => + sh "moon bin/moonbuild.moon compile-lua" + release: => + error "no version provided" unless @v + tasks.build! + sh "rockbuild -m -t #{@v} upload" diff --git a/Build.moon b/Build.moon index 84ab70f..6f2ea55 100644 --- a/Build.moon +++ b/Build.moon @@ -1,30 +1,14 @@ -SOURCES_MOON = wildcard '*.moon' -exclude SOURCES_MOON, 'Build.moon' +SOURCES_MOON = flatten {'bin/moonbuild.moon', wildcard 'moonbuild/**.moon'} OUT_LUA = patsubst SOURCES_MOON, '%.moon', '%.lua' -BINARY = 'moonbuild' -MAIN = "#{BINARY}.moon" -MAIN_LUA = patsubst MAIN, '%.moon', '%.lua' -OUT_C = patsubst MAIN, '%.moon', '%.lua.c' -PREFIX = env 'PREFIX', '/usr/local' -INSTALL_LOC = "#{PREFIX}/bin" - -public target 'install', from: BINARY, out: INSTALL_LOC, fn: => - -install @infile, @outfile public target 'clean', fn: => -rm '-f', OUT_LUA - -rm '-f', OUT_C - -public target 'mrproper', deps: 'clean', fn: => - -rm '-f', BINARY public target 'info', fn: => #echo "Moonscript sources:", SOURCES_MOON #echo "Compiled lua:", OUT_LUA - #echo "Binary:", BINARY -default target BINARY, out: {BINARY, OUT_C}, from: OUT_LUA, fn: => - -luastatic MAIN_LUA, OUT_LUA, (findclib 'lua5.3', 'all') +default target 'compile-lua', from: OUT_LUA target '%.lua', in: '%.moon', out: '%.lua', fn: => -moonc @infile diff --git a/bin/moonbuild.lua b/bin/moonbuild.lua new file mode 100644 index 0000000..1b7446a --- /dev/null +++ b/bin/moonbuild.lua @@ -0,0 +1,428 @@ +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 +} +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 diff --git a/moonbuild.moon b/bin/moonbuild.moon similarity index 99% rename from moonbuild.moon rename to bin/moonbuild.moon index fb2b493..70c68d6 100755 --- a/moonbuild.moon +++ b/bin/moonbuild.moon @@ -7,7 +7,7 @@ import loadfile from require 'moonscript.base' import truncate_traceback, rewrite_traceback from require 'moonscript.errors' import trim from require 'moonscript.util' -util=require 'util' +util=require 'moonbuild.util' import exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs from util import insert, concat from table diff --git a/fsutil.moon b/fsutil.moon deleted file mode 100644 index de42388..0000000 --- a/fsutil.moon +++ /dev/null @@ -1,88 +0,0 @@ -import dir, attributes from require 'lfs' - -import gmatch, match, gsub, sub from string -import insert, concat from table - -ls = (d) -> - [f for f in dir d when f!='.' and f!='..'] - -lswithpath = (d) -> - if d=='' - return ls '.' - [d..'/'..f for f in dir d when f!='.' and f!='..'] - -exists = (f) -> - (attributes f) != nil - -isdir = (f) -> - a = attributes f - a and a.mode == 'directory' or false - -mtime = (f) -> - a = attributes f - a and a.modification - -matchglob = (str, glob) -> - patt = '^'..(gsub (gsub glob, '%*%*', '.*'), '%*', '[^/]*')..'$' - rst = if (type str)=='table' - results, i = {}, 1 - for s in *str - rst = (match s, patt) and s - results[i], i = rst, i+1 if rst - results - else - (match str, patt) and str - rst - -wildcard = (glob) -> - parts = [part for part in gmatch glob, '[^/]+'] - absolute = (sub glob, 1, 1)=='/' - - for i, part in ipairs parts - prevpath = (absolute and '/' or '') .. concat parts, '/', 1, i-1 - currpath = prevpath .. '/' .. part - - if match part, '%*%*.*%*%*' - error "Two '**' in the same path component in a wildcard" - - if match part, '%*%*' - prefix = match currpath, '^(.*)%*%*' - suffix = (match part, '%*%*(.*)$') .. (i==#parts and '' or ('/'..concat parts, '/', i+1, #parts)) - files = lswithpath prevpath - - results = {} - for file in *files - if matchglob file, currpath - if i==#parts - insert results, file - elseif isdir file - for result in *wildcard file .. '/' .. concat parts, '/', i+1, #parts - insert results, result - if (matchglob file, prefix..'**') and isdir file - for result in *wildcard file .. '/**' .. suffix - insert results, result - return results - - if match part, '%*' - files = lswithpath prevpath - - if i==#parts - return matchglob files, glob - - results = {} - for file in *files - if (matchglob file, currpath) and isdir file - for result in *wildcard file .. '/' .. concat parts, '/', i+1, #parts - insert results, result - return results - - if exists glob - return {glob} - else - return {} - -{ - :wildcard - :exists, :isdir - :mtime -} diff --git a/rock.yml b/rock.yml new file mode 100644 index 0000000..e19e0c8 --- /dev/null +++ b/rock.yml @@ -0,0 +1,26 @@ +package: moonbuild +source: + url: git://github.com/natnat-mc/moonbuild +description: + summary: Small build system in between make and a build.sh + 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) +homepage: https://github.com/natnat-mc/moonbuild +dependencies: + - lua >= 5.3 + - luafilesystem >= 1.7.0 +build: + type: builtin + modules: + moonbuild.util: moonbuild/util.lua + moonbuild.fsutil: moonbuild/fsutil.lua + moonbuild.stringutil: moonbuild/stringutil.lua + moonbuild.tableutil: moonbuild/tableutil.lua + install: + bin: + moonbuild: bin/moonbuild.lua diff --git a/rockspecs/moonbuild-1.0.0-1.rockspec b/rockspecs/moonbuild-1.0.0-1.rockspec new file mode 100644 index 0000000..b9c79f3 --- /dev/null +++ b/rockspecs/moonbuild-1.0.0-1.rockspec @@ -0,0 +1,29 @@ +build = { + install = { + bin = { + moonbuild = "bin/moonbuild.lua" + } + }, + modules = { + ["moonbuild.fsutil"] = "moonbuild/fsutil.lua", + ["moonbuild.stringutil"] = "moonbuild/stringutil.lua", + ["moonbuild.tableutil"] = "moonbuild/tableutil.lua", + ["moonbuild.util"] = "moonbuild/util.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.0", + url = "git://github.com/natnat-mc/moonbuild" +} +version = "1.0.0-1" diff --git a/rockspecs/moonbuild-1.0.0-2.rockspec b/rockspecs/moonbuild-1.0.0-2.rockspec new file mode 100644 index 0000000..d3013de --- /dev/null +++ b/rockspecs/moonbuild-1.0.0-2.rockspec @@ -0,0 +1,29 @@ +build = { + install = { + bin = { + moonbuild = "bin/moonbuild.lua" + } + }, + modules = { + ["moonbuild.fsutil"] = "moonbuild/fsutil.lua", + ["moonbuild.stringutil"] = "moonbuild/stringutil.lua", + ["moonbuild.tableutil"] = "moonbuild/tableutil.lua", + ["moonbuild.util"] = "moonbuild/util.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.0", + url = "git://github.com/natnat-mc/moonbuild" +} +version = "1.0.0-2" diff --git a/stringutil.moon b/stringutil.moon deleted file mode 100644 index 91aeab8..0000000 --- a/stringutil.moon +++ /dev/null @@ -1,25 +0,0 @@ -import match, gmatch, sub from string -import upper, lower from string - -GLOB_PATT='^([^%%]*)%%([^%%]*)$' - -patsubst = (str, pattern, replacement) -> - return [patsubst s, pattern, replacement for s in *str] if (type str)=='table' - prefix, suffix = match pattern, GLOB_PATT - return str unless prefix - reprefix, resuffix = match replacement, GLOB_PATT - return replacement unless reprefix - - if (sub str, 1, #prefix)==prefix and (sub str, -#suffix)==suffix - return reprefix..(sub str, #prefix+1, -#suffix-1)..resuffix - str - -splitsp = (str) -> - [elem for elem in gmatch str, '%S+'] - -{ - :patsubst - :splitsp - - :upper, :lower -} diff --git a/tableutil.moon b/tableutil.moon deleted file mode 100644 index 77bcd49..0000000 --- a/tableutil.moon +++ /dev/null @@ -1,66 +0,0 @@ -import insert, remove, concat, sort from table -unpack or= table.unpack - -sortedpairs = (table, cmp) -> - keys = [k for k in pairs table] - sort keys, cmp - coroutine.wrap -> - for key in *keys - coroutine.yield key, table[key] - -min = (table, cmp=(a, b) -> a - val = table[1] - for i=2, #table - elem = table[i] - if cmp val, elem - val = elem - val - -max = (table, cmp=(a, b) -> a - val = table[1] - for i=2, #table - elem = table[i] - if not cmp val, elem - val = elem - val - -foreach = (tab, fn) -> - [fn e for e in *tab] - -first = (tab, fn) -> - for e in *tab - return e if fn e - -exclude = (tab, ...) -> - i=1 - while i<=#tab - removed=false - for j=1, select '#', ... - if tab[i]==select j, ... - remove tab, i - removed = true - break - i += 1 unless removed - tab - -flatten = (tab) -> - return {tab} if (type tab)!='table' - out = {} - for e in *tab - if (type e)=='table' - insert out, v for v in *flatten e - else - insert out, e - out - -{ - :min, :max - :foreach - :first - :exclude - :flatten - :sortedpairs - - :insert, :remove, :concat, :sort - :unpack -} diff --git a/util.moon b/util.moon deleted file mode 100644 index ad709d8..0000000 --- a/util.moon +++ /dev/null @@ -1,95 +0,0 @@ -import wildcard, exists, isdir, mtime from require 'fsutil' -import foreach, first, flatten, exclude, sortedpairs, min, max from require 'tableutil' -import patsubst, splitsp from require 'stringutil' - -import insert, concat, sort, pairs from require 'tableutil' -import upper, lower from require 'stringutil' - -GLOB_PATT='^([^%%]*)%%([^%%]*)$' - --- command functions -escapecmdpart= (p) -> - if (type p)=='table' - return p.raw if p.raw - return concat [escapecmdpart part for part in *p], ' ' - return p if p\match '^[a-zA-Z0-9_./-]+$' - '"'..p\gsub('\\', '\\\\')\gsub('"', '\\"')..'"' -escapecmd= (c, args={}) -> - c=escapecmdpart c - for a in *flatten args - c..=' '..escapecmdpart a if a - c -run= (c, args, params={}) -> - escaped=escapecmd c, args - print escaped if params.print - ret, _, code=os.execute escaped - ret, code=ret==0, ret if (type ret)=='number' - error "#{c} failed with code #{code}" if params.error and not ret - ret, code -popen= (c, args, mode='r', params={}) -> - escaped=escapecmd c, args - print escaped if params.print - io.popen escaped, mode - -calccdeps= (infile, includesys=false) -> - data=(popen 'cc', {includesys and '-M' or '-MM', infile})\read '*a' - rawdeps=data\gsub('\\\n', '')\match ':(.+)' - [dep for dep in rawdeps\gmatch '%S+' when dep!=infile] - -findclib= (name, mode='all') -> - args={name} - insert args, '--cflags' if mode=='all' or mode=='cc' - insert args, '--libs' if mode=='all' or mode=='ld' - [arg for arg in (popen 'pkg-config', args)\read('*a')\gmatch '%S+'] - --- glob match -match= (str, glob) -> - prefix, suffix=glob\match GLOB_PATT - return str==glob unless prefix - return str\sub #prefix+1, -#suffix-1 if (str\sub 1, #prefix)==prefix and (str\sub -#suffix)==suffix - false - --- is a valid glob -isglob= (glob) -> - return if glob\match GLOB_PATT - true - else - false - --- getenv -env= (key, def) -> - (os.getenv key) or def - -{ - -- table function - :min, :max - :foreach - :first - :exclude - :flatten - :sortedpairs - - :insert, :remove, :concat, :sort - :unpack - - -- file functions - :wildcard - :mtime - :exists, :isdir - - -- command functions - :run, :popen - :calccdeps, :findclib - - -- string functions - :patsubst - :splitsp - - :upper, :lower - - -- glob functions - :match, :isglob - - -- env functions - :env -}