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 filterForKey(obj, key, callback, expandArray) if (obj == nil) then return end local function runCallbackFe(value, key, callback, expandArray, isArray) if (expandArray and isArray) then auForEach(value, function(val) filterForKey(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") files(path .. "/**.ipp") end local function auBlockProjectKeyDefines(processor, value) -- Required for dependent and current processor // global library configuration filterForKey(value, "value", defines) end local function auBlockProjectKeyIncludes(processor, value, map, tasks, inc) filterForKey(value, "value", function(value) _includeDirectoryEx(processor:getMeta().path .. "/" .. value, not inc) end, true) end local function auBlockProjectKeyFeatures(processor, value) -- Runs special features / plugins defined in sAbsScripts/features filterForKey(value, "value", auAddFeature, true) end local function auBlockProjectKeyExcludes(processor, value) filterForKey(value, "value", removefiles) end local function auBlockProjectKeySources(processor, value) --files(value) -- NOTE: this was once path .. / .. value filterForKey(value, "value", files) end local function auBlockProjectKeySourcePaths(processor, value) filterForKey(value, "path", function(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, true) end local function auBlockProjectKeyEval(processor, value, map, tasksMask) if (type(object) == "string") then auEval(object) return end filterForKey(value, nil, function(value) __pRunTasks(processor, value, map, tasksMask, true) end) end local function auBlockProjectKeyDefines(processor, value) filterForKey(value, "value", defines) end local function auBlockProjectKeyImplDefines(processor, value) filterForKey(value, "value", defines) end local function auBlockProjectKeyStaticImplDefines(processor, value) if (not processor:getMeta().isStatic) then return end filterForKey(value, "value", defines) end local function auBlockKeyFeature(processor, value) filterForKey(value, "value", auAddFeature, true) end local function auBlockProjectKeyImplIncludes(processor, value) filterForKey(value, "value", _includeDirectoryEx) end local function auBlockProjectKeyClangIgnore(processor, value) auFilter {"toolset:clang"} disablewarnings(value) auFilter {} end local function auBlockProjectKeyMSVCIgnore(processor, value) auFilter {'not toolset:clang'} --auFilter {"toolset:msc"} disablewarnings(value) auFilter {} end local function _auBlockProjectKeyLinks(value, processor) end local function auBlockProjectKeyLinks(processor, value) filterForKey(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) filterForKey(value, nil, function(value) local type = "" if (value.lua) then type = "lua" elseif (value.bin) then type = "bin" elseif (value.project) then type = "project" elseif (value.cmd) then type = "cmd" else return end auAddBuildAction(value.when, type, value[type], value.isCwdProjRoot, value.args) end, processor) end local function handleActionCommon(action, cb, ...) local _if = action["if"] local _then = action["then"] --_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 if (action.eval) then cb(action.eval, ...) end end --_G["info"] = nil end local function auBlockProjectKeyBuildAction(processor, value, map, tasks) filterForKey(value, nil, function(value) handleActionCommon(value, function(thenblock) auBlockProjectKeyEval(processor, thenblock, map, tasks) end) end, processor) end local function handleDepends(processor, dep, soft) dep = processor:translateDep(dep) local macro = ("_auhas_" .. dep):upper():gsub("%-", "_"); if (auGetProjectProcessor(dep)) then defines(macro .. "=1") auLinkAndRefProject(dep, soft) else --defines(macro .. "=0") if (not soft) then auFatal("missing project: ", dep) end end end local function auBlockProjectKeyDepends(processor, value) filterForKey(value, "value", function(obj) handleDepends(processor, obj, false) end, true) end local function auBlockProjectKeyDllimport(processor, value) filterForKey(value, "value", defines, true) end local function auBlockProjectKeyDllexport(processor, value) filterForKey(value, "value", defines, true) end local function auBlockProjectKeyDllexport(processor, value) filterForKey(value, "value", defines, true) end local function auBlockProjectKeyResourceScript(processor, value, map, tasks) filterForKey(value, nil, function(value) auForEachKV(value, function(key, value) if (auIsArray(value)) then auAddResource(value, nil, key) else auAddResource(value.files, value.arguments, key) end end) end, processor) end local function auBlockProjectKeyProtobuf(processor, value, map, tasks, inc, resolve, object) filterForKey(value, "files", function(value) auProtobufFiles(value, {grpc = object.grpc, auRPC = object.auRPC}) end, true) end local function auBlockProjectKeyVala(processor, value) filterForKey(value, nil, function(value) local sources = {} local gir = Aurora.Settings.sValaGirs local vapi = Aurora.Settings.aValaDevVApis local valIncludes = nil local valGirFile = nil local header = nil local name = auGetCurrentProject() if (auIsArray(value)) then sources = value else gir = auConcatArrays(gir, value.girs) vapi = auConcatArrays(vapi, value.vapis) sources = value.sources valIncludes = path.join(processor:getMeta().path, value.include) valGirFile = path.join(processor:getMeta().path, value.gir) header = path.join(processor:getMeta().path, value.header) if (value.name) then name = value.name end end local extended = { sources = sources, gir = gir, vapi = vapi, vapi = vapi, package = valIncludes, header = header, girFile = valGirFile, name = name } auAddVala(extended) end, false) end local function auBlockProjectKeyUnpack(processor, value) filterForKey(value, "files", function(fileName) local referencePath = path.join(Aurora.Settings.sAbsRepoScripts, fileName) local destinationPath = path.join(processor:getMeta().path, fileName) if (not os.isfile(destinationPath)) then os.copyfile(referencePath, destinationPath) end end, true) end local function auBlockProjectKeyM4(processor, value) processor.m4_files = processor.m4_files or {} filterForKey(value, nil, function(obj) for fk, fv in pairs(obj) do local fileTbl = processor.m4_files[fk] or {} processor.m4_files[fk] = fileTbl for k, v in pairs(fv) do fileTbl[k] = v end end end, true) end local function auBlockProjectKeySoftDepends(processor, value) filterForKey(value, "value", function(obj) handleDepends(processor, obj, true) end, true) end local function auBlockProjectRefKeyInclSoftDepends(processor, value, taskMap, taskArray, inc, resolve) filterForKey(value, "value", function(obj) resolve(processor:translateDep(obj), false) end, true) end local function auBlockProjectRefKeyInclDepends(processor, value, taskMap, taskArray, inc, resolve) filterForKey(value, "value", function(obj) resolve(processor:translateDep(obj), false) end, true) end local function auBlockProjectRefKeyDepends(processor, value, taskMap, taskArray, inc, resolve) filterForKey(value, "value", function(obj) resolve(processor:translateDep(obj), false) end, true) end local function auBlockProjectRefKeyProtobuf(processor, value, taskMap, taskArray, inc, resolve) auProtobufIncludeProject(processor:getMeta().name) end local function auBlockProjectRefKeySoftDepends(processor, value, taskMap, taskArray, inc, resolve) filterForKey(value, "value", function(obj) resolve(processor:translateDep(obj), true) end, true) 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 function auBlockProjectKeyBigObject(processor, value) filterForKey(value, nil, function(obj) auFilter{"not toolset:clang"} buildoptions "/bigobj" auFilter{} end) end local function auBlockProjectKeyRtti(processor, value) if (value) then rtti "On" else rtti "Off" end end local auProjectHeaderHandlers = { linkDepends = auHeaderProjectKeyLinkDepends, includeDepends = auHeaderProjectKeyIncludeDepends } local kAllProjectHeaders = { "linkDepends", "includeDepends" } local function auBlockProjectKeyLtoNotMsvc(processor, value) if (value) then auFilter{"toolset:clang", "not system:windows"} --buildoptions "-flto=thin" --linkoptions "-Wl,-mllvm,-threads=4" buildoptions "-flto" linkoptions "-flto" auFilter{} end end local function auBlockProjectKeyLtoMsvc(processor, value) if (value) then auFilter{"toolset:msc"} --linkoptions "/LTCG" flags { "LinkTimeOptimization" } flags { "NoIncrementalLink" } buildoptions "/GL" auFilter{} end end local function auBlockProjectKeyLtoClang(processor, value) auBlockProjectKeyLtoNotMsvc(processor, value) end local function auBlockProjectKeyLtoNotClang(processor, value) auBlockProjectKeyLtoMsvc(processor, value) end local function auBlockProjectKeyLto(processor, value) auBlockProjectKeyLtoMsvc(processor, value) auBlockProjectKeyLtoNotMsvc(processor, value) end 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, resourceScript = auBlockProjectKeyResourceScript, protobuf = auBlockProjectKeyProtobuf, vala = auBlockProjectKeyVala, unpack = auBlockProjectKeyUnpack, m4 = auBlockProjectKeyM4, bigObject = auBlockProjectKeyBigObject, rtti = auBlockProjectKeyRtti, lto = auBlockProjectKeyLto, ltoNotMsvc = auBlockProjectKeyLtoNotMsvc, ltoNotClang = auBlockProjectKeyLtoNotClang, ltoMsvc = auBlockProjectKeyLtoMsvc, ltoClang = auBlockProjectKeyLtoClang } auProjectBlockHandlers["soft-depends"] = auBlockProjectKeySoftDepends local auProjectRefHandlers = { linkDepends = auHeaderProjectKeyLinkDepends, eval = auBlockProjectKeyEval, actions = auBlockProjectKeyBuildAction, links = auBlockProjectKeyLinks, defines = auBlockProjectKeyDefines, include = auBlockProjectKeyIncludes, includes = auBlockProjectKeyIncludes, dllimport = auBlockProjectKeyDllimport, dllexport = auBlockProjectKeyDllimport, staticImport = auBlockProjectKeyDllimport, staticImpDefines = auBlockProjectKeyDllimport } auProjectRefHandlers["soft-depends"] = auBlockProjectRefKeySoftDepends auProjectRefHandlers["include-soft-depends"] = auBlockProjectRefKeyInclSoftDepends auProjectRefHandlers["include-depends"] = auBlockProjectRefKeyInclDepends auProjectRefHandlers["depends"] = auBlockProjectRefKeyDepends auProjectRefHandlers["protobuf"] = auBlockProjectRefKeyProtobuf kGenericTasks = { "sourcePaths", "includes","include", "sources", "clangIgnore", "impDefines", "implDefines", "implementationDefines", "impInclude", "implInclude", "impIncludes", "implIncludes", "msvcIgnore", "excludes", "depends", "require", "m4", "vala", "eval", "lua", "events", "actions", "staticImpDefines", "features", "links", "soft-depends", "resourceScript", "protobuf", "unpack", "bigObject", "rtti", "lto", "ltoNotMsvc", "ltoNotClang", "ltoMsvc", "ltoClang" } local kReferenceTasks = {"eval", "includes", "defines", "include", "includes", "protobuf", "actions"} --, "features"} -- , "include-depends", "include-soft-depends" __pRunTasks = function(processor, object, map, tasks, inc, resolve) auForEachKV(tasks, function(na, key) local value = object[key] if (value == nil) then return end map[key](processor, value, map, tasks, inc, resolve, object) end) end local function postRunMain(processor) -- TODO: m4 end local function __pRunLinkTasks(processor, object, resolve) __pRunTasks(processor, object, auProjectRefHandlers, { "links", "depends", "soft-depends", "eval", "linkDepends", "actions" }, false, resolve) end local function __pRunOtherLang(processor, object, resolve) __pRunTasks(processor, object, auProjectRefHandlers, { "depends", "soft-depends", "eval", "actions" }, false, resolve) end local function __pRunIncludeTasks(processor, object, isIncludeLocalProject) __pRunTasks(processor, object, auProjectRefHandlers, 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, resolve) __pRunIncludeTasks(processor, object, false) if (not object.noRootInclude) then _includeDirectoryEx(processor:getMeta().path, false) end end local function ___pRunImportTask(processor, object, mask, resolve) __pRunIncludeTasks(processor, object, false) __pRunTasks(processor, object, auProjectRefHandlers, mask, false, resolve) if (not object.noRootInclude) then _includeDirectoryEx(processor:getMeta().path, false) 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 postRunMain(processor) end return auCopyTables(auProjectHeaderHandlers, auProjectBlockHandlers, { runProjectBlock = __pRunMainTasks, runProjectLink = __pRunLinkTasks, runProjectImport = ___pRunImportTask, runProjectRef = ___pRunIncludeTasks, runOtherLang = __pRunOtherLang })