local kTargetingCmake = false local kTargetingWindows = os.host() == "windows" local kBugHack = kTargetingCmake or kTargetingWindows local auProjectBlockHandlers = {} local kGenericTasks = {} local __pRunTasks = function(processor, object, map, tasks, inc) end local function __pushFilter(obj, key, callback, expandArray) if (not obj) then return end local function runCallbackFe(value, key, callback, expandArray, isArray) if (expandArray and isArray) then auForEach(value, function(val) __pushFilter(val, key, callback, false) end) else callback(value) end end if (type(obj) == "table") then local value = nil local isArray = false if (auIsArray(obj)) then value = obj isArray = true else if (key) then value = obj[key] else value = obj end if (not value) then return end end if (obj.filter) then auFilter(auFilterOf(obj.filter)) end runCallbackFe(value, key, callback, expandArray, isArray) if (obj.filter) then auFilter {} end else if (expandArray) then -- fast path. we can skip this, if false. the if and statment doesnt optimize away the auIsArray anymore runCallbackFe(obj, key, callback, true, auIsArray(obj)) else callback(obj) end end end local function __handleIncludeCallback(processor, includeProject, callback) if (type(processor) == "table") then auForEachKV(processor, function(processorName, soft) if (type(processorName) == "number") then processorName = soft soft = false end if (type(processorName) ~= "string") then auFatal("what is my processor name?") end callback(processorName, not soft) end) else if (type(processor) ~= "string") then auFatal("what is my processor name? [2]", type(processor)) end callback(processorName, true) end end local function __translate(processor, key) return processor:translateDep(key) end local function _includeDirectoryEx(path, incFiles) includedirs(path) if (not incFiles) then return end files(path .. "/**.h") files(path .. "/**.hpp") files(path .. "/**.inl") end local function auBlockProjectKeyDefines(processor, value) -- Required for dependent and current processor // global library configuration __pushFilter(value, "value", defines) end local function auBlockProjectKeyIncludes(processor, value, tasks, inc) _includeDirectoryEx(processor:getMeta().path .. "/" .. value, not inc) end local function auBlockProjectKeyFeatures(processor, value) -- Runs special features / plugins defined in sAbsScripts/features __pushFilter(value, "value", auAddFeature, true) end local function auBlockProjectKeyExcludes(processor, value) __pushFilter(value, "value", removefiles) end local function auBlockProjectKeySources(processor, value) --files(value) -- NOTE: this was once path .. / .. value __pushFilter(value, "value", files) end local function auBlockProjectKeySourcePaths(processor, value) local source = value local path = processor:getMeta().path files { path .. "/" .. source .. "/**.*pp", path .. "/" .. source .. "/**.inl", path .. "/" .. source .. "/**.c", path .. "/" .. source .. "/**.cc", path .. "/" .. source .. "/**.h", path .. "/" .. source .. "/**.masm" } end local function auBlockProjectKeyEval(processor, value, tasksMask) if (type(object) == "string") then auEval(object) return end __pushFilter(value, nil, function(value) __pRunTasks(processor, value, auProjectBlockHandlers, kGenericTasks, true) end) end local function auBlockProjectKeyDefines(processor, value) __pushFilter(value, "value", defines) end local function auBlockProjectKeyImplDefines(processor, value) __pushFilter(value, "value", defines) end local function auBlockProjectKeyStaticImplDefines(processor, value) if (not processor:getMeta().isStatic) then return end __pushFilter(value, "value", defines) end local function auBlockKeyFeature(processor, value) __pushFilter(value, "value", auAddFeature, true) end local function auBlockProjectKeyImplIncludes(processor, value) __pushFilter(value, "value", _includeDirectoryEx) end local function auBlockProjectKeyClangIgnore(processor, value) if (targetingCmake) then filter {"toolset:clang"} end disablewarnings(value) filter {} end local function auBlockProjectKeyMSVCIgnore(processor, value) if (targetingCmake) then filter {"toolset:msc"} end disablewarnings(value) filter {} end local function _auBlockProjectKeyLinks(value, processor) end local function auBlockProjectKeyLinks(processor, value) print("LINK?", json.encode(value)) __pushFilter(value, "value", function(val) links(__translate(processor, val)) end, true) end local function auHeaderProjectKeyIncludeDepends(processor, includeProject) -- Projects that include __handleIncludeCallback(processor, includeProject, function(processorName, hard) auIncludeProject(__translate(processor, processorName), not hard) end) end local function auHeaderProjectKeyLinkDepends(processor, includeProject) __handleIncludeCallback(processor, includeProject, function(processorName, hard) auLinkProject(__translate(processor, processorName), not hard) end) end local function auBlockProjectKeyBuildEvent(processor, value) __pushFilter(value, nil, function(value) local type = "" if (value.lua) then type = "lua" elseif (value.bin) then type = "bin" else return end auAddBuildAction(obj.when, type, value[type], value.isCwdProjRoot) end, processor) end local function handleActionCommon(action, cb, ...) local _if = action["if"] local _then = action["then"] print("EVAL?") --_G["info"] = info if (_if) then local val = auEval("return " .. _if) if (not val) then return end if (_then) then cb(_then, ...) end else if (not action.eval) then action.eval = action["then"] end print("RUN?", json.encode(action.eval)) if (action.eval) then cb(action.eval, ...) end end --_G["info"] = nil end local function auBlockProjectKeyBuildAction(processor, value, mask) __pushFilter(value, nil, function(value) handleActionCommon(value, function(thenblock) print("eval... ", json.encode(thenblock)) auBlockProjectKeyEval(processor, thenblock, auProjectBlockHandlers) end) end, processor) end local function handleDepends(processor, dep, soft) dep = processor:translateDep(dep) local macro = ("_auhas_" .. dep):upper():gsub("%-", "_"); if (isProjectLoaded(dep)) then defines(macro .. "=1") auLinkAndRefProject(dep, soft) else defines(macro .. "=0") if (not soft) then fatal("missing project: ", dep) end end end local function auBlockProjectKeyDepends(processor, value) __pushFilter(value, "value", function(obj) auForEach(obj, function(re) handleDepends(processor, re, false) end) end, processor) end local function auBlockProjectKeyLua(processor, script) auUserRequire(script) end local function auBlockProjectKeyImplNoRootInclude() -- this is just a stub. -- set me, the "noRootInclude" key to 'true' if you do not want the processor root to be include in the include dir search path end local auProjectHeaderHandlers = { linkDepends = auHeaderProjectKeyLinkDepends, includeDepends = auHeaderProjectKeyIncludeDepends } local kAllProjectHeaders = { "linkDepends", "includeDepends" } auProjectBlockHandlers = { links = auBlockProjectKeyLinks, lua = auBlockProjectKeyLua, sourcePaths = auBlockProjectKeySourcePaths, sources = auBlockProjectKeySources, includes = auBlockProjectKeyIncludes, include = auBlockProjectKeyIncludes, excludes = auBlockProjectKeyExcludes, eval = auBlockProjectKeyEval, defines = auBlockProjectKeyDefines, impDefines = auBlockProjectKeyImplDefines, implDefines = auBlockProjectKeyImplDefines, implementationDefines = auBlockProjectKeyImplDefines, staticImpDefines = auBlockProjectKeyStaticImplDefines, impInclude = auBlockProjectKeyImplIncludes, implInclude = auBlockProjectKeyImplIncludes, impIncludes = auBlockProjectKeyImplIncludes, implIncludes = auBlockProjectKeyImplIncludes, clangIgnore = auBlockProjectKeyClangIgnore, msvcIgnore = auBlockProjectKeyMSVCIgnore, depends = auBlockProjectKeyDepends, require = auBlockProjectKeyRequire, noRootInclude = auBlockProjectKeyImplNoRootInclude, events = auBlockProjectKeyBuildEvent, actions = auBlockProjectKeyBuildAction, features = auBlockKeyFeature } kGenericTasks = {"sourcePaths", "includes","include", "sources", "impDefines", "implDefines", "implementationDefines", "impInclude", "implInclude", "impIncludes", "implIncludes", "clangIgnore", "msvcIgnore", "excludes", "depends", "require", "eval", "lua", "events", "actions", "staticImpDefines", "features", "links" } local kReferenceTasks = {"eval", "includes", "include"} --, "features"} __pRunTasks = function(processor, object, map, tasks, inc) auForEachKV(tasks, function(na, key) local value = object[key] if (not value) then return end map[key](processor, value, tasks, inc) end) end local function __pRunLinkTasks(processor, object) __pRunTasks(processor, object, auProjectBlockHandlers, { "links", "depends"}) end local function __pRunIncludeTasks(processor, object, isIncludeLocalProject) __pRunTasks(processor, object, auProjectBlockHandlers, kReferenceTasks, isIncludeLocalProject) if (object.type:lower() == "aurora") then _includeDirectoryEx(processor:getMeta().path .. "/Include") elseif (object.type:lower() == "lazy_free") then object.noRootInclude = false elseif (object.type:lower() == "root") then _includeDirectoryEx(processor:getMeta().path) end end local function ___pRunIncludeTasks(processor, object, isIncludeLocalProject) __pRunIncludeTasks(processor, object, isIncludeLocalProject) if (not object.noRootInclude) then _includeDirectoryEx(processor:getMeta().path, isIncludeLocalProject) end end local function __pRunMainTasks(processor, object) __pRunIncludeTasks(processor, object, true) __pRunTasks(processor, object, auProjectBlockHandlers, kGenericTasks, true) if (not object.noRootInclude) then _includeDirectoryEx(processor:getMeta().path, isIncludeLocalProject) end end return auCopyTables(auProjectHeaderHandlers, auProjectBlockHandlers, { runProjectBlock = __pRunMainTasks, runProjectLink = __pRunLinkTasks, runProjectRef = ___pRunIncludeTasks })