Initial commit

Publish a collection of boilerplate and an additional json parser.
This meta build chain as-is should replace a lot of the premake5.lua in the AuroraEngine repo
This commit is contained in:
Reece Wilson 2021-05-20 13:56:44 +01:00
parent 41ece037a8
commit 615bcb53b9
19 changed files with 1449 additions and 0 deletions

86
Actions/buildAction.lua Normal file
View File

@ -0,0 +1,86 @@
local getExeFileExt = function()
if os.host() == "windows" then
return ".exe"
end
return ""
end
local testPath = function(cwd, exe, ext)
local path = cwd .. "/" .. exe .. ext
if (not os.isfile(path)) then
return nil
end
return os.realpath(path)
end
local getPremakeExec = function()
local exec = premake_exe;
if (exec) then
return exec
end
if (_PREMAKE_COMMAND) then
premake_exe = _PREMAKE_COMMAND
return premake_exe
end
local cwd = os.getcwd()
local ext = getExeFileExt()
local mods = {"auroramake", "premake5", "premake", "genie"}
for k, v in pairs(mods) do
premake_exe = testPath(cwd, v, ext)
if (premake_exe) then
return premake_exe
end
end
premake_exe = "premake5"
return premake_exe
end
local addBuildCommand = function(when, scriptType, path)
local scriptPath = path
local cwd = getroot()
if (os.host() == "linux") then
command = "cd \"" .. cwd .. "\" && "
elseif (os.host() == "windows") then
command = "call "
end
command = command .. getPremakeExec()
command = command .. " --file=\"" .. os.realpath(cwd .. "/Build_Scripts/Actions/buildActionBootstrap.lua") .. "\""
command = command .. " --actualcwd=\"" .. os.realpath(cwd) .. "\""
command = command .. " --project_name=\"%{prj.name}\""
command = command .. " --project_arch=\"%{cfg.architecture}\""
command = command .. " --project_platform=\"%{cfg.system}\""
local cur = getProjectInfo(getCurrentProjectName())
if (cur and cur.path) then
command = command .. " --project_root=\"" .. cur.path .. "\""
end
command = command .. " --scripts=\"" .. os.realpath(cwd .. "/Build_Scripts") .. "\""
if (when == "post") then
local postBuildSuffix = " --cur_binary=\"" .. os.realpath(_G.hack_outputpath) .. "\""
command = command .. postBuildSuffix
end
if (scriptType == "lua") then
command = command .. " --luascript=\"" .. path .. "\""
elseif (scriptType == "bin") then
command = command .. " --binscript=\"" .. path .. "\""
end
--command = command:gsub("\\","\\\\")
if (when == "post") then
postbuildcommands(command)
elseif (when == "pre") then
prebuildcommands(command)
end
end
return addBuildCommand

View File

@ -0,0 +1,98 @@
require("Utils/utils")
newoption
{
trigger = "binscript",
description = ""
}
newoption
{
trigger = "luascript",
description = ""
}
newoption
{
trigger = "cur_binary",
description = ""
}
newoption
{
trigger = "actualcwd",
description = ""
}
newoption
{
trigger = "project_name",
description = "prj.name"
}
newoption
{
trigger = "project_arch",
description = "cfg.architecture"
}
newoption
{
trigger = "project_platform",
description = "cfg.platform"
}
newoption
{
trigger = "project_root",
description = ""
}
local binScript = _OPTIONS["binscript"]
if (binScript) then
local command = "";
local cwd =_OPTIONS["actualcwd"]
if (cwd) then
command = command .. string.format("cd \"%s\" && ", cwd:gsub("\\","\\\\"))
end
command = command .. binScript
os.exit(os.execute(command))
end
local getRoot = function()
local path = os.realpath(os.getcwd())
if (path:ends("/") or path:ends("\\")) then
path = path:sub(1, #path - 1)
end
if (path:ends("Actions")) then
path = path:sub(1, #path - #"/Actions")
end
if (path:ends("Build_Scripts")) then
path = path:sub(1, #path - #"/Build_Scripts")
end
return path
end
_G["_overloadRoot"] = getRoot()
_G["build"] =
{
platform = _OPTIONS["project_platform"],
architecture = _OPTIONS["project_arch"],
projectName = _OPTIONS["project_name"],
projectRoot = _OPTIONS["project_root"],
root = _overloadRoot
}
local luaScript = _OPTIONS["luascript"]
if (luaScript) then
require(os.realpath(build.root .. "/Build_UserScripts/" .. luaScript))
end
os.exit()

View File

@ -0,0 +1,59 @@
local commonFmt = function(name, type, dir, ex, iswin, buildcfg, realName)
local stringPrefix = "";
if iswin then
stringPrefix = "*\"";
else
stringPrefix = "\"";
end
local targetName = string.format("%s.%s.%%{cfg.system}.%%{cfg.architecture}", realName, buildcfg)
local unixName = string.format("%s.%s.%%{cfg.system}.%%{cfg.architecture}", name, buildcfg)
-- ok, shut up. this was an after thought
-- modules were dynamically loaded in scriptability
targetname(targetName)
local outputPath = string.format("%s/%s%s", dir, unixName, ex)
local uglyBuildPath = string.format("%%{cfg.targetdir}/%s%s", unixName, ex)
-- really dont ask what this was for
_G.hack_outputpath = outputPath;
_G.hack_buildoutpath = uglyBuildPath;
--
local fmt = string.format("{COPY} \"%s\" \"%s%s", uglyBuildPath, outputPath, stringPrefix);
return fmt;
end
local LonixFmt1 = function(name, type, dir, ex)
return string.format("mkdir -p \"%s\"", dir);
end
local postBuildCmdsCopyWindows = function(name, type, cfgHack, dir)
if (type == "SharedLib") then
postbuildcommands({commonFmt(name, type, dir, ".dll", true, cfgHack:lower(), name)})
elseif (
(type == "WindowedApp") or
(type == "ConsoleApp")
) then
postbuildcommands({commonFmt(name, type, dir, ".exe", true, cfgHack:lower(), name)})
end
end
local postBuildCmdsCopyLinux = function(name, type, cfgHack, dir)
if (type == "SharedLib") then
postbuildcommands({LonixFmt1("lib" .. name, type, dir, "")})
postbuildcommands({commonFmt("lib" .. name, type, dir, ".so", false, cfgHack:lower(), name)})
elseif (
(type == "WindowedApp") or
(type == "ConsoleApp")
) then
postbuildcommands({LonixFmt1(name, type, dir, "")})
postbuildcommands({commonFmt(name, type, dir, "", false, cfgHack:lower(), name)})
end
end
local handlers = {};
handlers["target-win32"] = postBuildCmdsCopyWindows;
handlers["target-linux"] = postBuildCmdsCopyLinux;
return require("Utils/lookupCmdArgs")(handlers);

View File

@ -0,0 +1,271 @@
local project = require("project")
function JsonProcessor(info)
local result, err = json.decode(io.readfile(info.path .. "/Aurora.json"))
if (not result) then
print("parse error", info.path, err)
return
end
if (not info.name) then
info.name = result.name
end
local handleUserJsonInclude = function(path)
includedirs(info.path .. "/" .. path)
end
local handleJSONInclude = function(result)
if (not result.include) then
includedirs (info.path)
return
end
forEach(result.include, handleUserJsonInclude)
end
local handleInclude = function(this)
local result = this.result
if (result.type:lower() == "aurora") then
includedirs (info.path .. "/Include")
elseif (result.type:lower() == "lazy_free") then
handleJSONInclude(result)
elseif (result.type:lower() == "root") then
includedirs (info.path)
handleJSONInclude(result)
elseif (result.type:lower() == "pair") then
includedirs (info.srcInclude)
handleJSONInclude(result)
elseif (result.type:lower() == "generic") then
handleJSONInclude(result)
elseif (result.type:lower() == "empty") then
handleJSONInclude(result)
end
end
local handlePostBuild = function(obj)
local type = ""
if ( obj.lua) then
type = "lua"
elseif (obj.bin) then
type = "bin"
else
return
end
addBuildAction(obj.when, type, obj[type])
end
local handleDllImportMaybe = function(this)
if (this.info.isShared) then
defines(this.result.dllimport)
end
end
local handleDllExportMaybe = function(this)
if (this.info.isShared) then
defines(this.result.dllexport)
end
end
local handleLink = function(this)
dependson(this.info.name)
links(this.info.name)
handleDllImportMaybe(this)
end
local handleReference = function(this)
local cur = getProjectInfo(getCurrentProjectName())
if (cur and cur.isShared) then
-- shared libraries are only allowed to import other shared libraries
handleDllImportMaybe(this)
elseif (cur and cur.isStatic) then
-- static libs are allowed to reference dllexports in translation units of the parent shared module
handleDllExportMaybe(this)
end
handleInclude(this)
end
local tryAddDefine = function (aaa)
if (aaa) then
defines(aaa)
end
end
local handleProcess = function (a)
local result = a.result
local name = a.info.name
local path = a.info.path
if (result.type:lower() == "aurora") then
local srcPath = path .. "/Source"
local incPath = path .. "/Include"
project(name, a.info.projectType, {srcPath}, {srcPath, incPath}, a.info.out, path)
elseif (result.type:lower() == "lazy_free") then
project(name, a.info.projectType, {path .. "/*.*"}, {path .. "/"}, a.info.out, path)
elseif (result.type:lower() == "root") then
project(name, a.info.projectType, {path .. "/**.*"}, {path .. "/"}, a.info.out, path)
elseif (result.type:lower() == "pair") then
project(name, a.info.projectType, {path .. "/" .. result.srcSource .. "/**.*"}, {path .. "/" .. result.srcInclude}, a.info.out, path)
elseif (result.type:lower() == "generic") then
project(name, a.info.projectType, nil, nil, a.info.out, path)
elseif (result.type:lower() == "empty") then
project(name, a.info.projectType, nil, nil, a.info.out, path)
else
print "invalid project type"
os.exit()
end
handleJSONInclude(result) -- include project public headers, do not use handleInclude, that could reinclude a header included in `project`
-- that could potentially fuck with #include_next
local handleFeature = function(feature)
addFeature(feature)
end
local translateDep = function(dep)
if (a.info.translations) then
local override = a.info.translations[dep]
if (override) then
dep = override
end
end
return dep
end
local handleRequire = function(dep)
dep = translateDep(dep)
dependson(dep)
end
local handleDepends = function (dep, soft)
dep = translateDep(dep)
local iface = _G["projectsprocessor"][dep]
if (isWeakCircularReference(dep)) then
print("handling circular reference", dep)
iface:handleReference()
return
end
if (not isProjectLoaded(dep)) then
processSubproject(dep)
end
if (isProjectLoaded(dep)) then
defines(("_auhas_" .. dep):upper() .. "=1")
iface:includeHeaders()
iface:handleLink()
else
defines(("_auhas_" .. dep):upper() .. "=0")
if (not soft) then
print("missing project: ", dep)
os.exit()
end
end
end
local handleAction = function(action)
local _if = action["if"]
local _then = action["then"]
_G["info"] = info
local cwd = os.getcwd()
os.chdir(info.path)
if (_if) then
print("DEBUG: IF?? ", _if)
local eval = loadstring("return " .. _if)
if (not eval) then
return
end
if (_then) then
print("DEBUG: EVAL ", _then)
forEach(_then, loadstring)
end
else
if (action.eval) then
print("DEBUG: EVAL ", action.eval)
forEach(action.eval, loadstring)
end
end
os.chdir(cwd)
_G["info"] = nil
end
local handleExcludes = function(excludes, path)
removefiles(path .. "/" .. excludes)
end
local handleSoftDepends = function(dep)
handleDepends(dep, true)
end
function handleSources(source, path)
files(path .. "/" .. source)
end
forEach(result.depends, handleDepends, info.path)
forEach(result.features, handleFeature, info.path)
forEach(result.excludes, handleExcludes, info.path)
forEach(result.sources, handleSources, info.path)
forEach(result["soft-depends"], handleSoftDepends)
forEach(result.require, handleRequire)
if (a.info.projectType:lower() == "sharedlib") then
tryAddDefine(result.dllexport)
end
tryAddDefine(result.impdefines)
defines(result.defines)
forEach(result.actions, handleAction, info.path)
forEach(result.postBuild, handlePostBuild, info.path)
forEach(result.preBuild, handlePreBuild, info.path)
end
forEach(result.subprojs, function(subproj)
local subinfo = {
namespace = info.namespace,
path = info.path .. "/" .. subproj.path,
projectType = subproj.type,
out = info.out,
name = nil,
translations = info.translations
}
addVist(subinfo)
end)
local interface = {}
interface.result = result
interface.info = info
interface.process = handleProcess
interface.includeHeaders = handleInclude
interface.handleLink = handleLink
interface.handleReference = handleReference
return interface
end
return JsonProcessor

83
Boilerplate/options.lua Normal file
View File

@ -0,0 +1,83 @@
newoption
{
trigger = "target-win32",
description = "Specifies Win32 as the host and compile machine"
}
newoption
{
trigger = "target-linux",
description = "Specifies linux as the host and compile machine"
}
newoption
{
trigger = "target-switch",
description = "Specifies NX as the host and build chain"
}
newoption
{
trigger = "target-switch-pc",
description = "Specifies NX-win32 as the host and build chain"
}
newoption
{
trigger = "target-ps5",
description = "Specifies PS5 as the host and build chain"
}
newoption
{
trigger = "target-x86_64",
description = "Use Intel vector optimizations and JIT"
}
newoption
{
trigger = "target-arm",
description = "Use ARM JIT"
}
newoption
{
trigger = "target-wayland",
description = "Compile time support for wayland"
}
newoption
{
trigger = "mm-restricted-platform",
description = "uses vendor supplied libcxx for allocations and assumes no jit unless forced"
}
local tbl =
{
"target-win32",
"target-linux",
"target-switch",
"target-ps5",
"target-ps5",
"target-x86_64",
"target-arm",
"target-wayland"
}
for i, k in pairs(tbl) do
local key = string.sub(k, 8)
_G[key] = false
if (_OPTIONS[k]) then
_G[key] = true
end
end
local userOptions = userRequire("options")
if (not userOptions) then
return
end
for i, k in pairs(userOptions) do
_G[k] = _OPTIONS[k]
end

6
Boilerplate/platform.lua Normal file
View File

@ -0,0 +1,6 @@
local archMap = {};
--archMap["target-x86_32"] = "x86_32" unsupported
archMap["target-x86_64"] = "x86_64"
archMap["target-aarch"] = "ARM64"
--archMap["target-arm"] = "ARM" unsupported
return require("Utils/lookupCmdArgs")(archMap, true)

View File

@ -0,0 +1,16 @@
local triggerPairs = {}
triggerPairs["target-win32"] = "_WIN32_AURORA_PREPROCESSOR"
triggerPairs["target-linux"] = "_LINUX_AURORA_PREPROCESSOR"
triggerPairs["target-switch"] = "_SWITCH_AURORA_PREPROCESSOR"
triggerPairs["target-ps4"] = "_PS4_AURORA_PREPROCESSOR"
triggerPairs["target-ps5"] = "_PS5_AURORA_PREPROCESSOR"
triggerPairs["mm-restricted-platform"] = "_AURORA_MEM_STRICT"
local userPaths = userRequire("preprocessors")
if (userPaths) then
if (userPaths.add) then
userPaths.add(triggerPairs)
end
end
return require("Utils/lookupCmdArgs")(triggerPairs, true);

169
Boilerplate/project.lua Normal file
View File

@ -0,0 +1,169 @@
local defintions = require("preprocessors")
local projectCopyCmds = require("buildPostProcess")
local addDest = function(name, projectType, dest)
if (dest:starts("[BUILD_PATH]")) then
local append = dest:sub(13)
filter "configurations:Debug"
projectCopyCmds(name, projectType, "debug", getroot() .. "/Build_Develop/" .. append)
filter "configurations:Release"
projectCopyCmds(name, projectType, "release", getroot() .. "/Build_Stage/" .. append)
filter "configurations:Ship"
projectCopyCmds(name, projectType, "ship", getroot() .. "/Build_Ship/" .. append)
filter {}
else
filter "configurations:Debug"
projectCopyCmds(name, projectType, "debug", path)
filter "configurations:Release"
projectCopyCmds(name, projectType, "release", path)
filter "configurations:Ship"
projectCopyCmds(name, projectType, "ship", path)
filter {}
end
end
local setBestDebugDir = function(dest)
if (not dest or dest:starts("[BUILD_PATH]")) then
local append = dest and dest:sub(#"[BUILD_PATH]")
if (not append) then append = "" end
filter "configurations:Debug"
debugdir(getroot() .. "/Build_Develop/" .. append)
filter "configurations:Release"
debugdir(getroot() .. "/Build_Stage/" .. append)
filter "configurations:Ship"
debugdir(getroot() .. "/Build_Ship/" .. append)
filter {}
else
local path = getroot() .. dest
debugdir(path)
end
end
local boilerplateProject = function(name, projectType, src, inc, dest, root)
print("project", name)
project(name)
targetname(name)
language("C++")
cppdialect("C++20")
kind(projectType)
if (not _G.win32) then
if ((projectType == "SharedLib") or
(projectType == "StaticLib")) then
pic "On"
end
end
if (_G.win32) then
characterset("MBCS")
staticruntime("Off")
end
objdir(getroot() .. "/Build_CompilerWorkingDirectory/" .. name)
if (root and (root ~= "MAGIC")) then
location(root)
else
if (_G["use-workspace-root"]) then
location("../Build_CompilerWorkingDirectory")
end
end
-- V8 takes minutes to start up on an i9-9900k, QST/VM tests result in highs of ~30MB/s from 900MB/s
-- In place of page NX traps and suspending thread contexts like most debug operations,
-- they perform an expensive check in each functions prologue :vomit:
-- MSVCs implementation is not fit for use.
justmycode "Off"
-- again, ye no, i would actually like usable debug builds
defines
{
"_ITERATOR_DEBUG_LEVEL=0",
}
-- add defintions
defines(defintions)
local includeCommonBoilerplate = getroot() .. "/Include";
if (os.isdir(includeCommonBoilerplate)) then
includedirs(includeCommonBoilerplate)
files(includeCommonBoilerplate .. "/**.h*")
end
-- add includes, if available
if inc ~= nil then
forEach(inc, function(path)
print("", "include", _G.path.normalize(path))
includedirs(path)
files(path .. "/**.h")
files(path .. "/**.hpp")
files(path .. "/**.inl")
end)
end
-- add sources, if available
if src ~= nil then
annoyingfirst = false
forEach(src, function(path, root)
print("", "source", _G.path.normalize(path))
--if (string.sub(path, -2) == ".*") then
if (string.find(path, "*")) then
files {path}
return
end
-- dont question it. supporting legacy code
if (not annoyingfirst) then
if (not root) then
location(path)
end
end
annoyingfirst = true
if ((not root) or (root ~= "MAGIC")) then
includedirs(path)
end
files
{
path .. "/**.*pp",
path .. "/**.inl",
path .. "/**.c",
path .. "/**.cc",
path .. "/**.h",
path .. "/**.masm"
}
end, root)
end
local debugDir = nil
if (type(dest) == "string") then debugDir = dest end
if (type(dest) == "table") then debugDir = dest[1] end
setBestDebugDir(debugDir)
if (dest) then
forEach(dest, function(v)
addDest(name, projectType, v)
end)
end
print()
end
return boilerplateProject

122
Boilerplate/workspace.lua Normal file
View File

@ -0,0 +1,122 @@
local toolPlatforms = {"win32", "linux"}
-------------------------------------------------------
-- build platform
-------------------------------------------------------
local isWin = _G.win32
local isToolChain = false
for k in pairs(toolPlatforms) do
if (_G[toolPlatforms[k]]) then
isToolChain = true
end
end
printHeader("configuration", "platforms")
print("isWin", isWin)
print("isDevelopmentPlatform", isToolChain)
print()
-------------------------------------------------------
-- create workspace
-------------------------------------------------------
local target = require("platform")
workspace "Aurora Project"
configurations { "Debug", "Release", "Ship" }
platforms(target)
architecture(target[1])
location(getroot() .. "/Build_CompilerWorkingDirectory/")
symbols "On"
staticruntime "On"
visibility "Hidden"
editandcontinue "Off"
flags
{
"NoIncrementalLink",
"MultiProcessorCompile"--,
--"NoEditAndContinue"
}
filter "configurations:Debug"
defines { "DEBUG" }
targetdir(getroot() .. "/Build_CompilerWorkingDirectory/Bin/Debug")
debugdir( getroot() .. "/Build_Develop")
filter "configurations:Release or configurations:Ship"
defines { "NDEBUG" }
optimize "Speed"
filter "configurations:Release"
defines {"INTERNAL", "STAGING"}
targetdir(getroot() .. "/Build_CompilerWorkingDirectory/Bin/Release")
debugdir(getroot() .. "/Build_Stage")
filter "configurations:Ship"
defines {"SHIP"}
targetdir(getroot() .. "/Build_CompilerWorkingDirectory/Bin/Ship")
debugdir(getroot() .. "/Build_Ship")
filter {}
if ((not isWin) or (_G.forceClang)) then
usingClang = true
_G.usingClang = true
toolset "clang"
buildoptions {"-fms-extensions"}
filter {"files:**.cpp"} -- TODO: `.. " or files:**.cc"` should be possible
buildoptions {"-stdlib=libc++"}
filter {}
filter {"files:**.cc"}
buildoptions {"-stdlib=libc++"}
filter {}
disablewarnings
{
-- we live life on the edge
"unused-result",
-- warning: unused unused enumeration
"unused-value",
"unknown-warning-option"
}
elseif (isWin) then
usingMSVC = true
disablewarnings "4996" -- The whiny C99 is no longer supported nag, please needlessly use _s and _'d functions
disablewarnings "4251" -- MSVC's hurrdurr abis will break if you dynamically link classes
-- counter: fuck off, we have full control of the build process, and we only link against
-- dynamic c/stl runtimes. which brainlet thought this was a good idea?
-- even microsofts docs doesn't state what is guaranteed to be safe. raii works so who cares
disablewarnings "4244" -- conversion from 'double' to 'float', possible loss of data
-- this warning is extremely important; however, we're making a game engine.
-- pragma warning push, disable and/or static_casts to hint we expect floating point precision
-- loss is extremely annoying and impractical. further, projects including harfbuzz, freetype,
-- and v8 don't seem to care about these warnings either
end
if (_G.linux and usingClang) then
linkoptions {"-nodefaultlibs"}
links "c++abi"
links "c++"
links "c"
links "gcc"
links "gcc_s"
links "m"
end
if (isWin) then
-- yeaaa, no
defines "_CRT_SECURE_NO_WARNINGS"
end

View File

@ -0,0 +1,70 @@
local feature = function()
local readdPattern = function(pattern)
files (getProjectInfo(getCurrentProjectName()).path + "/" + pattern)
end
local readd = function(name)
readdPattern "**/" .. name .. "/**.c"
readdPattern "**/" .. name .. "/**.*pp"
readdPattern "**/" .. name .. "/**.masm"
readdPattern "**/" .. name .. "/**.inl"
readdPattern "**/" .. name .. "/**.h"
readdPattern "**/*." .. name .. ".cc"
readdPattern "**/*." .. name .. ".c"
readdPattern "**/*." .. name .. ".h"
readdPattern "**/*." .. name .. ".*pp"
readdPattern "**/*." .. name .. ".masm"
readdPattern "**/*." .. name .. ".inl"
end
if (_G["target-win32"]) then
if (_G["target-x86_64"]) then
readd "win64"
end
readd "win32"
readd "windows"
end
if (_G["target-linux"]) then
readd "linux"
end
if (_G["target-mac"]) then
readd "macos"
readd "mac"
readd "apple"
end
if (_G["target-ios"]) then
readd "apple"
readd "ios"
end
if (_G["target-x86_64"]) then
readd "x64"
readd "x86_64"
readd "amd64"
end
if (_G["target-x86_32"]) then
readdPattern "**/x86/**"
readdPattern "**/x86/**.c"
readdPattern "**/x86/**.h"
readdPattern "**/x86/**.*pp"
readdPattern "**/x86/**.masm"
readdPattern "**/x86/**.inl"
readdPattern "**/x86/**.cpp"
readdPattern "**/*.x86.*pp"
readd "x86_32"
readd "intel"
end
if (_G["target-arm"]) then
readd "arm"
readd "aarch64"
readd "aarch"
end
end
return feature

View File

@ -0,0 +1,12 @@
local feature = function()
local platforms = {"win32", "linux", "xnu", "mac", "osx", "ios", "x86_64", "x86_32", "aarch", "arm64", "mips", "mips64", "riscv", "intel", "powerpc", "amiga"}
forEach(platforms, function(platform)
if (not _G[platform]) then
excludes("**/" .. platform .. "/**");
end
end)
excludes("**/arm/**"); -- whatever, we might name a file `arm` something, as in the limb, but a directory is far less likely for now
end
return feature

177
JSON Schema.json Normal file
View File

@ -0,0 +1,177 @@
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"type": "object",
"properties":
{
"name": {"type": "string"},
"type":
{
"type": "string",
"enum": ["pair", "empty", "root", "lazy_free"],
"description": "https://pastebin.com/ThE2t9EJ"
},
"srcSource":
{
"type": "string",
"description": "use with type == pair"
},
"srcInclude":
{
"type": "string",
"description": "use with type == pair"
},
"include":
{
"type": ["array", "string"],
"description": "path + suffix/include, is added to the includedirs after internal source includes. included by public and internal (obviously) translation units. (when internal available, internal -> include_next -> public) "
},
"dllexport":
{
"type": ["array", "string"],
"items":
{
"type": "string"
},
"description": "adds a preprocessor definition to translation units compling a shared project"
},
"dllimport":
{
"type": ["array", "string"],
"items":
{
"type": "string"
},
"description": "adds a preprocessor definition to translation units linking against a shared project"
},
"impdefines":
{
"type": ["array", "string"],
"items":
{
"type": "string"
},
"description": "adds a preprocessor definition to translation units compiling the project"
},
"defines":
{
"type": ["array", "string"],
"items":
{
"type": "string"
},
"description": "adds preprocessor definition, supports '=value' "
},
"require":
{
"type": ["array", "string"],
"items":
{
"type": "string"
},
"description": "depend on another project. this can be used to fence build stages and integrate other native build+execaction ahead of module compilation time"
},
"soft-depends":
{
"type": ["array", "string"],
"items":
{
"type": "string"
}
},
"depends":
{
"type": ["array", "string"],
"items":
{
"type": "string"
}
},
"excludes":
{
"type": ["array", "string"],
"items":
{
"type": "string"
},
"description": "removes files matching regex('projectDir/${exclude}') "
},
"features":
{
"type": ["array", "string"],
"items":
{
"type": "string",
"enum": ["remove-platform-code", "guess-platform-code"]
},
"description": "remove-platform-code -> excludes paths which appear to be tied to common hardware and software architectures (win32,mac,xnu,nt,intel,amiga,x86_64,mips,arm,powerpc,riscv,etc)"
},
"actions":
{
"type": "array",
"items":
{
"type": "object",
"properties":
{
"if": {"type": "string"},
"then": {"type": "string"},
"eval": {"type": "string"}
}
}
},
"postBuild":
{
"type": "array",
"items":
{
"type": "object",
"properties":
{
"when":
{
"type": "string",
"enum": ["pre", "post"]
},
"lua":
{
"type": "string",
"description": "executes lua script under Build_UserScripts/%s.lua"
},
"bin":
{
"type": "string",
"description": "shell script"
}
}
}
},
"preBuild":
{
"type": "array",
"items":
{
"type": "object",
"properties":
{
"when":
{
"type": "string",
"enum": ["pre", "post"]
},
"lua":
{
"type": "string",
"description": "executes lua script under Build_UserScripts/%s.lua"
},
"bin":
{
"type": "string",
"description": "shell script"
}
}
}
}
},
"required": ["name", "type"]
}

12
Utils/forEach.lua Normal file
View File

@ -0,0 +1,12 @@
function forEach(xd, cb, ...)
if (not xd) then
return
end
if type(xd) == "table" then
for k, v in pairs(xd) do
cb(v, ...)
end
else
cb(xd)
end
end

8
Utils/getRoot.lua Normal file
View File

@ -0,0 +1,8 @@
local root = os.realpath(os.getcwd() .. "/../..")
function getroot()
if (_overloadRoot) then
return _overloadRoot
end
return root
end

21
Utils/lookupCmdArgs.lua Normal file
View File

@ -0,0 +1,21 @@
function lookupArgPair(map, array)
local ret = true
if (array) then
ret = {}
end
for k, v in pairs(map) do
if (_OPTIONS[k] ~= nil) then
if (not array) then
return v
end
table.insert(ret, v)
end
end
return ret
end
return lookupArgPair

7
Utils/strings.lua Normal file
View File

@ -0,0 +1,7 @@
function string.starts(input, suffix)
return suffix == "" or string.sub(input, 1, string.len(suffix)) == suffix
end
function string.ends(input, ending)
return ending == "" or input:sub(-#ending) == ending
end

9
Utils/userRequire.lua Normal file
View File

@ -0,0 +1,9 @@
function userRequire(path)
local script = getroot() .. "/Build_UserScripts/" .. path
if (not os.isfile(script)) then
return
end
return require(script)
end

5
Utils/utils.lua Normal file
View File

@ -0,0 +1,5 @@
require("getRoot")
require("forEach")
require("strings")
require("userRequire")
require("lookupCmdArgs")

218
aurora.lua Normal file
View File

@ -0,0 +1,218 @@
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
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
}
if (os.isfile(path .. "/Aurora.lua")) then
project.processor = require(path .. "/Aurora.lua")(info)
elseif (os.isfile(path .. "/Aurora.json")) then
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)
processSubproject(proj.info.name);
end
function processProject()
forEach(projectsprocessor, processLocalProject)
end
function processSubproject(name)
if (projectsblocked[name]) then
return
end
projectsblocked[name] = name
local a = projectsprocessor[name]
if (not a) then
print("missing project: ", name)
return
end
local ns = a.info.namespace
if (not namespacesemitted[ns]) then
namespacesemitted[ns] = "";
dbgGroup(ns)
end
local s = _G["current_project"]
_G["current_project"] = name
a.processor:process(a.processor)
_G["current_project"] = s
projectsemitted[name] = name
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_Script/Features/" .. feature:lower() .. ".lua"
if (not os.isfile(script)) then
return
end
require(script)()
end
require ("Boilerplate.workspace")