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, deps = {} } 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, deps = {} } local procesor = userRequire(args.script) if (not procesor) then processor = requireAbs(args.script) if (not procesor) then print("missing project script:", args.script, path) return end 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 -- private local processInit = function(project) if (not project.isInitialized) then if (project.processor.init) then project.processor:init() end project.isInitialized = true end end -- private _G["_resolved_dep_res"] = {} _G["_resolved_dep"] = {} function processDepSearch(proj, resolveProject) local name = proj.info.name _G["_resolved_dep"][name] = name if (not proj.resolvedDeps) then if (proj.processor.resolveDependencies) then proj.processor:resolveDependencies(function(name, soft) table.insert(proj.deps, name) if (_G["_resolved_dep"][name]) then return end local depProj = projectsprocessor[name] if (not depProj) then if (not soft) then fatal("missing dependency: ", name) else return false end end processDepSearch(depProj, true) end) end proj.resolvedDeps = true end processInit(proj) end -- private 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) processDepSearch(projs[idx], true) 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 processInit(a) 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(depName) local curName = getCurrentProjectName() local cur = projectsprocessor[curName] if (not cur) then return end local dep = projectsprocessor[depName] if (not dep) then return end -- TODO: recursion for index, value in ipairs(dep.deps) do if value == curName then return true end end return false end function isProjectLoaded(name) local a = projectsprocessor[name] if (not a) then return false end return a.isInitialized 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 = getroot() .. "/Build_Scripts/Features/" .. feature:lower() .. ".lua" if (not os.isfile(script)) then fatal("missing feature", feature, script) return end requireAbs(script)() end require ("Boilerplate.workspace")