require("Utils.utils") ------------------------------------------------------- -- globals ------------------------------------------------------- _G["projectsprocessor"] = {} _G["projectsblocked"] = {} _G["projectsemitted"] = {} _G["namespacesemitted"] = {} _G["usingClang"] = false _G["usingMSVC"] = false ------------------------------------------------------- -- process command line arguments into global space ------------------------------------------------------- require("Boilerplate.options") ------------------------------------------------------- -- debug stuff ------------------------------------------------------- function printHeader(key, val) print("-------------------------------------------------------") print(key, val) print("-------------------------------------------------------") end function dbgGroup(name) printHeader("group", name); group(name) end ------------------------------------------------------- -- API ------------------------------------------------------- local jsonProcessor = require("Boilerplate.jsonProcessor") local normalizeSourceRoot = function(path) local backup = path path = os.realpath(_G.path.join(os.getcwd(), path)); if (not path) then print("path error, not found?", backup) return end return path end local extendInfo = function(this) local type = this.projectType:lower() this.isShared = type == "sharedlib" this.isStatic = type == "staticlib" this.isExec = type == "consoleapp" or type == 'windowedapp' this.isConsole = type == "consoleapp" this.isWindowed = type == "windowedapp" end local requireAbs = function(path) local absRefPath = os.realpath(getroot() .. "/Build_Scripts/") local relPath = _G.path.getrelative(absRefPath, path) if (os.isfile(relPath)) then fatal("Script not found: ", relPath) end return require(relPath:sub(1, #relPath - 4)) end function addVisit(ina) local args = { namespace = ina.namespace, name = ina.name, -- OPT: recommended path = ina.path, type = ina.type, out = ina.out, translations = ina.translations -- OPT: dictionary of dependency maps } local path = normalizeSourceRoot(args.path) if (not path) then return end local info = { namespace = args.namespace, path = path, projectType = args.type, out = args.out, name = args.name, translations = args.translations } extendInfo(info) local project = { info = info, processor = nil } local cwd = getroot() local remoteLua = path .. "/Aurora.lua" local remoteJson = path .. "/Aurora.json" local localJson = cwd .. "/Build_UserScripts/" .. args.name .. ".aurora.json" local localLua = cwd .. "/Build_UserScripts/" .. args.name .. ".aurora.lua" if (os.isfile(localLua)) then project.processor = requireAbs(localLua)(info) elseif (os.isfile(localJson)) then info.jpath = localJson project.processor = jsonProcessor(info) elseif (os.isfile(remoteLua)) then project.processor = requireAbs(remoteLua)(info) elseif (os.isfile(remoteJson)) then info.jpath = remoteJson project.processor = jsonProcessor(info) else print("Couldnt find Aurora build script for: ", path) return end projectsprocessor[info.name] = project end function addScript(ina) local args = { namespace = ina.namespace, script = ina.script, path = ina.path, type = ina.type, out = ina.out } local path = normalizeSourceRoot(args.path) if (not path) then return end local info = { namespace = args.namespace, path = path, projectType = args.type, out = args.out } extendInfo(info) local project = { info = info, processor = nil } local procesor = userRequire(args.script) if (not procesor) then print("missing project script:", args.script, path) return end project.processor = procesor(info) if (not project.processor) then print("script error") return end projectsprocessor[info.name] = project end -- private local processLocalProject = function(proj) processProject(proj.info.name) end local processNS = function(namespace) local projs = {} local projsIdxs = {} forEach(projectsprocessor, function(proj) if (proj.info.namespace ~= namespace) then return end local name = proj.info.name projs[name] = proj table.insert(projsIdxs, name) end) table.sort(projsIdxs, function(a, b) return a:upper() < b:upper() end) forEach(projsIdxs, function(idx) processLocalProject(projs[idx]) end) end function processSolution() local hack = {} local hackIdx = {} forEach(projectsprocessor, function(proj) table.insert(hackIdx, proj.info.namespace) end) table.sort(hackIdx, function(a, b) return a:upper() < b:upper() end) forEach(hackIdx, processNS) end function attemptNS(ns) local attemptLoad = false if (not namespacesemitted[ns]) then dbgGroup(ns) -- only print the group once attemptLoad = true end -- this seems to be singleshot. -- once you switch namespaces, theres no going back, it seems. -- we try to preserve namespace-project contiguity as much as possible through sorting and evil recursion namespace(ns) return attemptLoad end resolved = {} function processProject(name, required, noNs) local a = projectsprocessor[name] if (not a) then if (required) then fatal("missing project: ", name) else return false end end if (not a.isParsed) then if (a.processor.parse) then a.processor:parse() end a.isParsed = true end resolved[name] = name if (not a.resolvedDeps) then if (a.processor.resolveDependencies) then a.processor:resolveDependencies(function(name, soft) if (resolved[name]) then return end processProject(name, not soft, noNs) end) end a.resolvedDeps = true end if (projectsblocked[name]) then return true end projectsblocked[name] = name local ns = a.info.namespace local loadOthers = attemptNS(ns) local cwd = os.getcwd() local old = _G["current_project"] _G["current_project"] = name os.chdir(a.info.path) a.processor:process() os.chdir(cwd) _G["current_project"] = old projectsemitted[name] = name if (loadOthers) then namespacesemitted[ns] = ""; processNS(ns) end return true end function isWeakCircularReference(name) return projectsblocked[name] and not projectsemitted[name] end function isProjectLoaded(name) return projectsemitted[name] and true end function getProjectInfo(name) if (not name) then return end local scre = projectsprocessor[name] if (not scre) then return end return scre.info end function getCurrentProjectName() return current_project end -- private local buildAction = require("Actions.buildAction") -- executes inline under iprocessor::process function addBuildAction(...) buildAction(...) end -- executes inline under iprocessor::process function addFeature(feature) local script = os.getcwd() .. "/Build_Scripts/Features/" .. feature:lower() .. ".lua" if (not os.isfile(script)) then return end requireAbs(script)() end require ("Boilerplate.workspace")