Build/Core/JSON/jsonProjectHandlers.lua

683 lines
20 KiB
Lua

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 auBlockProjectKeyDebugArgs(processor, value, taskMap, taskArray, inc, resolve)
filterForKey(value, "value", function(obj)
debugargs(obj)
end, false)
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 auBlockProjectKeyClangOption(processor, value)
auFilter {"toolset:clang"}
buildoptions(value)
auFilter {}
end
local function auBlockProjectKeyMSVCOption(processor, value)
auFilter {"toolset:msc"}
buildoptions(value)
auFilter {}
end
local function auBlockProjectKeyBigObject(processor, value)
filterForKey(value, nil, function(obj)
auFilter{"not toolset:clang"}
buildoptions "/bigobj"
auFilter{}
end)
end
local function auBlockProjectKeyWinStack(processor, value)
filterForKey(value, nil, function(obj)
auFilter{"system:windows"}
linkoptions("/STACK:" .. value)
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"
linkoptions "-O3"
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,
clangOption = auBlockProjectKeyClangOption,
msvcOption = auBlockProjectKeyMSVCOption,
msvcIgnore = auBlockProjectKeyMSVCIgnore,
MSVCOption = auBlockProjectKeyMSVCOption,
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,
debugArgs = auBlockProjectKeyDebugArgs,
winStack = auBlockProjectKeyWinStack
}
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", "debugArgs", "winStack"
}
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
})