Initial community commit
This commit is contained in:
170
Src/external_dependencies/openmpt-trunk/include/genie/src/base/action.lua
vendored
Normal file
170
Src/external_dependencies/openmpt-trunk/include/genie/src/base/action.lua
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
--
|
||||
-- action.lua
|
||||
-- Work with the list of registered actions.
|
||||
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
premake.action = { }
|
||||
|
||||
|
||||
--
|
||||
-- The list of registered actions.
|
||||
--
|
||||
|
||||
premake.action.list = { }
|
||||
|
||||
|
||||
--
|
||||
-- Register a new action.
|
||||
--
|
||||
-- @param a
|
||||
-- The new action object.
|
||||
--
|
||||
|
||||
function premake.action.add(a)
|
||||
-- validate the action object, at least a little bit
|
||||
local missing
|
||||
for _, field in ipairs({"description", "trigger"}) do
|
||||
if (not a[field]) then
|
||||
missing = field
|
||||
end
|
||||
end
|
||||
|
||||
if (missing) then
|
||||
error("action needs a " .. missing, 3)
|
||||
end
|
||||
|
||||
-- add it to the master list
|
||||
premake.action.list[a.trigger] = a
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Trigger an action.
|
||||
--
|
||||
-- @param name
|
||||
-- The name of the action to be triggered.
|
||||
-- @returns
|
||||
-- None.
|
||||
--
|
||||
|
||||
function premake.action.call(name)
|
||||
local a = premake.action.list[name]
|
||||
for sln in premake.solution.each() do
|
||||
if a.onsolution then
|
||||
a.onsolution(sln)
|
||||
end
|
||||
if sln.postsolutioncallbacks then
|
||||
for _,cb in ipairs(sln.postsolutioncallbacks) do
|
||||
cb(sln)
|
||||
end
|
||||
end
|
||||
|
||||
for prj in premake.solution.eachproject(sln) do
|
||||
if a.onproject then
|
||||
a.onproject(prj)
|
||||
end
|
||||
if prj.postprojectcallbacks then
|
||||
for _,cb in ipairs(prj.postprojectcallbacks) do
|
||||
cb(prj)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if a.execute then
|
||||
a.execute()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve the current action, as determined by _ACTION.
|
||||
--
|
||||
-- @return
|
||||
-- The current action, or nil if _ACTION is nil or does not match any action.
|
||||
--
|
||||
|
||||
function premake.action.current()
|
||||
return premake.action.get(_ACTION)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve an action by name.
|
||||
--
|
||||
-- @param name
|
||||
-- The name of the action to retrieve.
|
||||
-- @returns
|
||||
-- The requested action, or nil if the action does not exist.
|
||||
--
|
||||
|
||||
function premake.action.get(name)
|
||||
return premake.action.list[name]
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Iterator for the list of actions.
|
||||
--
|
||||
|
||||
function premake.action.each()
|
||||
-- sort the list by trigger
|
||||
local keys = { }
|
||||
for _, action in pairs(premake.action.list) do
|
||||
table.insert(keys, action.trigger)
|
||||
end
|
||||
table.sort(keys)
|
||||
|
||||
local i = 0
|
||||
return function()
|
||||
i = i + 1
|
||||
return premake.action.list[keys[i]]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Activates a particular action.
|
||||
--
|
||||
-- @param name
|
||||
-- The name of the action to activate.
|
||||
--
|
||||
|
||||
function premake.action.set(name)
|
||||
_ACTION = name
|
||||
-- Some actions imply a particular operating system
|
||||
local action = premake.action.get(name)
|
||||
if action then
|
||||
_OS = action.os or _OS
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Determines if an action supports a particular language or target type.
|
||||
--
|
||||
-- @param action
|
||||
-- The action to test.
|
||||
-- @param feature
|
||||
-- The feature to check, either a programming language or a target type.
|
||||
-- @returns
|
||||
-- True if the feature is supported, false otherwise.
|
||||
--
|
||||
|
||||
function premake.action.supports(action, feature)
|
||||
if not action then
|
||||
return false
|
||||
end
|
||||
if action.valid_languages then
|
||||
if table.contains(action.valid_languages, feature) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
if action.valid_kinds then
|
||||
if table.contains(action.valid_kinds, feature) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
1556
Src/external_dependencies/openmpt-trunk/include/genie/src/base/api.lua
vendored
Normal file
1556
Src/external_dependencies/openmpt-trunk/include/genie/src/base/api.lua
vendored
Normal file
File diff suppressed because it is too large
Load Diff
865
Src/external_dependencies/openmpt-trunk/include/genie/src/base/bake.lua
vendored
Normal file
865
Src/external_dependencies/openmpt-trunk/include/genie/src/base/bake.lua
vendored
Normal file
@@ -0,0 +1,865 @@
|
||||
--
|
||||
-- base/bake.lua
|
||||
--
|
||||
-- Takes all the configuration information provided by the project scripts
|
||||
-- and stored in the solution->project->block hierarchy and flattens it all
|
||||
-- down into one object per configuration. These objects are cached with the
|
||||
-- project, and can be retrieved by calling the getconfig() or eachconfig().
|
||||
--
|
||||
-- Copyright (c) 2008-2011 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
premake.bake = { }
|
||||
local bake = premake.bake
|
||||
|
||||
|
||||
-- do not copy these fields into the configurations
|
||||
|
||||
local nocopy =
|
||||
{
|
||||
blocks = true,
|
||||
keywords = true,
|
||||
projects = true,
|
||||
__configs = true,
|
||||
}
|
||||
|
||||
-- do not cascade these fields from projects to configurations
|
||||
|
||||
local nocascade =
|
||||
{
|
||||
makesettings = true,
|
||||
}
|
||||
|
||||
-- leave these paths as absolute, rather than converting to project relative
|
||||
|
||||
local keeprelative =
|
||||
{
|
||||
basedir = true,
|
||||
location = true,
|
||||
}
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Returns a list of all of the active terms from the current environment.
|
||||
-- See the docs for configuration() for more information about the terms.
|
||||
--
|
||||
|
||||
function premake.getactiveterms(obj)
|
||||
-- While the `obj` argument is not used in this function, it should
|
||||
-- remain accepted so users can override this function if need be, and
|
||||
-- still have access to the context (solution/project).
|
||||
|
||||
local terms = { _action = _ACTION:lower(), os = os.get() }
|
||||
|
||||
-- add option keys or values
|
||||
for key, value in pairs(_OPTIONS) do
|
||||
if value ~= "" then
|
||||
table.insert(terms, value:lower())
|
||||
else
|
||||
table.insert(terms, key:lower())
|
||||
end
|
||||
end
|
||||
|
||||
return terms
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Test a single configuration block keyword against a list of terms.
|
||||
-- The terms are a mix of key/value pairs. The keyword is tested against
|
||||
-- the values; on a match, the corresponding key is returned. This
|
||||
-- enables testing for required values in iskeywordsmatch(), below.
|
||||
--
|
||||
|
||||
function premake.iskeywordmatch(keyword, terms)
|
||||
-- is it negated?
|
||||
if keyword:startswith("not ") then
|
||||
return not premake.iskeywordmatch(keyword:sub(5), terms)
|
||||
end
|
||||
|
||||
for _, pattern in ipairs(keyword:explode(" or ")) do
|
||||
for termkey, term in pairs(terms) do
|
||||
if term:match(pattern) == term then
|
||||
return termkey
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Checks a set of configuration block keywords against a list of terms.
|
||||
-- The required flag is used by the file configurations: only blocks
|
||||
-- with a term that explictly matches the filename get applied; more
|
||||
-- general blocks are skipped over (since they were already applied at
|
||||
-- the config level).
|
||||
--
|
||||
|
||||
function premake.iskeywordsmatch(keywords, terms)
|
||||
local hasrequired = false
|
||||
for _, keyword in ipairs(keywords) do
|
||||
local matched = premake.iskeywordmatch(keyword, terms)
|
||||
if not matched then
|
||||
return false
|
||||
end
|
||||
if matched == "required" then
|
||||
hasrequired = true
|
||||
end
|
||||
end
|
||||
|
||||
if terms.required and not hasrequired then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Converts path fields from absolute to location-relative paths.
|
||||
--
|
||||
-- @param location
|
||||
-- The base location, paths will be relative to this directory.
|
||||
-- @param obj
|
||||
-- The object containing the fields to be adjusted.
|
||||
--
|
||||
|
||||
local function adjustpaths(location, obj)
|
||||
function adjustpathlist(list)
|
||||
for i, p in ipairs(list) do
|
||||
list[i] = path.getrelative(location, p)
|
||||
end
|
||||
end
|
||||
|
||||
if obj.allfiles ~= nil then
|
||||
adjustpathlist(obj.allfiles)
|
||||
end
|
||||
|
||||
for name, value in pairs(obj) do
|
||||
local field = premake.fields[name]
|
||||
if field and value and not keeprelative[name] then
|
||||
if field.kind == "path" then
|
||||
obj[name] = path.getrelative(location, value)
|
||||
elseif field.kind == "dirlist" or field.kind == "filelist" then
|
||||
adjustpathlist(value)
|
||||
elseif field.kind == "keypath" then
|
||||
for k,v in pairs(value) do
|
||||
adjustpathlist(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function removevalue(tbl, remove)
|
||||
for index, item in ipairs(tbl) do
|
||||
if item == remove then
|
||||
table.remove(tbl, index)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function removevalues(tbl, removes)
|
||||
for k, v in pairs(tbl) do
|
||||
for _, pattern in ipairs(removes) do
|
||||
if pattern == tbl[k] then
|
||||
if type(k) == "number" then
|
||||
table.remove(tbl, k)
|
||||
else
|
||||
tbl[k] = nil
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Merge all of the fields from one object into another. String values are overwritten,
|
||||
-- while list values are merged. Fields listed in premake.nocopy are skipped.
|
||||
--
|
||||
-- @param dest
|
||||
-- The destination object, to contain the merged settings.
|
||||
-- @param src
|
||||
-- The source object, containing the settings to added to the destination.
|
||||
--
|
||||
|
||||
local function mergefield(kind, dest, src, mergecopiestotail)
|
||||
local tbl = dest or { }
|
||||
if kind == "keyvalue" or kind == "keypath" then
|
||||
for key, value in pairs(src) do
|
||||
tbl[key] = mergefield("list", tbl[key], value, mergecopiestotail)
|
||||
end
|
||||
else
|
||||
for _, item in ipairs(src) do
|
||||
if tbl[item] then
|
||||
if mergecopiestotail then
|
||||
removevalue(tbl, item)
|
||||
table.insert(tbl, item)
|
||||
tbl[item] = item
|
||||
end
|
||||
else
|
||||
table.insert(tbl, item)
|
||||
tbl[item] = item
|
||||
end
|
||||
end
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
local function mergeobject(dest, src)
|
||||
-- if there's nothing to add, quick out
|
||||
if not src then
|
||||
return
|
||||
end
|
||||
|
||||
for fieldname, value in pairs(src) do
|
||||
if not nocopy[fieldname] then
|
||||
-- fields that are included in the API are merged...
|
||||
local field = premake.fields[fieldname]
|
||||
if field then
|
||||
if type(value) == "table" then
|
||||
dest[fieldname] = mergefield(field.kind, dest[fieldname], value, field.mergecopiestotail)
|
||||
if src.removes then
|
||||
removes = src.removes[fieldname]
|
||||
if removes then
|
||||
removevalues(dest[fieldname], removes)
|
||||
end
|
||||
end
|
||||
else
|
||||
dest[fieldname] = value
|
||||
end
|
||||
|
||||
-- ...everything else is just copied as-is
|
||||
else
|
||||
dest[fieldname] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Merges the settings from a solution's or project's list of configuration blocks,
|
||||
-- for all blocks that match the provided set of environment terms.
|
||||
--
|
||||
-- @param dest
|
||||
-- The destination object, to contain the merged settings.
|
||||
-- @param obj
|
||||
-- The solution or project object being collapsed.
|
||||
-- @param basis
|
||||
-- "Root" level settings, from the solution, which act as a starting point for
|
||||
-- all of the collapsed settings built during this call.
|
||||
-- @param terms
|
||||
-- A list of keywords to filter the configuration blocks; only those that
|
||||
-- match will be included in the destination.
|
||||
-- @param cfgname
|
||||
-- The name of the configuration being collapsed. May be nil.
|
||||
-- @param pltname
|
||||
-- The name of the platform being collapsed. May be nil.
|
||||
--
|
||||
|
||||
local function merge(dest, obj, basis, terms, cfgname, pltname)
|
||||
-- the configuration key is the merged configuration and platform names
|
||||
local key = cfgname or ""
|
||||
pltname = pltname or "Native"
|
||||
if pltname ~= "Native" then
|
||||
key = key .. pltname
|
||||
end
|
||||
|
||||
-- add the configuration and platform to the block filter terms
|
||||
terms.config = (cfgname or ""):lower()
|
||||
terms.platform = pltname:lower()
|
||||
|
||||
-- build the configuration base by merging the solution and project level settings
|
||||
local cfg = {}
|
||||
mergeobject(cfg, basis[key])
|
||||
|
||||
adjustpaths(obj.location, cfg)
|
||||
mergeobject(cfg, obj)
|
||||
|
||||
-- add `kind` to the filter terms
|
||||
if (cfg.kind) then
|
||||
terms['kind']=cfg.kind:lower()
|
||||
end
|
||||
|
||||
-- now add in any blocks that match the filter terms
|
||||
for _, blk in ipairs(obj.blocks) do
|
||||
if (premake.iskeywordsmatch(blk.keywords, terms))then
|
||||
mergeobject(cfg, blk)
|
||||
if (cfg.kind and not cfg.terms.kind) then
|
||||
cfg.terms['kind'] = cfg.kind:lower()
|
||||
terms['kind'] = cfg.kind:lower()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- package it all up and add it to the result set
|
||||
cfg.name = cfgname
|
||||
cfg.platform = pltname
|
||||
for k,v in pairs(terms) do
|
||||
cfg.terms[k] =v
|
||||
end
|
||||
dest[key] = cfg
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Collapse a solution or project object down to a canonical set of configuration settings,
|
||||
-- keyed by configuration block/platform pairs, and taking into account the current
|
||||
-- environment settings.
|
||||
--
|
||||
-- @param obj
|
||||
-- The solution or project to be collapsed.
|
||||
-- @param basis
|
||||
-- "Root" level settings, from the solution, which act as a starting point for
|
||||
-- all of the collapsed settings built during this call.
|
||||
-- @returns
|
||||
-- The collapsed list of settings, keyed by configuration block/platform pair.
|
||||
--
|
||||
|
||||
local function collapse(obj, basis)
|
||||
local result = {}
|
||||
basis = basis or {}
|
||||
|
||||
-- find the solution, which contains the configuration and platform lists
|
||||
local sln = obj.solution or obj
|
||||
|
||||
-- build a set of configuration filter terms; only those configuration blocks
|
||||
-- with a matching set of keywords will be included in the merged results
|
||||
local terms = premake.getactiveterms(obj)
|
||||
|
||||
-- build a project-level configuration.
|
||||
merge(result, obj, basis, terms)--this adjusts terms
|
||||
|
||||
-- now build configurations for each build config/platform pair
|
||||
for _, cfgname in ipairs(sln.configurations) do
|
||||
local terms_local = {}
|
||||
for k,v in pairs(terms)do terms_local[k]=v end
|
||||
merge(result, obj, basis, terms_local, cfgname, "Native")--terms cam also be adjusted here
|
||||
for _, pltname in ipairs(sln.platforms or {}) do
|
||||
if pltname ~= "Native" then
|
||||
merge(result, obj, basis,terms_local, cfgname, pltname)--terms also here
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Computes a unique objects directory for every configuration, using the
|
||||
-- following choices:
|
||||
-- [1] -> the objects directory as set in the project of config
|
||||
-- [2] -> [1] + the platform name
|
||||
-- [3] -> [2] + the configuration name
|
||||
-- [4] -> [3] + the project name
|
||||
--
|
||||
|
||||
local function builduniquedirs()
|
||||
local num_variations = 4
|
||||
|
||||
-- Start by listing out each possible object directory for each configuration.
|
||||
-- Keep a count of how many times each path gets used across the session.
|
||||
local cfg_dirs = {}
|
||||
local hit_counts = {}
|
||||
|
||||
for sln in premake.solution.each() do
|
||||
for _, prj in ipairs(sln.projects) do
|
||||
for _, cfg in pairs(prj.__configs) do
|
||||
|
||||
local dirs = { }
|
||||
dirs[1] = path.getabsolute(path.join(cfg.location, cfg.objdir or cfg.project.objdir or "obj"))
|
||||
dirs[2] = path.join(dirs[1], iif(cfg.platform == "Native", "", cfg.platform))
|
||||
dirs[3] = path.join(dirs[2], cfg.name)
|
||||
dirs[4] = path.join(dirs[3], cfg.project.name)
|
||||
cfg_dirs[cfg] = dirs
|
||||
|
||||
-- configurations other than the root should bias toward a more
|
||||
-- description path, including the platform or config name
|
||||
local start = iif(cfg.name, 2, 1)
|
||||
for v = start, num_variations do
|
||||
local d = dirs[v]
|
||||
hit_counts[d] = (hit_counts[d] or 0) + 1
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Now assign an object directory to each configuration, skipping those
|
||||
-- that are in use somewhere else in the session
|
||||
for sln in premake.solution.each() do
|
||||
for _, prj in ipairs(sln.projects) do
|
||||
for _, cfg in pairs(prj.__configs) do
|
||||
|
||||
local dir
|
||||
local start = iif(cfg.name, 2, 1)
|
||||
for v = start, iif(cfg.flags.SingleOutputDir==true,num_variations-1,num_variations) do
|
||||
dir = cfg_dirs[cfg][v]
|
||||
if hit_counts[dir] == 1 then break end
|
||||
end
|
||||
cfg.objectsdir = path.getrelative(cfg.location, dir)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Pre-computes the build and link targets for a configuration.
|
||||
--
|
||||
|
||||
local function buildtargets()
|
||||
for sln in premake.solution.each() do
|
||||
for _, prj in ipairs(sln.projects) do
|
||||
for _, cfg in pairs(prj.__configs) do
|
||||
-- determine which conventions the target should follow for this config
|
||||
local pathstyle = premake.getpathstyle(cfg)
|
||||
local namestyle = premake.getnamestyle(cfg)
|
||||
|
||||
-- build the targets
|
||||
cfg.buildtarget = premake.gettarget(cfg, "build", pathstyle, namestyle, cfg.system)
|
||||
cfg.linktarget = premake.gettarget(cfg, "link", pathstyle, namestyle, cfg.system)
|
||||
if pathstyle == "windows" then
|
||||
cfg.objectsdir = path.translate(cfg.objectsdir, "\\")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function getCfgKind(cfg)
|
||||
if(cfg.kind) then
|
||||
return cfg.kind;
|
||||
end
|
||||
|
||||
if(cfg.project.__configs[""] and cfg.project.__configs[""].kind) then
|
||||
return cfg.project.__configs[""].kind;
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function getprojrec(dstArray, foundList, cfg, cfgname, searchField, bLinkage)
|
||||
if(not cfg) then return end
|
||||
|
||||
local foundUsePrjs = {};
|
||||
for _, useName in ipairs(cfg[searchField]) do
|
||||
local testName = useName:lower();
|
||||
if((not foundList[testName])) then
|
||||
local theProj = nil;
|
||||
local theUseProj = nil;
|
||||
for _, prj in ipairs(cfg.project.solution.projects) do
|
||||
if (prj.name:lower() == testName) then
|
||||
if(prj.usage) then
|
||||
theUseProj = prj;
|
||||
else
|
||||
theProj = prj;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Must connect to a usage project.
|
||||
if(theUseProj) then
|
||||
foundList[testName] = true;
|
||||
local prjEntry = {
|
||||
name = testName,
|
||||
proj = theProj,
|
||||
usageProj = theUseProj,
|
||||
bLinkageOnly = bLinkage,
|
||||
};
|
||||
dstArray[testName] = prjEntry;
|
||||
table.insert(foundUsePrjs, theUseProj);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, usePrj in ipairs(foundUsePrjs) do
|
||||
--Links can only recurse through static libraries.
|
||||
if((searchField ~= "links") or
|
||||
(getCfgKind(usePrj.__configs[cfgname]) == "StaticLib")) then
|
||||
getprojrec(dstArray, foundList, usePrj.__configs[cfgname],
|
||||
cfgname, searchField, bLinkage);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- This function will recursively get all projects that the given configuration has in its "uses"
|
||||
-- field. The return values are a list of tables. Each table in that list contains the following:
|
||||
-- name = The lowercase name of the project.
|
||||
-- proj = The project. Can be nil if it is usage-only.
|
||||
-- usageProj = The usage project. Can't be nil, as using a project that has no
|
||||
-- usage project is not put into the list.
|
||||
-- bLinkageOnly = If this is true, then only the linkage information should be copied.
|
||||
-- The recursion will only look at the "uses" field on *usage* projects.
|
||||
-- This function will also add projects to the list that are mentioned in the "links"
|
||||
-- field of usage projects. These will only copy linker information, but they will recurse.
|
||||
-- through other "links" fields.
|
||||
--
|
||||
local function getprojectsconnections(cfg, cfgname)
|
||||
local dstArray = {};
|
||||
local foundList = {};
|
||||
foundList[cfg.project.name:lower()] = true;
|
||||
|
||||
--First, follow the uses recursively.
|
||||
getprojrec(dstArray, foundList, cfg, cfgname, "uses", false);
|
||||
|
||||
--Next, go through all of the usage projects and recursively get their links.
|
||||
--But only if they're not already there. Get the links as linkage-only.
|
||||
local linkArray = {};
|
||||
for prjName, prjEntry in pairs(dstArray) do
|
||||
getprojrec(linkArray, foundList, prjEntry.usageProj.__configs[cfgname], cfgname,
|
||||
"links", true);
|
||||
end
|
||||
|
||||
--Copy from linkArray into dstArray.
|
||||
for prjName, prjEntry in pairs(linkArray) do
|
||||
dstArray[prjName] = prjEntry;
|
||||
end
|
||||
|
||||
return dstArray;
|
||||
end
|
||||
|
||||
|
||||
local function isnameofproj(cfg, strName)
|
||||
local sln = cfg.project.solution;
|
||||
local strTest = strName:lower();
|
||||
for prjIx, prj in ipairs(sln.projects) do
|
||||
if (prj.name:lower() == strTest) then
|
||||
return true;
|
||||
end
|
||||
end
|
||||
|
||||
return false;
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Copies the field from dstCfg to srcCfg.
|
||||
--
|
||||
local function copydependentfield(srcCfg, dstCfg, strSrcField)
|
||||
local srcField = premake.fields[strSrcField];
|
||||
local strDstField = strSrcField;
|
||||
|
||||
if type(srcCfg[strSrcField]) == "table" then
|
||||
--handle paths.
|
||||
if (srcField.kind == "dirlist" or srcField.kind == "filelist") and
|
||||
(not keeprelative[strSrcField]) then
|
||||
for i,p in ipairs(srcCfg[strSrcField]) do
|
||||
table.insert(dstCfg[strDstField],
|
||||
path.rebase(p, srcCfg.project.location, dstCfg.project.location))
|
||||
end
|
||||
else
|
||||
if(strSrcField == "links") then
|
||||
for i,p in ipairs(srcCfg[strSrcField]) do
|
||||
if(not isnameofproj(dstCfg, p)) then
|
||||
table.insert(dstCfg[strDstField], p)
|
||||
else
|
||||
printf("Failed to copy '%s' from proj '%s'.",
|
||||
p, srcCfg.project.name);
|
||||
end
|
||||
end
|
||||
else
|
||||
for i,p in ipairs(srcCfg[strSrcField]) do
|
||||
table.insert(dstCfg[strDstField], p)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if(srcField.kind == "path" and (not keeprelative[strSrcField])) then
|
||||
dstCfg[strDstField] = path.rebase(srcCfg[strSrcField],
|
||||
prj.location, dstCfg.project.location);
|
||||
else
|
||||
dstCfg[strDstField] = srcCfg[strSrcField];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- This function will take the list of project entries and apply their usage project data
|
||||
-- to the given configuration. It will copy compiling information for the projects that are
|
||||
-- not listed as linkage-only. It will copy the linking information for projects only if
|
||||
-- the source project is not a static library. It won't copy linking information
|
||||
-- if the project is in this solution; instead it will add that project to the configuration's
|
||||
-- links field, expecting that Premake will handle the rest.
|
||||
--
|
||||
local function copyusagedata(cfg, cfgname, linkToProjs)
|
||||
local myPrj = cfg.project;
|
||||
local bIsStaticLib = (getCfgKind(cfg) == "StaticLib");
|
||||
|
||||
for prjName, prjEntry in pairs(linkToProjs) do
|
||||
local srcPrj = prjEntry.usageProj;
|
||||
local srcCfg = srcPrj.__configs[cfgname];
|
||||
|
||||
for name, field in pairs(premake.fields) do
|
||||
if(srcCfg[name]) then
|
||||
if(field.usagecopy) then
|
||||
if(not prjEntry.bLinkageOnly) then
|
||||
copydependentfield(srcCfg, cfg, name)
|
||||
end
|
||||
elseif(field.linkagecopy) then
|
||||
--Copy the linkage data if we're building a non-static thing
|
||||
--and this is a pure usage project. If it's not pure-usage, then
|
||||
--we will simply put the project's name in the links field later.
|
||||
if((not bIsStaticLib) and (not prjEntry.proj)) then
|
||||
copydependentfield(srcCfg, cfg, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if((not bIsStaticLib) and prjEntry.proj) then
|
||||
table.insert(cfg.links, prjEntry.proj.name);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Build an inverse dictionary of literal vpaths for fast lookup
|
||||
--
|
||||
|
||||
local function inverseliteralvpaths()
|
||||
for sln in premake.solution.each() do
|
||||
for _,prj in ipairs(sln.projects) do
|
||||
prj.inversevpaths = {}
|
||||
for replacement, patterns in pairs(prj.vpaths or {}) do
|
||||
for _, pattern in ipairs(patterns) do
|
||||
if string.find(pattern, "*") == nil then
|
||||
prj.inversevpaths[pattern] = replacement
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--
|
||||
-- Main function, controls the process of flattening the configurations.
|
||||
--
|
||||
|
||||
function premake.bake.buildconfigs()
|
||||
|
||||
-- convert project path fields to be relative to project location
|
||||
for sln in premake.solution.each() do
|
||||
for _, prj in ipairs(sln.projects) do
|
||||
prj.location = prj.location or sln.location or prj.basedir
|
||||
adjustpaths(prj.location, prj)
|
||||
for _, blk in ipairs(prj.blocks) do
|
||||
adjustpaths(prj.location, blk)
|
||||
end
|
||||
end
|
||||
sln.location = sln.location or sln.basedir
|
||||
end
|
||||
|
||||
-- convert paths for imported projects to be relative to solution location
|
||||
for sln in premake.solution.each() do
|
||||
for _, iprj in ipairs(sln.importedprojects) do
|
||||
iprj.location = path.getabsolute(iprj.location)
|
||||
end
|
||||
end
|
||||
|
||||
inverseliteralvpaths()
|
||||
|
||||
-- collapse configuration blocks, so that there is only one block per build
|
||||
-- configuration/platform pair, filtered to the current operating environment
|
||||
for sln in premake.solution.each() do
|
||||
local basis = collapse(sln)
|
||||
for _, prj in ipairs(sln.projects) do
|
||||
prj.__configs = collapse(prj, basis)
|
||||
for _, cfg in pairs(prj.__configs) do
|
||||
bake.postprocess(prj, cfg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This loop finds the projects that a configuration is connected to
|
||||
-- via its "uses" field. It will then copy any usage project information from that
|
||||
-- usage project to the configuration in question.
|
||||
for sln in premake.solution.each() do
|
||||
for prjIx, prj in ipairs(sln.projects) do
|
||||
if(not prj.usage) then
|
||||
for cfgname, cfg in pairs(prj.__configs) do
|
||||
local usesPrjs = getprojectsconnections(cfg, cfgname);
|
||||
copyusagedata(cfg, cfgname, usesPrjs)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- mark all configurations that have been removed via their removes table.
|
||||
for sln in premake.solution.each() do
|
||||
for prjIx, prj in ipairs(sln.projects) do
|
||||
for cfgName, cfg in pairs(prj.__configs) do
|
||||
cfg.build = true
|
||||
|
||||
local removes = nil
|
||||
|
||||
if cfg.removes ~= nil then
|
||||
removes = cfg.removes["platforms"];
|
||||
end
|
||||
|
||||
if removes ~= nil then
|
||||
for _,p in ipairs(removes) do
|
||||
if p == cfg.platform then
|
||||
cfg.build = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove all usage projects.
|
||||
for sln in premake.solution.each() do
|
||||
local removeList = {};
|
||||
for index, prj in ipairs(sln.projects) do
|
||||
if(prj.usage) then
|
||||
table.insert(removeList, 1, index); --Add in reverse order.
|
||||
end
|
||||
end
|
||||
|
||||
for _, index in ipairs(removeList) do
|
||||
table.remove(sln.projects, index);
|
||||
end
|
||||
end
|
||||
|
||||
-- assign unique object directories to each configuration
|
||||
builduniquedirs()
|
||||
|
||||
-- walk it again and build the targets and unique directories
|
||||
buildtargets(cfg)
|
||||
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Post-process a project configuration, applying path fix-ups and other adjustments
|
||||
-- to the "raw" setting data pulled from the project script.
|
||||
--
|
||||
-- @param prj
|
||||
-- The project object which contains the configuration.
|
||||
-- @param cfg
|
||||
-- The configuration object to be fixed up.
|
||||
--
|
||||
|
||||
function premake.bake.postprocess(prj, cfg)
|
||||
cfg.project = prj
|
||||
cfg.shortname = premake.getconfigname(cfg.name, cfg.platform, true)
|
||||
cfg.longname = premake.getconfigname(cfg.name, cfg.platform)
|
||||
|
||||
-- set the project location, if not already set
|
||||
cfg.location = cfg.location or cfg.basedir
|
||||
|
||||
-- figure out the target system
|
||||
local platform = premake.platforms[cfg.platform]
|
||||
if platform.iscrosscompiler then
|
||||
cfg.system = cfg.platform
|
||||
else
|
||||
cfg.system = os.get()
|
||||
end
|
||||
|
||||
-- adjust the kind as required by the target system
|
||||
if cfg.kind == "Bundle"
|
||||
and _ACTION ~= "gmake"
|
||||
and (_ACTION ~= "ninja" and (not prj.options or not prj.options.SkipBundling))
|
||||
and not _ACTION:match("xcode[0-9]") then
|
||||
cfg.kind = "SharedLib"
|
||||
end
|
||||
|
||||
if cfg.kind == "SharedLib" and platform.nosharedlibs then
|
||||
cfg.kind = "StaticLib"
|
||||
end
|
||||
|
||||
local removefiles = cfg.removefiles
|
||||
if _ACTION == 'gmake' or _ACTION == 'ninja' then
|
||||
removefiles = table.join(removefiles, cfg.excludes)
|
||||
end
|
||||
|
||||
-- build a table of removed files, indexed by file name
|
||||
local removefilesDict = {}
|
||||
for _, fname in ipairs(removefiles) do
|
||||
removefilesDict[fname] = true
|
||||
end
|
||||
|
||||
-- remove excluded files from the file list
|
||||
local files = {}
|
||||
for _, fname in ipairs(cfg.files) do
|
||||
if removefilesDict[fname] == nil then
|
||||
table.insert(files, fname)
|
||||
end
|
||||
end
|
||||
cfg.files = files
|
||||
|
||||
-- remove excluded files from the project's allfiles list, and
|
||||
-- un-duplify it
|
||||
local allfiles = {}
|
||||
local allfilesDict = {}
|
||||
if cfg.allfiles ~= nil then
|
||||
for _, fname in ipairs(cfg.allfiles) do
|
||||
if allfilesDict[fname] == nil then
|
||||
if removefilesDict[fname] == nil then
|
||||
allfilesDict[fname] = true
|
||||
table.insert(allfiles, fname)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
cfg.allfiles = allfiles
|
||||
|
||||
-- fixup the data
|
||||
for name, field in pairs(premake.fields) do
|
||||
-- re-key flag fields for faster lookups
|
||||
if field.isflags then
|
||||
local values = cfg[name]
|
||||
for _, flag in ipairs(values) do values[flag] = true end
|
||||
end
|
||||
end
|
||||
|
||||
-- build configuration objects for all files
|
||||
-- TODO: can I build this as a tree instead, and avoid the extra
|
||||
-- step of building it later?
|
||||
local cfgfields = {
|
||||
{"__fileconfigs", cfg.files},
|
||||
{"__allfileconfigs", cfg.allfiles},
|
||||
}
|
||||
|
||||
for _, cfgfield in ipairs(cfgfields) do
|
||||
local fieldname = cfgfield[1]
|
||||
local field = cfgfield[2]
|
||||
|
||||
cfg[fieldname] = { }
|
||||
for _, fname in ipairs(field) do
|
||||
local fcfg = {}
|
||||
|
||||
-- Only do this if the script has called enablefilelevelconfig()
|
||||
if premake._filelevelconfig then
|
||||
cfg.terms.required = fname:lower()
|
||||
for _, blk in ipairs(cfg.project.blocks) do
|
||||
-- BK - `iskeywordsmatch` call is super slow for large projects...
|
||||
if (premake.iskeywordsmatch(blk.keywords, cfg.terms)) then
|
||||
mergeobject(fcfg, blk)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- add indexed by name and integer
|
||||
-- TODO: when everything is converted to trees I won't need
|
||||
-- to index by name any longer
|
||||
fcfg.name = fname
|
||||
cfg[fieldname][fname] = fcfg
|
||||
table.insert(cfg[fieldname], fcfg)
|
||||
end
|
||||
end
|
||||
end
|
||||
103
Src/external_dependencies/openmpt-trunk/include/genie/src/base/cmdline.lua
vendored
Normal file
103
Src/external_dependencies/openmpt-trunk/include/genie/src/base/cmdline.lua
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
--
|
||||
-- cmdline.lua
|
||||
-- Functions to define and handle command line actions and options.
|
||||
-- Copyright (c) 2002-2011 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- Built-in command line options
|
||||
--
|
||||
|
||||
newoption
|
||||
{
|
||||
trigger = "cc",
|
||||
value = "VALUE",
|
||||
description = "Choose a C/C++ compiler set",
|
||||
allowed = {
|
||||
{ "gcc", "GNU GCC (gcc/g++)" },
|
||||
{ "ow", "OpenWatcom" },
|
||||
{ "ghs", "Green Hills Software" },
|
||||
}
|
||||
}
|
||||
|
||||
newoption
|
||||
{
|
||||
trigger = "dotnet",
|
||||
value = "VALUE",
|
||||
description = "Choose a .NET compiler set",
|
||||
allowed = {
|
||||
{ "msnet", "Microsoft .NET (csc)" },
|
||||
{ "mono", "Novell Mono (mcs)" },
|
||||
{ "pnet", "Portable.NET (cscc)" },
|
||||
}
|
||||
}
|
||||
|
||||
newoption
|
||||
{
|
||||
trigger = "file",
|
||||
value = "FILE",
|
||||
description = "Read FILE as a Premake script; default is 'premake4.lua'"
|
||||
}
|
||||
|
||||
newoption
|
||||
{
|
||||
trigger = "help",
|
||||
description = "Display this information"
|
||||
}
|
||||
|
||||
newoption
|
||||
{
|
||||
trigger = "os",
|
||||
value = "VALUE",
|
||||
description = "Generate files for a different operating system",
|
||||
allowed = {
|
||||
{ "bsd", "OpenBSD, NetBSD, or FreeBSD" },
|
||||
{ "linux", "Linux" },
|
||||
{ "macosx", "Apple Mac OS X" },
|
||||
{ "solaris", "Solaris" },
|
||||
{ "windows", "Microsoft Windows" },
|
||||
}
|
||||
}
|
||||
|
||||
newoption
|
||||
{
|
||||
trigger = "platform",
|
||||
value = "VALUE",
|
||||
description = "Add target architecture (if supported by action)",
|
||||
allowed = {
|
||||
{ "x32", "32-bit" },
|
||||
{ "x64", "64-bit" },
|
||||
{ "universal", "Mac OS X Universal, 32- and 64-bit" },
|
||||
{ "universal32", "Mac OS X Universal, 32-bit only" },
|
||||
{ "universal64", "Mac OS X Universal, 64-bit only" },
|
||||
{ "ps3", "Playstation 3" },
|
||||
{ "orbis", "Playstation 4" },
|
||||
{ "xbox360", "Xbox 360" },
|
||||
{ "durango", "Xbox One" },
|
||||
{ "ARM", "ARM" },
|
||||
{ "ARM64", "ARM64" },
|
||||
{ "PowerPC", "PowerPC" },
|
||||
{ "nx32", "Nintendo Switch, 32-bit only" },
|
||||
{ "nx64", "Nintendo Switch, 64-bit only" },
|
||||
}
|
||||
}
|
||||
|
||||
newoption
|
||||
{
|
||||
trigger = "scripts",
|
||||
value = "path",
|
||||
description = "Search for additional scripts on the given path"
|
||||
}
|
||||
|
||||
newoption
|
||||
{
|
||||
trigger = "debug-profiler",
|
||||
description = "GENie script generation profiler."
|
||||
}
|
||||
|
||||
newoption
|
||||
{
|
||||
trigger = "version",
|
||||
description = "Display version information"
|
||||
}
|
||||
107
Src/external_dependencies/openmpt-trunk/include/genie/src/base/config.lua
vendored
Normal file
107
Src/external_dependencies/openmpt-trunk/include/genie/src/base/config.lua
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
--
|
||||
-- configs.lua
|
||||
--
|
||||
-- Functions for working with configuration objects (which can include
|
||||
-- projects and solutions).
|
||||
--
|
||||
-- Copyright (c) 2008-2011 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
premake.config = { }
|
||||
local config = premake.config
|
||||
|
||||
|
||||
--
|
||||
-- Determine if a configuration represents a "debug" or "release" build.
|
||||
-- This controls the runtime library selected for Visual Studio builds
|
||||
-- (and might also be useful elsewhere).
|
||||
--
|
||||
|
||||
function premake.config.isdebugbuild(cfg)
|
||||
-- If any of the specific runtime flags are set
|
||||
if cfg.flags.DebugRuntime then
|
||||
return true
|
||||
end
|
||||
|
||||
if cfg.flags.ReleaseRuntime then
|
||||
return false
|
||||
end
|
||||
|
||||
-- If any of the optimize flags are set, it's a release a build
|
||||
if cfg.flags.Optimize or cfg.flags.OptimizeSize or cfg.flags.OptimizeSpeed then
|
||||
return false
|
||||
end
|
||||
|
||||
-- If symbols are not defined, it's a release build
|
||||
if not cfg.flags.Symbols then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Return an iterator over each file included in this configuration.
|
||||
--
|
||||
|
||||
function premake.config.eachfile(cfg)
|
||||
local i = 0
|
||||
local t = cfg.files
|
||||
return function ()
|
||||
i = i + 1
|
||||
if (i <= #t) then
|
||||
local fcfg = cfg.__fileconfigs[t[i]]
|
||||
fcfg.vpath = premake.project.getvpath(cfg.project, fcfg.name)
|
||||
return fcfg
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Determines if this configuration can be linked incrementally.
|
||||
--
|
||||
|
||||
function premake.config.isincrementallink(cfg)
|
||||
if cfg.kind == "StaticLib" then
|
||||
return false
|
||||
end
|
||||
return not config.islinkeroptimizedbuild(cfg.flags) and not cfg.flags.NoIncrementalLink
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Determine if this configuration uses one of the optimize flags.
|
||||
--
|
||||
|
||||
function premake.config.isoptimizedbuild(flags)
|
||||
return flags.Optimize or flags.OptimizeSize or flags.OptimizeSpeed
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Determine if this configuration uses one of the optimize flags.
|
||||
-- Optimized builds get different treatment, such as full linking
|
||||
-- instead of incremental.
|
||||
--
|
||||
|
||||
function premake.config.islinkeroptimizedbuild(flags)
|
||||
return config.isoptimizedbuild(flags) and not flags.NoOptimizeLink
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Determines if this configuration uses edit and continue.
|
||||
--
|
||||
|
||||
function premake.config.iseditandcontinue(cfg)
|
||||
if cfg.flags.NoEditAndContinue
|
||||
or cfg.flags.Managed
|
||||
or (cfg.kind ~= "StaticLib" and not config.isincrementallink(cfg))
|
||||
or config.islinkeroptimizedbuild(cfg.flags) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
209
Src/external_dependencies/openmpt-trunk/include/genie/src/base/globals.lua
vendored
Normal file
209
Src/external_dependencies/openmpt-trunk/include/genie/src/base/globals.lua
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
--
|
||||
-- globals.lua
|
||||
-- Global tables and variables, replacements and extensions to Lua's global functions.
|
||||
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
|
||||
-- A top-level namespace for support functions
|
||||
|
||||
premake = { }
|
||||
|
||||
|
||||
-- The list of supported platforms; also update list in cmdline.lua
|
||||
|
||||
premake.platforms =
|
||||
{
|
||||
Native =
|
||||
{
|
||||
cfgsuffix = "",
|
||||
},
|
||||
x32 =
|
||||
{
|
||||
cfgsuffix = "32",
|
||||
},
|
||||
x64 =
|
||||
{
|
||||
cfgsuffix = "64",
|
||||
},
|
||||
Universal =
|
||||
{
|
||||
cfgsuffix = "univ",
|
||||
},
|
||||
Universal32 =
|
||||
{
|
||||
cfgsuffix = "univ32",
|
||||
},
|
||||
Universal64 =
|
||||
{
|
||||
cfgsuffix = "univ64",
|
||||
},
|
||||
PS3 =
|
||||
{
|
||||
cfgsuffix = "ps3",
|
||||
iscrosscompiler = true,
|
||||
nosharedlibs = true,
|
||||
namestyle = "PS3",
|
||||
},
|
||||
WiiDev =
|
||||
{
|
||||
cfgsuffix = "wii",
|
||||
iscrosscompiler = true,
|
||||
namestyle = "PS3",
|
||||
},
|
||||
Xbox360 =
|
||||
{
|
||||
cfgsuffix = "xbox360",
|
||||
iscrosscompiler = true,
|
||||
namestyle = "windows",
|
||||
},
|
||||
PowerPC =
|
||||
{
|
||||
cfgsuffix = "ppc",
|
||||
iscrosscompiler = true,
|
||||
},
|
||||
ARM =
|
||||
{
|
||||
cfgsuffix = "ARM",
|
||||
iscrosscompiler = true,
|
||||
},
|
||||
ARM64 =
|
||||
{
|
||||
cfgsuffix = "ARM64",
|
||||
iscrosscompiler = true,
|
||||
},
|
||||
Orbis =
|
||||
{
|
||||
cfgsuffix = "orbis",
|
||||
iscrosscompiler = true,
|
||||
namestyle = "Orbis",
|
||||
},
|
||||
Durango =
|
||||
{
|
||||
cfgsuffix = "durango",
|
||||
iscrosscompiler = true,
|
||||
nosharedlibs = true,
|
||||
namestyle = "windows",
|
||||
},
|
||||
TegraAndroid =
|
||||
{
|
||||
cfgsuffix = "tegraandroid",
|
||||
iscrosscompiler = true,
|
||||
namestyle = "TegraAndroid",
|
||||
},
|
||||
NX32 =
|
||||
{
|
||||
cfgsuffix = "nx32",
|
||||
iscrosscompiler = true,
|
||||
namestyle = "NX",
|
||||
},
|
||||
NX64 =
|
||||
{
|
||||
cfgsuffix = "nx64",
|
||||
iscrosscompiler = true,
|
||||
namestyle = "NX",
|
||||
},
|
||||
Emscripten =
|
||||
{
|
||||
cfgsuffix = "emscripten",
|
||||
iscrosscompiler = true,
|
||||
nosharedlibs = true,
|
||||
namestyle = "Emscripten",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
-- A replacement for Lua's built-in dofile() function, this one sets the
|
||||
-- current working directory to the script's location, enabling script-relative
|
||||
-- referencing of other files and resources.
|
||||
--
|
||||
|
||||
local builtin_dofile = dofile
|
||||
function dofile(fname)
|
||||
-- remember the current working directory and file; I'll restore it shortly
|
||||
local oldcwd = os.getcwd()
|
||||
local oldfile = _SCRIPT
|
||||
|
||||
-- if the file doesn't exist, check the search path
|
||||
if (not os.isfile(fname)) then
|
||||
local path = os.pathsearch(fname, _OPTIONS["scripts"], os.getenv("PREMAKE_PATH"))
|
||||
if (path) then
|
||||
fname = path.."/"..fname
|
||||
end
|
||||
end
|
||||
|
||||
-- use the absolute path to the script file, to avoid any file name
|
||||
-- ambiguity if an error should arise
|
||||
_SCRIPT = path.getabsolute(fname)
|
||||
|
||||
-- switch the working directory to the new script location
|
||||
local newcwd = path.getdirectory(_SCRIPT)
|
||||
os.chdir(newcwd)
|
||||
|
||||
-- run the chunk. How can I catch variable return values?
|
||||
local a, b, c, d, e, f = builtin_dofile(_SCRIPT)
|
||||
|
||||
-- restore the previous working directory when done
|
||||
_SCRIPT = oldfile
|
||||
os.chdir(oldcwd)
|
||||
return a, b, c, d, e, f
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- "Immediate If" - returns one of the two values depending on the value of expr.
|
||||
--
|
||||
|
||||
function iif(expr, trueval, falseval)
|
||||
if (expr) then
|
||||
return trueval
|
||||
else
|
||||
return falseval
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- A shortcut for including another build file, often used for projects.
|
||||
--
|
||||
|
||||
function include(fname)
|
||||
local dir, name = premake.findDefaultScript(fname, false)
|
||||
if dir ~= nil then
|
||||
return dofile(dir .. "/" .. name)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- A shortcut for printing formatted output.
|
||||
--
|
||||
|
||||
function printf(msg, ...)
|
||||
local arg={...}
|
||||
print(string.format(msg, table.unpack(arg)))
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- An extended type API to identify project object types by reading the
|
||||
-- "__type" field from the metatable.
|
||||
--
|
||||
|
||||
function typex(t)
|
||||
local mt = getmetatable(t)
|
||||
if (mt) then
|
||||
if (mt.__type) then
|
||||
return mt.__type
|
||||
end
|
||||
end
|
||||
return type(t)
|
||||
end
|
||||
|
||||
48
Src/external_dependencies/openmpt-trunk/include/genie/src/base/help.lua
vendored
Normal file
48
Src/external_dependencies/openmpt-trunk/include/genie/src/base/help.lua
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
--
|
||||
-- help.lua
|
||||
-- User help, displayed on /help option.
|
||||
-- Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
|
||||
function premake.showhelp()
|
||||
|
||||
-- display the basic usage
|
||||
printf("")
|
||||
printf("Usage: genie [options] action [arguments]")
|
||||
printf("")
|
||||
|
||||
|
||||
-- display all options
|
||||
printf("OPTIONS")
|
||||
printf("")
|
||||
for option in premake.option.each() do
|
||||
local trigger = option.trigger
|
||||
local description = option.description
|
||||
if (option.value) then trigger = trigger .. "=" .. option.value end
|
||||
if (option.allowed) then description = description .. "; one of:" end
|
||||
|
||||
printf(" --%-15s %s", trigger, description)
|
||||
if (option.allowed) then
|
||||
for _, value in ipairs(option.allowed) do
|
||||
printf(" %-14s %s", value[1], value[2])
|
||||
end
|
||||
end
|
||||
printf("")
|
||||
end
|
||||
|
||||
-- display all actions
|
||||
printf("ACTIONS")
|
||||
printf("")
|
||||
for action in premake.action.each() do
|
||||
printf(" %-17s %s", action.trigger, action.description)
|
||||
end
|
||||
printf("")
|
||||
|
||||
|
||||
-- see more
|
||||
printf("For additional information, see https://github.com/bkaradzic/genie")
|
||||
|
||||
end
|
||||
|
||||
|
||||
291
Src/external_dependencies/openmpt-trunk/include/genie/src/base/inspect.lua
vendored
Normal file
291
Src/external_dependencies/openmpt-trunk/include/genie/src/base/inspect.lua
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
-- Copyright (c) 2013 Enrique García Cota
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, sublicense, and/or sell copies of the Software, and to
|
||||
-- permit persons to whom the Software is furnished to do so, subject to
|
||||
-- the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included
|
||||
-- in all copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
-- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
-- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
-- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
-- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
-- Apostrophizes the string if it has quotes, but not aphostrophes
|
||||
-- Otherwise, it returns a regular quoted string
|
||||
local function smartQuote(str)
|
||||
if str:match('"') and not str:match("'") then
|
||||
return "'" .. str .. "'"
|
||||
end
|
||||
return '"' .. str:gsub('"', '\\"') .. '"'
|
||||
end
|
||||
|
||||
local controlCharsTranslation = {
|
||||
["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
|
||||
["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v"
|
||||
}
|
||||
|
||||
local function escapeChar(c) return controlCharsTranslation[c] end
|
||||
|
||||
local function escape(str)
|
||||
local result = str:gsub("\\", "\\\\"):gsub("(%c)", escapeChar)
|
||||
return result
|
||||
end
|
||||
|
||||
local function isIdentifier(str)
|
||||
return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" )
|
||||
end
|
||||
|
||||
local function isArrayKey(k, length)
|
||||
return type(k) == 'number' and 1 <= k and k <= length
|
||||
end
|
||||
|
||||
local function isDictionaryKey(k, length)
|
||||
return not isArrayKey(k, length)
|
||||
end
|
||||
|
||||
local defaultTypeOrders = {
|
||||
['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,
|
||||
['function'] = 5, ['userdata'] = 6, ['thread'] = 7
|
||||
}
|
||||
|
||||
local function sortKeys(a, b)
|
||||
local ta, tb = type(a), type(b)
|
||||
|
||||
-- strings and numbers are sorted numerically/alphabetically
|
||||
if ta == tb and (ta == 'string' or ta == 'number') then return a < b end
|
||||
|
||||
local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]
|
||||
-- Two default types are compared according to the defaultTypeOrders table
|
||||
if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb]
|
||||
elseif dta then return true -- default types before custom ones
|
||||
elseif dtb then return false -- custom types after default ones
|
||||
end
|
||||
|
||||
-- custom types are sorted out alphabetically
|
||||
return ta < tb
|
||||
end
|
||||
|
||||
local function getDictionaryKeys(t)
|
||||
local keys, length = {}, #t
|
||||
for k,_ in pairs(t) do
|
||||
if isDictionaryKey(k, length) then table.insert(keys, k) end
|
||||
end
|
||||
table.sort(keys, sortKeys)
|
||||
return keys
|
||||
end
|
||||
|
||||
local function getToStringResultSafely(t, mt)
|
||||
local __tostring = type(mt) == 'table' and rawget(mt, '__tostring')
|
||||
local str, ok
|
||||
if type(__tostring) == 'function' then
|
||||
ok, str = pcall(__tostring, t)
|
||||
str = ok and str or 'error: ' .. tostring(str)
|
||||
end
|
||||
if type(str) == 'string' and #str > 0 then return str end
|
||||
end
|
||||
|
||||
local maxIdsMetaTable = {
|
||||
__index = function(self, typeName)
|
||||
rawset(self, typeName, 0)
|
||||
return 0
|
||||
end
|
||||
}
|
||||
|
||||
local idsMetaTable = {
|
||||
__index = function (self, typeName)
|
||||
local col = setmetatable({}, {__mode = "kv"})
|
||||
rawset(self, typeName, col)
|
||||
return col
|
||||
end
|
||||
}
|
||||
|
||||
local function countTableAppearances(t, tableAppearances)
|
||||
tableAppearances = tableAppearances or setmetatable({}, {__mode = "k"})
|
||||
|
||||
if type(t) == 'table' then
|
||||
if not tableAppearances[t] then
|
||||
tableAppearances[t] = 1
|
||||
for k,v in pairs(t) do
|
||||
countTableAppearances(k, tableAppearances)
|
||||
countTableAppearances(v, tableAppearances)
|
||||
end
|
||||
countTableAppearances(getmetatable(t), tableAppearances)
|
||||
else
|
||||
tableAppearances[t] = tableAppearances[t] + 1
|
||||
end
|
||||
end
|
||||
|
||||
return tableAppearances
|
||||
end
|
||||
|
||||
local function parse_filter(filter)
|
||||
if type(filter) == 'function' then return filter end
|
||||
-- not a function, so it must be a table or table-like
|
||||
filter = type(filter) == 'table' and filter or {filter}
|
||||
local dictionary = {}
|
||||
for _,v in pairs(filter) do dictionary[v] = true end
|
||||
return function(x) return dictionary[x] end
|
||||
end
|
||||
|
||||
local function makePath(path, key)
|
||||
local newPath, len = {}, #path
|
||||
for i=1, len do newPath[i] = path[i] end
|
||||
newPath[len+1] = key
|
||||
return newPath
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
function inspect(rootObject, options)
|
||||
options = options or {}
|
||||
local depth = options.depth or math.huge
|
||||
local filter = parse_filter(options.filter or {})
|
||||
|
||||
local tableAppearances = countTableAppearances(rootObject)
|
||||
|
||||
local buffer = {}
|
||||
local maxIds = setmetatable({}, maxIdsMetaTable)
|
||||
local ids = setmetatable({}, idsMetaTable)
|
||||
local level = 0
|
||||
local blen = 0 -- buffer length
|
||||
|
||||
local function puts(...)
|
||||
local args = {...}
|
||||
for i=1, #args do
|
||||
blen = blen + 1
|
||||
buffer[blen] = tostring(args[i])
|
||||
end
|
||||
end
|
||||
|
||||
local function down(f)
|
||||
level = level + 1
|
||||
f()
|
||||
level = level - 1
|
||||
end
|
||||
|
||||
local function tabify()
|
||||
puts("\n", string.rep(" ", level))
|
||||
end
|
||||
|
||||
local function commaControl(needsComma)
|
||||
if needsComma then puts(',') end
|
||||
return true
|
||||
end
|
||||
|
||||
local function alreadyVisited(v)
|
||||
return ids[type(v)][v] ~= nil
|
||||
end
|
||||
|
||||
local function getId(v)
|
||||
local tv = type(v)
|
||||
local id = ids[tv][v]
|
||||
if not id then
|
||||
id = maxIds[tv] + 1
|
||||
maxIds[tv] = id
|
||||
ids[tv][v] = id
|
||||
end
|
||||
return id
|
||||
end
|
||||
|
||||
local putValue -- forward declaration that needs to go before putTable & putKey
|
||||
|
||||
local function putKey(k)
|
||||
if isIdentifier(k) then return puts(k) end
|
||||
puts( "[" )
|
||||
putValue(k, {})
|
||||
puts("]")
|
||||
end
|
||||
|
||||
local function putTable(t, path)
|
||||
if alreadyVisited(t) then
|
||||
puts('<table ', getId(t), '>')
|
||||
elseif level >= depth then
|
||||
puts('{...}')
|
||||
else
|
||||
if tableAppearances[t] > 1 then puts('<', getId(t), '>') end
|
||||
|
||||
local dictKeys = getDictionaryKeys(t)
|
||||
local length = #t
|
||||
local mt = getmetatable(t)
|
||||
local to_string_result = getToStringResultSafely(t, mt)
|
||||
|
||||
puts('{')
|
||||
down(function()
|
||||
if to_string_result then
|
||||
puts(' -- ', escape(to_string_result))
|
||||
if length >= 1 then tabify() end -- tabify the array values
|
||||
end
|
||||
|
||||
local needsComma = false
|
||||
for i=1, length do
|
||||
needsComma = commaControl(needsComma)
|
||||
puts(' ')
|
||||
putValue(t[i], makePath(path, i))
|
||||
end
|
||||
|
||||
for _,k in ipairs(dictKeys) do
|
||||
needsComma = commaControl(needsComma)
|
||||
tabify()
|
||||
putKey(k)
|
||||
puts(' = ')
|
||||
putValue(t[k], makePath(path, k))
|
||||
end
|
||||
|
||||
if mt then
|
||||
needsComma = commaControl(needsComma)
|
||||
tabify()
|
||||
puts('<metatable> = ')
|
||||
putValue(mt, makePath(path, '<metatable>'))
|
||||
end
|
||||
end)
|
||||
|
||||
if #dictKeys > 0 or mt then -- dictionary table. Justify closing }
|
||||
tabify()
|
||||
elseif length > 0 then -- array tables have one extra space before closing }
|
||||
puts(' ')
|
||||
end
|
||||
|
||||
puts('}')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- putvalue is forward-declared before putTable & putKey
|
||||
putValue = function(v, path)
|
||||
if filter(v, path) then
|
||||
puts('<filtered>')
|
||||
else
|
||||
local tv = type(v)
|
||||
|
||||
if tv == 'string' then
|
||||
puts(smartQuote(escape(v)))
|
||||
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' then
|
||||
puts(tostring(v))
|
||||
elseif tv == 'table' then
|
||||
putTable(v, path)
|
||||
else
|
||||
puts('<',tv,' ',getId(v),'>')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
putValue(rootObject, {})
|
||||
|
||||
return table.concat(buffer)
|
||||
end
|
||||
|
||||
function printtable(name, table)
|
||||
print("table: ", name, inspect(table), "\n")
|
||||
end
|
||||
|
||||
function printstack()
|
||||
print(debug.traceback(), "\n")
|
||||
end
|
||||
136
Src/external_dependencies/openmpt-trunk/include/genie/src/base/io.lua
vendored
Normal file
136
Src/external_dependencies/openmpt-trunk/include/genie/src/base/io.lua
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
--
|
||||
-- io.lua
|
||||
-- Additions to the I/O namespace.
|
||||
-- Copyright (c) 2008-2009 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
io.eol = "\n"
|
||||
io.indent = "\t"
|
||||
io.indentLevel = 0
|
||||
|
||||
-- default escaper function
|
||||
local function _escaper(v) return v end
|
||||
_esc = _escaper
|
||||
|
||||
|
||||
--
|
||||
-- Prepare to capture the output from all subsequent calls to io.printf(),
|
||||
-- used for automated testing of the generators. Returns the previously
|
||||
-- captured text.
|
||||
--
|
||||
|
||||
function io.capture()
|
||||
local prev = io.captured
|
||||
io.captured = ''
|
||||
return prev
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Returns the captured text and stops capturing, optionally restoring a
|
||||
-- previous capture.
|
||||
--
|
||||
|
||||
function io.endcapture(restore)
|
||||
local captured = io.captured
|
||||
io.captured = restore
|
||||
return captured
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Open an overload of the io.open() function, which will create any missing
|
||||
-- subdirectories in the filename if "mode" is set to writeable.
|
||||
--
|
||||
|
||||
local builtin_open = io.open
|
||||
function io.open(fname, mode)
|
||||
if (mode) then
|
||||
if (mode:find("w")) then
|
||||
local dir = path.getdirectory(fname)
|
||||
ok, err = os.mkdir(dir)
|
||||
if (not ok) then
|
||||
error(err, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
return builtin_open(fname, mode)
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- A shortcut for printing formatted output to an output stream.
|
||||
--
|
||||
|
||||
function io.printf(msg, ...)
|
||||
local arg={...}
|
||||
if not io.eol then
|
||||
io.eol = "\n"
|
||||
end
|
||||
|
||||
if not io.indent then
|
||||
io.indent = "\t"
|
||||
end
|
||||
|
||||
if type(msg) == "number" then
|
||||
s = string.rep(io.indent, msg) .. string.format(table.unpack(arg))
|
||||
else
|
||||
s = string.format(msg, table.unpack(arg))
|
||||
end
|
||||
|
||||
if io.captured then
|
||||
io.captured = io.captured .. s .. io.eol
|
||||
else
|
||||
io.write(s)
|
||||
io.write(io.eol)
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Write a formatted string to the exported file, after passing all
|
||||
-- arguments (except for the first, which is the formatting string)
|
||||
-- through io.esc().
|
||||
--
|
||||
|
||||
function io.xprintf(msg, ...)
|
||||
local arg = {...}
|
||||
for i = 1, #arg do
|
||||
arg[i] = io.esc(arg[i])
|
||||
end
|
||||
io.printf(msg, unpack(arg))
|
||||
end
|
||||
|
||||
--
|
||||
-- Handle escaping of strings for various outputs
|
||||
--
|
||||
|
||||
function io.esc(value)
|
||||
if type(value) == "table" then
|
||||
local result = {}
|
||||
local n = #value
|
||||
for i = 1, n do
|
||||
table.insert(result, io.esc(value[i]))
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
return _esc(value or "")
|
||||
end
|
||||
|
||||
--
|
||||
-- Set a new string escaping function
|
||||
--
|
||||
|
||||
function io.escaper(func)
|
||||
_esc = func or _escaper
|
||||
end
|
||||
|
||||
--
|
||||
-- Because I use io.printf() so often in the generators, create a terse shortcut
|
||||
-- for it. This saves me typing, and also reduces the size of the executable.
|
||||
--
|
||||
|
||||
_p = io.printf
|
||||
_x = io.xprintf
|
||||
16
Src/external_dependencies/openmpt-trunk/include/genie/src/base/iter.lua
vendored
Normal file
16
Src/external_dependencies/openmpt-trunk/include/genie/src/base/iter.lua
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
iter = {}
|
||||
|
||||
-- sortByKeys iterates over the table where the keys are in sort order
|
||||
|
||||
function iter.sortByKeys(arr, f)
|
||||
local a = table.keys(arr)
|
||||
table.sort(a, f)
|
||||
|
||||
local i = 0
|
||||
return function()
|
||||
i = i + 1
|
||||
if a[i] ~= nil then
|
||||
return a[i], arr[a[i]]
|
||||
end
|
||||
end
|
||||
end
|
||||
113
Src/external_dependencies/openmpt-trunk/include/genie/src/base/option.lua
vendored
Normal file
113
Src/external_dependencies/openmpt-trunk/include/genie/src/base/option.lua
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
--
|
||||
-- option.lua
|
||||
-- Work with the list of registered options.
|
||||
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
premake.option = { }
|
||||
|
||||
|
||||
--
|
||||
-- The list of registered options.
|
||||
--
|
||||
|
||||
premake.option.list = { }
|
||||
|
||||
|
||||
--
|
||||
-- Register a new option.
|
||||
--
|
||||
-- @param opt
|
||||
-- The new option object.
|
||||
--
|
||||
|
||||
function premake.option.add(opt)
|
||||
-- some sanity checking
|
||||
local missing
|
||||
for _, field in ipairs({ "description", "trigger" }) do
|
||||
if (not opt[field]) then
|
||||
missing = field
|
||||
end
|
||||
end
|
||||
|
||||
if (missing) then
|
||||
error("option needs a " .. missing, 3)
|
||||
end
|
||||
|
||||
-- add it to the master list
|
||||
premake.option.list[opt.trigger] = opt
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve an option by name.
|
||||
--
|
||||
-- @param name
|
||||
-- The name of the option to retrieve.
|
||||
-- @returns
|
||||
-- The requested option, or nil if the option does not exist.
|
||||
--
|
||||
|
||||
function premake.option.get(name)
|
||||
return premake.option.list[name]
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Iterator for the list of options.
|
||||
--
|
||||
|
||||
function premake.option.each()
|
||||
-- sort the list by trigger
|
||||
local keys = { }
|
||||
for _, option in pairs(premake.option.list) do
|
||||
table.insert(keys, option.trigger)
|
||||
end
|
||||
table.sort(keys)
|
||||
|
||||
local i = 0
|
||||
return function()
|
||||
i = i + 1
|
||||
return premake.option.list[keys[i]]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Validate a list of user supplied key/value pairs against the list of registered options.
|
||||
--
|
||||
-- @param values
|
||||
-- The list of user supplied key/value pairs.
|
||||
-- @returns
|
||||
--- True if the list of pairs are valid, false and an error message otherwise.
|
||||
--
|
||||
|
||||
function premake.option.validate(values)
|
||||
for key, value in pairs(values) do
|
||||
-- does this option exist
|
||||
local opt = premake.option.get(key)
|
||||
if (not opt) then
|
||||
return false, "invalid option '" .. key .. "'"
|
||||
end
|
||||
|
||||
-- does it need a value?
|
||||
if (opt.value and value == "") then
|
||||
return false, "no value specified for option '" .. key .. "'"
|
||||
end
|
||||
|
||||
-- is the value allowed?
|
||||
if opt.allowed then
|
||||
local found = false
|
||||
for _, match in ipairs(opt.allowed) do
|
||||
if match[1] == value then
|
||||
found = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not found then
|
||||
return false, string.format("invalid value '%s' for option '%s'", value, key)
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
298
Src/external_dependencies/openmpt-trunk/include/genie/src/base/os.lua
vendored
Normal file
298
Src/external_dependencies/openmpt-trunk/include/genie/src/base/os.lua
vendored
Normal file
@@ -0,0 +1,298 @@
|
||||
--
|
||||
-- os.lua
|
||||
-- Additions to the OS namespace.
|
||||
-- Copyright (c) 2002-2011 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- Same as os.execute(), but accepts string formatting arguments.
|
||||
--
|
||||
|
||||
function os.executef(cmd, ...)
|
||||
local arg={...}
|
||||
cmd = string.format(cmd, table.unpack(arg))
|
||||
return os.execute(cmd)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Scan the well-known system locations for a particular library.
|
||||
--
|
||||
|
||||
local function parse_ld_so_conf(conf_file)
|
||||
-- Linux ldconfig file parser to find system library locations
|
||||
local first, last
|
||||
local dirs = { }
|
||||
local file = io.open(conf_file)
|
||||
-- Handle missing ld.so.conf (BSDs) gracefully
|
||||
if file == nil then
|
||||
return dirs
|
||||
end
|
||||
for line in file:lines() do
|
||||
-- ignore comments
|
||||
first = line:find("#", 1, true)
|
||||
if first ~= nil then
|
||||
line = line:sub(1, first - 1)
|
||||
end
|
||||
|
||||
if line ~= "" then
|
||||
-- check for include files
|
||||
first, last = line:find("include%s+")
|
||||
if first ~= nil then
|
||||
-- found include glob
|
||||
local include_glob = line:sub(last + 1)
|
||||
local includes = os.matchfiles(include_glob)
|
||||
for _, v in ipairs(includes) do
|
||||
dirs = table.join(dirs, parse_ld_so_conf(v))
|
||||
end
|
||||
else
|
||||
-- found an actual ld path entry
|
||||
table.insert(dirs, line)
|
||||
end
|
||||
end
|
||||
end
|
||||
return dirs
|
||||
end
|
||||
|
||||
function os.findlib(libname)
|
||||
local path, formats
|
||||
|
||||
-- assemble a search path, depending on the platform
|
||||
if os.is("windows") then
|
||||
formats = { "%s.dll", "%s" }
|
||||
path = os.getenv("PATH")
|
||||
else
|
||||
if os.is("macosx") then
|
||||
formats = { "lib%s.dylib", "%s.dylib" }
|
||||
path = os.getenv("DYLD_LIBRARY_PATH")
|
||||
else
|
||||
formats = { "lib%s.so", "%s.so" }
|
||||
path = os.getenv("LD_LIBRARY_PATH") or ""
|
||||
|
||||
for _, v in ipairs(parse_ld_so_conf("/etc/ld.so.conf")) do
|
||||
path = path .. ":" .. v
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(formats, "%s")
|
||||
path = path or ""
|
||||
if os.is64bit() then
|
||||
path = path .. ":/lib64:/usr/lib64/:usr/local/lib64"
|
||||
end
|
||||
path = path .. ":/lib:/usr/lib:/usr/local/lib"
|
||||
end
|
||||
|
||||
for _, fmt in ipairs(formats) do
|
||||
local name = string.format(fmt, libname)
|
||||
local result = os.pathsearch(name, path)
|
||||
if result then return result end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve the current operating system ID string.
|
||||
--
|
||||
|
||||
function os.get()
|
||||
return _OPTIONS.os or _OS
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Check the current operating system; may be set with the /os command line flag.
|
||||
--
|
||||
|
||||
function os.is(id)
|
||||
return (os.get():lower() == id:lower())
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Determine if the current system is running a 64-bit architecture
|
||||
--
|
||||
|
||||
local _64BitHostTypes = {
|
||||
"x86_64",
|
||||
"ia64",
|
||||
"amd64",
|
||||
"ppc64",
|
||||
"powerpc64",
|
||||
"sparc64",
|
||||
"arm64"
|
||||
}
|
||||
|
||||
function os.is64bit()
|
||||
-- Call the native code implementation. If this returns true then
|
||||
-- we're 64-bit, otherwise do more checking locally
|
||||
if (os._is64bit()) then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Identify the system
|
||||
local arch = ""
|
||||
if _OS == "windows" then
|
||||
arch = os.getenv("PROCESSOR_ARCHITECTURE")
|
||||
elseif _OS == "macosx" then
|
||||
arch = os.outputof("echo $HOSTTYPE")
|
||||
else
|
||||
arch = os.outputof("uname -m")
|
||||
end
|
||||
|
||||
if nil ~= arch then
|
||||
-- Check our known 64-bit identifiers
|
||||
arch = arch:lower()
|
||||
for _, hosttype in ipairs(_64BitHostTypes) do
|
||||
if arch:find(hosttype) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- The os.matchdirs() and os.matchfiles() functions
|
||||
--
|
||||
|
||||
local function domatch(result, mask, wantfiles)
|
||||
-- need to remove extraneous path info from the mask to ensure a match
|
||||
-- against the paths returned by the OS. Haven't come up with a good
|
||||
-- way to do it yet, so will handle cases as they come up
|
||||
if mask:startswith("./") then
|
||||
mask = mask:sub(3)
|
||||
end
|
||||
|
||||
-- strip off any leading directory information to find out
|
||||
-- where the search should take place
|
||||
local basedir = mask
|
||||
local starpos = mask:find("%*")
|
||||
if starpos then
|
||||
basedir = basedir:sub(1, starpos - 1)
|
||||
end
|
||||
basedir = path.getdirectory(basedir)
|
||||
if (basedir == ".") then basedir = "" end
|
||||
|
||||
-- recurse into subdirectories?
|
||||
local recurse = mask:find("**", nil, true)
|
||||
|
||||
-- convert mask to a Lua pattern
|
||||
mask = path.wildcards(mask)
|
||||
|
||||
local function matchwalker(basedir)
|
||||
local wildcard = path.join(basedir, "*")
|
||||
|
||||
-- retrieve files from OS and test against mask
|
||||
local m = os.matchstart(wildcard)
|
||||
while (os.matchnext(m)) do
|
||||
local isfile = os.matchisfile(m)
|
||||
if ((wantfiles and isfile) or (not wantfiles and not isfile)) then
|
||||
local fname = path.join(basedir, os.matchname(m))
|
||||
if fname:match(mask) == fname then
|
||||
table.insert(result, fname)
|
||||
end
|
||||
end
|
||||
end
|
||||
os.matchdone(m)
|
||||
|
||||
-- check subdirectories
|
||||
if recurse then
|
||||
m = os.matchstart(wildcard)
|
||||
while (os.matchnext(m)) do
|
||||
if not os.matchisfile(m) then
|
||||
local dirname = os.matchname(m)
|
||||
matchwalker(path.join(basedir, dirname))
|
||||
end
|
||||
end
|
||||
os.matchdone(m)
|
||||
end
|
||||
end
|
||||
|
||||
matchwalker(basedir)
|
||||
end
|
||||
|
||||
function os.matchdirs(...)
|
||||
local arg={...}
|
||||
local result = { }
|
||||
for _, mask in ipairs(arg) do
|
||||
domatch(result, mask, false)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function os.matchfiles(...)
|
||||
local arg={...}
|
||||
local result = { }
|
||||
for _, mask in ipairs(arg) do
|
||||
domatch(result, mask, true)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- An overload of the os.mkdir() function, which will create any missing
|
||||
-- subdirectories along the path.
|
||||
--
|
||||
|
||||
local builtin_mkdir = os.mkdir
|
||||
function os.mkdir(p)
|
||||
local dir = iif(p:startswith("/"), "/", "")
|
||||
for part in p:gmatch("[^/]+") do
|
||||
dir = dir .. part
|
||||
|
||||
if (part ~= "" and not path.isabsolute(part) and not os.isdir(dir)) then
|
||||
local ok, err = builtin_mkdir(dir)
|
||||
if (not ok) then
|
||||
return nil, err
|
||||
end
|
||||
end
|
||||
|
||||
dir = dir .. "/"
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Run a shell command and return the output.
|
||||
--
|
||||
|
||||
function os.outputof(cmd)
|
||||
local pipe = io.popen(cmd)
|
||||
local result = pipe:read('*a')
|
||||
pipe:close()
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Remove a directory, along with any contained files or subdirectories.
|
||||
--
|
||||
|
||||
local builtin_rmdir = os.rmdir
|
||||
function os.rmdir(p)
|
||||
-- recursively remove subdirectories
|
||||
local dirs = os.matchdirs(p .. "/*")
|
||||
for _, dname in ipairs(dirs) do
|
||||
os.rmdir(dname)
|
||||
end
|
||||
|
||||
-- remove any files
|
||||
local files = os.matchfiles(p .. "/*")
|
||||
for _, fname in ipairs(files) do
|
||||
os.remove(fname)
|
||||
end
|
||||
|
||||
-- remove this directory
|
||||
builtin_rmdir(p)
|
||||
end
|
||||
400
Src/external_dependencies/openmpt-trunk/include/genie/src/base/path.lua
vendored
Normal file
400
Src/external_dependencies/openmpt-trunk/include/genie/src/base/path.lua
vendored
Normal file
@@ -0,0 +1,400 @@
|
||||
--
|
||||
-- path.lua
|
||||
-- Path manipulation functions.
|
||||
-- Copyright (c) 2002-2010 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve the filename portion of a path, without any extension.
|
||||
--
|
||||
|
||||
function path.getbasename(p)
|
||||
local name = path.getname(p)
|
||||
local i = name:findlast(".", true)
|
||||
if (i) then
|
||||
return name:sub(1, i - 1)
|
||||
else
|
||||
return name
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Retrieve the path, without any extension.
|
||||
--
|
||||
|
||||
function path.removeext(name)
|
||||
local i = name:findlast(".", true)
|
||||
if (i) then
|
||||
return name:sub(1, i - 1)
|
||||
else
|
||||
return name
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Retrieve the directory portion of a path, or an empty string if
|
||||
-- the path does not include a directory.
|
||||
--
|
||||
|
||||
function path.getdirectory(p)
|
||||
local i = p:findlast("/", true)
|
||||
if (i) then
|
||||
if i > 1 then i = i - 1 end
|
||||
return p:sub(1, i)
|
||||
else
|
||||
return "."
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve the drive letter, if a Windows path.
|
||||
--
|
||||
|
||||
function path.getdrive(p)
|
||||
local ch1 = p:sub(1,1)
|
||||
local ch2 = p:sub(2,2)
|
||||
if ch2 == ":" then
|
||||
return ch1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve the file extension.
|
||||
--
|
||||
|
||||
function path.getextension(p)
|
||||
local i = p:findlast(".", true)
|
||||
if (i) then
|
||||
return p:sub(i)
|
||||
else
|
||||
return ""
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve the filename portion of a path.
|
||||
--
|
||||
|
||||
function path.getname(p)
|
||||
local i = p:findlast("[/\\]")
|
||||
if (i) then
|
||||
return p:sub(i + 1)
|
||||
else
|
||||
return p
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Returns the common base directory of two paths.
|
||||
--
|
||||
|
||||
function path.getcommonbasedir(a, b)
|
||||
a = path.getdirectory(a)..'/'
|
||||
b = path.getdirectory(b)..'/'
|
||||
|
||||
-- find the common leading directories
|
||||
local idx = 0
|
||||
while (true) do
|
||||
local tst = a:find('/', idx + 1, true)
|
||||
if tst then
|
||||
if a:sub(1,tst) == b:sub(1,tst) then
|
||||
idx = tst
|
||||
else
|
||||
break
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
-- idx is the index of the last sep before path string 'a' ran out or didn't match.
|
||||
local result = ''
|
||||
if idx > 1 then
|
||||
result = a:sub(1, idx - 1) -- Remove the trailing slash to be consistent with other functions.
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Returns true if the filename has a particular extension.
|
||||
--
|
||||
-- @param fname
|
||||
-- The file name to test.
|
||||
-- @param extensions
|
||||
-- The extension(s) to test. Maybe be a string or table.
|
||||
--
|
||||
|
||||
function path.hasextension(fname, extensions)
|
||||
local fext = path.getextension(fname):lower()
|
||||
if type(extensions) == "table" then
|
||||
for _, extension in pairs(extensions) do
|
||||
if fext == extension then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
else
|
||||
return (fext == extensions)
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Returns true if the filename represents a C/C++ source code file. This check
|
||||
-- is used to prevent passing non-code files to the compiler in makefiles. It is
|
||||
-- not foolproof, but it has held up well. I'm open to better suggestions.
|
||||
--
|
||||
|
||||
function path.iscfile(fname)
|
||||
return path.hasextension(fname, { ".c", ".m" })
|
||||
end
|
||||
|
||||
function path.iscppfile(fname)
|
||||
return path.hasextension(fname, { ".cc", ".cpp", ".cxx", ".c++", ".c", ".m", ".mm" })
|
||||
end
|
||||
|
||||
function path.iscxfile(fname)
|
||||
return path.hasextension(fname, ".cx")
|
||||
end
|
||||
|
||||
function path.isobjcfile(fname)
|
||||
return path.hasextension(fname, { ".m", ".mm" })
|
||||
end
|
||||
|
||||
function path.iscppheader(fname)
|
||||
return path.hasextension(fname, { ".h", ".hh", ".hpp", ".hxx" })
|
||||
end
|
||||
|
||||
function path.iscppmodule(fname)
|
||||
return path.hasextension(fname, { ".ixx", ".cppm" })
|
||||
end
|
||||
|
||||
function path.isappxmanifest(fname)
|
||||
return path.hasextension(fname, ".appxmanifest")
|
||||
end
|
||||
|
||||
function path.isandroidbuildfile(fname)
|
||||
return path.getname(fname) == "AndroidManifest.xml"
|
||||
end
|
||||
|
||||
function path.isnatvis(fname)
|
||||
return path.hasextension(fname, ".natvis")
|
||||
end
|
||||
|
||||
function path.isasmfile(fname)
|
||||
return path.hasextension(fname, { ".asm", ".s", ".S" })
|
||||
end
|
||||
|
||||
function path.isvalafile(fname)
|
||||
return path.hasextension(fname, ".vala")
|
||||
end
|
||||
|
||||
function path.isgresource(fname)
|
||||
local ending = ".gresource.xml"
|
||||
return ending == "" or fname:sub(-#ending) == ending
|
||||
end
|
||||
|
||||
function path.isswiftfile(fname)
|
||||
return path.hasextension(fname, ".swift")
|
||||
end
|
||||
|
||||
function path.issourcefile(fname)
|
||||
return path.iscfile(fname)
|
||||
or path.iscppfile(fname)
|
||||
or path.iscxfile(fname)
|
||||
or path.isasmfile(fname)
|
||||
or path.isvalafile(fname)
|
||||
or path.isswiftfile(fname)
|
||||
end
|
||||
|
||||
function path.issourcefilevs(fname)
|
||||
return path.hasextension(fname, { ".cc", ".cpp", ".cxx", ".c++", ".c" })
|
||||
or path.iscxfile(fname)
|
||||
or path.iscppmodule(fname)
|
||||
end
|
||||
|
||||
--
|
||||
-- Returns true if the filename represents a compiled object file. This check
|
||||
-- is used to support object files in the "files" list for archiving.
|
||||
--
|
||||
|
||||
function path.isobjectfile(fname)
|
||||
return path.hasextension(fname, { ".o", ".obj" })
|
||||
end
|
||||
|
||||
--
|
||||
-- Returns true if the filename represents a Windows resource file. This check
|
||||
-- is used to prevent passing non-resources to the compiler in makefiles.
|
||||
--
|
||||
|
||||
function path.isresourcefile(fname)
|
||||
return path.hasextension(fname, ".rc")
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Returns true if the filename represents a Windows image file.
|
||||
--
|
||||
|
||||
function path.isimagefile(fname)
|
||||
local extensions = { ".png" }
|
||||
local ext = path.getextension(fname):lower()
|
||||
return table.contains(extensions, ext)
|
||||
end
|
||||
|
||||
--
|
||||
-- Join one or more pieces of a path together into a single path.
|
||||
--
|
||||
-- @param ...
|
||||
-- One or more path strings.
|
||||
-- @return
|
||||
-- The joined path.
|
||||
--
|
||||
|
||||
function path.join(...)
|
||||
local arg={...}
|
||||
local numargs = select("#", ...)
|
||||
if numargs == 0 then
|
||||
return "";
|
||||
end
|
||||
|
||||
local allparts = {}
|
||||
for i = numargs, 1, -1 do
|
||||
local part = select(i, ...)
|
||||
if part and #part > 0 and part ~= "." then
|
||||
-- trim off trailing slashes
|
||||
while part:endswith("/") do
|
||||
part = part:sub(1, -2)
|
||||
end
|
||||
|
||||
table.insert(allparts, 1, part)
|
||||
if path.isabsolute(part) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(allparts, "/")
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Takes a path which is relative to one location and makes it relative
|
||||
-- to another location instead.
|
||||
--
|
||||
|
||||
function path.rebase(p, oldbase, newbase)
|
||||
p = path.getabsolute(path.join(oldbase, p))
|
||||
p = path.getrelative(newbase, p)
|
||||
return p
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Convert the separators in a path from one form to another. If `sep`
|
||||
-- is nil, then a platform-specific separator is used.
|
||||
--
|
||||
|
||||
function path.translate(p, sep)
|
||||
if (type(p) == "table") then
|
||||
local result = { }
|
||||
for _, value in ipairs(p) do
|
||||
table.insert(result, path.translate(value))
|
||||
end
|
||||
return result
|
||||
else
|
||||
if (not sep) then
|
||||
if (os.is("windows")) then
|
||||
sep = "\\"
|
||||
else
|
||||
sep = "/"
|
||||
end
|
||||
end
|
||||
local result = p:gsub("[/\\]", sep)
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Converts from a simple wildcard syntax, where * is "match any"
|
||||
-- and ** is "match recursive", to the corresponding Lua pattern.
|
||||
--
|
||||
-- @param pattern
|
||||
-- The wildcard pattern to convert.
|
||||
-- @returns
|
||||
-- The corresponding Lua pattern.
|
||||
--
|
||||
|
||||
function path.wildcards(pattern)
|
||||
-- Escape characters that have special meanings in Lua patterns
|
||||
pattern = pattern:gsub("([%+%.%-%^%$%(%)%%])", "%%%1")
|
||||
|
||||
-- Replace wildcard patterns with special placeholders so I don't
|
||||
-- have competing star replacements to worry about
|
||||
pattern = pattern:gsub("%*%*", "\001")
|
||||
pattern = pattern:gsub("%*", "\002")
|
||||
|
||||
-- Replace the placeholders with their Lua patterns
|
||||
pattern = pattern:gsub("\001", ".*")
|
||||
pattern = pattern:gsub("\002", "[^/]*")
|
||||
|
||||
return pattern
|
||||
end
|
||||
|
||||
--
|
||||
-- remove any dot ("./", "../") patterns from the start of the path
|
||||
--
|
||||
function path.trimdots(p)
|
||||
local changed
|
||||
repeat
|
||||
changed = true
|
||||
if p:startswith("./") then
|
||||
p = p:sub(3)
|
||||
elseif p:startswith("../") then
|
||||
p = p:sub(4)
|
||||
else
|
||||
changed = false
|
||||
end
|
||||
until not changed
|
||||
|
||||
return p
|
||||
end
|
||||
|
||||
--
|
||||
-- Takes a path which is relative to one location and makes it relative
|
||||
-- to another location instead.
|
||||
--
|
||||
|
||||
function path.rebase(p, oldbase, newbase)
|
||||
p = path.getabsolute(path.join(oldbase, p))
|
||||
p = path.getrelative(newbase, p)
|
||||
return p
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Replace the file extension.
|
||||
--
|
||||
|
||||
function path.replaceextension(p, newext)
|
||||
local ext = path.getextension(p)
|
||||
|
||||
if not ext then
|
||||
return p
|
||||
end
|
||||
|
||||
if #newext > 0 and not newext:findlast(".", true) then
|
||||
newext = "."..newext
|
||||
end
|
||||
|
||||
return p:match("^(.*)"..ext.."$")..newext
|
||||
end
|
||||
120
Src/external_dependencies/openmpt-trunk/include/genie/src/base/premake.lua
vendored
Normal file
120
Src/external_dependencies/openmpt-trunk/include/genie/src/base/premake.lua
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
--
|
||||
-- premake.lua
|
||||
-- High-level processing functions.
|
||||
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
premake._filelevelconfig = false
|
||||
premake._checkgenerate = true
|
||||
|
||||
--
|
||||
-- Open a file for output, and call a function to actually do the writing.
|
||||
-- Used by the actions to generate solution and project files.
|
||||
--
|
||||
-- @param obj
|
||||
-- A solution or project object; will be based to the callback function.
|
||||
-- @param filename
|
||||
-- The output filename; see the docs for premake.project.getfilename()
|
||||
-- for the expected format.
|
||||
-- @param callback
|
||||
-- The function responsible for writing the file, should take a solution
|
||||
-- or project as a parameters.
|
||||
--
|
||||
|
||||
function premake.generate(obj, filename, callback)
|
||||
local prev = io.capture()
|
||||
local abort = (callback(obj) == false)
|
||||
local new = io.endcapture(prev)
|
||||
|
||||
if abort then
|
||||
premake.stats.num_skipped = premake.stats.num_skipped + 1
|
||||
return
|
||||
end
|
||||
|
||||
filename = premake.project.getfilename(obj, filename)
|
||||
|
||||
if (premake._checkgenerate) then
|
||||
local delta = false
|
||||
|
||||
local f, err = io.open(filename, "rb")
|
||||
if (not f) then
|
||||
if string.find(err, "No such file or directory") then
|
||||
delta = true
|
||||
else
|
||||
error(err, 0)
|
||||
end
|
||||
else
|
||||
local existing = f:read("*all")
|
||||
if existing ~= new then
|
||||
delta = true
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
|
||||
if delta then
|
||||
printf("Generating %q", filename)
|
||||
local f, err = io.open(filename, "wb")
|
||||
if (not f) then
|
||||
error(err, 0)
|
||||
end
|
||||
|
||||
f:write(new)
|
||||
f:close()
|
||||
|
||||
premake.stats.num_generated = premake.stats.num_generated + 1
|
||||
else
|
||||
-- printf("Skipping %s as its contents would not change.", filename)
|
||||
premake.stats.num_skipped = premake.stats.num_skipped + 1
|
||||
end
|
||||
else
|
||||
printf("Generating %q", filename)
|
||||
|
||||
local f, err = io.open(filename, "wb")
|
||||
if (not f) then
|
||||
error(err, 0)
|
||||
end
|
||||
|
||||
f:write(new)
|
||||
f:close()
|
||||
premake.stats.num_generated = premake.stats.num_generated + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Finds a valid premake build file in the specified directory
|
||||
-- Used by both the main genie process, and include commands
|
||||
--
|
||||
-- @param dir
|
||||
-- The path in which to start looking for the script
|
||||
-- @param search_upwards
|
||||
-- When the script was not found in the specified directory, does the
|
||||
-- script need to look upwards in the file system
|
||||
--
|
||||
|
||||
function premake.findDefaultScript(dir, search_upwards)
|
||||
search_upwards = search_upwards or true
|
||||
|
||||
local last = ""
|
||||
while dir ~= last do
|
||||
for _, name in ipairs({ "genie.lua", "solution.lua", "premake4.lua" }) do
|
||||
|
||||
local script0 = dir .. "/" .. name
|
||||
if (os.isfile(script0)) then
|
||||
return dir, name
|
||||
end
|
||||
|
||||
local script1 = dir .. "/scripts/" .. name
|
||||
if (os.isfile(script1)) then
|
||||
return dir .. "/scripts/", name
|
||||
end
|
||||
end
|
||||
|
||||
last = dir
|
||||
dir = path.getabsolute(dir .. "/..")
|
||||
|
||||
if dir == "." or not search_upwards then break end
|
||||
end
|
||||
|
||||
return nil, nil
|
||||
end
|
||||
613
Src/external_dependencies/openmpt-trunk/include/genie/src/base/profiler.lua
vendored
Normal file
613
Src/external_dependencies/openmpt-trunk/include/genie/src/base/profiler.lua
vendored
Normal file
@@ -0,0 +1,613 @@
|
||||
--
|
||||
-- http://lua-users.org/wiki/PepperfishProfiler
|
||||
--
|
||||
-- == Introduction ==
|
||||
--
|
||||
-- Note that this requires os.clock(), debug.sethook(),
|
||||
-- and debug.getinfo() or your equivalent replacements to
|
||||
-- be available if this is an embedded application.
|
||||
--
|
||||
-- Example usage:
|
||||
--
|
||||
-- profiler = newProfiler()
|
||||
-- profiler:start()
|
||||
--
|
||||
-- < call some functions that take time >
|
||||
--
|
||||
-- profiler:stop()
|
||||
--
|
||||
-- local outfile = io.open( "profile.txt", "w+" )
|
||||
-- profiler:report( outfile )
|
||||
-- outfile:close()
|
||||
--
|
||||
-- == Optionally choosing profiling method ==
|
||||
--
|
||||
-- The rest of this comment can be ignored if you merely want a good profiler.
|
||||
--
|
||||
-- newProfiler(method, sampledelay):
|
||||
--
|
||||
-- If method is omitted or "time", will profile based on real performance.
|
||||
-- optionally, frequency can be provided to control the number of opcodes
|
||||
-- per profiling tick. By default this is 100000, which (on my system) provides
|
||||
-- one tick approximately every 2ms and reduces system performance by about 10%.
|
||||
-- This can be reduced to increase accuracy at the cost of performance, or
|
||||
-- increased for the opposite effect.
|
||||
--
|
||||
-- If method is "call", will profile based on function calls. Frequency is
|
||||
-- ignored.
|
||||
--
|
||||
--
|
||||
-- "time" may bias profiling somewhat towards large areas with "simple opcodes",
|
||||
-- as the profiling function (which introduces a certain amount of unavoidable
|
||||
-- overhead) will be called more often. This can be minimized by using a larger
|
||||
-- sample delay - the default should leave any error largely overshadowed by
|
||||
-- statistical noise. With a delay of 1000 I was able to achieve inaccuray of
|
||||
-- approximately 25%. Increasing the delay to 100000 left inaccuracy below my
|
||||
-- testing error.
|
||||
--
|
||||
-- "call" may bias profiling heavily towards areas with many function calls.
|
||||
-- Testing found a degenerate case giving a figure inaccurate by approximately
|
||||
-- 20,000%. (Yes, a multiple of 200.) This is, however, more directly comparable
|
||||
-- to common profilers (such as gprof) and also gives accurate function call
|
||||
-- counts, which cannot be retrieved from "time".
|
||||
--
|
||||
-- I strongly recommend "time" mode, and it is now the default.
|
||||
--
|
||||
-- == History ==
|
||||
--
|
||||
-- 2008-09-16 - Time-based profiling and conversion to Lua 5.1
|
||||
-- by Ben Wilhelm ( zorba-pepperfish@pavlovian.net ).
|
||||
-- Added the ability to optionally choose profiling methods, along with a new
|
||||
-- profiling method.
|
||||
--
|
||||
-- Converted to Lua 5, a few improvements, and
|
||||
-- additional documentation by Tom Spilman ( tom@sickheadgames.com )
|
||||
--
|
||||
-- Additional corrections and tidying by original author
|
||||
-- Daniel Silverstone ( dsilvers@pepperfish.net )
|
||||
--
|
||||
-- == Status ==
|
||||
--
|
||||
-- Daniel Silverstone is no longer using this code, and judging by how long it's
|
||||
-- been waiting for Lua 5.1 support, I don't think Tom Spilman is either. I'm
|
||||
-- perfectly willing to take on maintenance, so if you have problems or
|
||||
-- questions, go ahead and email me :)
|
||||
-- -- Ben Wilhelm ( zorba-pepperfish@pavlovian.net ) '
|
||||
--
|
||||
-- == Copyright ==
|
||||
--
|
||||
-- Lua profiler - Copyright Pepperfish 2002,2003,2004
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to
|
||||
-- deal in the Software without restriction, including without limitation the
|
||||
-- rights to use, copy, modify, merge, publish, distribute, and/or sell copies
|
||||
-- of the Software, and to permit persons to whom the Software is furnished to
|
||||
-- do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in
|
||||
-- all copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
-- IN THE SOFTWARE.
|
||||
--
|
||||
|
||||
--
|
||||
-- All profiler related stuff is stored in the top level table '_profiler'
|
||||
--
|
||||
_profiler = {}
|
||||
|
||||
|
||||
--
|
||||
-- newProfiler() creates a new profiler object for managing
|
||||
-- the profiler and storing state. Note that only one profiler
|
||||
-- object can be executing at one time.
|
||||
--
|
||||
function newProfiler(variant, sampledelay)
|
||||
if _profiler.running then
|
||||
print("Profiler already running.")
|
||||
return
|
||||
end
|
||||
|
||||
variant = variant or "time"
|
||||
|
||||
if variant ~= "time" and variant ~= "call" then
|
||||
print("Profiler method must be 'time' or 'call'.")
|
||||
return
|
||||
end
|
||||
|
||||
local newprof = {}
|
||||
for k,v in pairs(_profiler) do
|
||||
newprof[k] = v
|
||||
end
|
||||
newprof.variant = variant
|
||||
newprof.sampledelay = sampledelay or 100000
|
||||
return newprof
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- This function starts the profiler. It will do nothing
|
||||
-- if this (or any other) profiler is already running.
|
||||
--
|
||||
function _profiler.start(self)
|
||||
if _profiler.running then
|
||||
return
|
||||
end
|
||||
-- Start the profiler. This begins by setting up internal profiler state
|
||||
_profiler.running = self
|
||||
self.rawstats = {}
|
||||
self.callstack = {}
|
||||
if self.variant == "time" then
|
||||
self.lastclock = os.clock()
|
||||
debug.sethook( _profiler_hook_wrapper_by_time, "", self.sampledelay )
|
||||
elseif self.variant == "call" then
|
||||
debug.sethook( _profiler_hook_wrapper_by_call, "cr" )
|
||||
else
|
||||
print("Profiler method must be 'time' or 'call'.")
|
||||
sys.exit(1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- This function stops the profiler. It will do nothing
|
||||
-- if a profiler is not running, and nothing if it isn't
|
||||
-- the currently running profiler.
|
||||
--
|
||||
function _profiler.stop(self)
|
||||
if _profiler.running ~= self then
|
||||
return
|
||||
end
|
||||
-- Stop the profiler.
|
||||
debug.sethook( nil )
|
||||
_profiler.running = nil
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Simple wrapper to handle the hook. You should not
|
||||
-- be calling this directly. Duplicated to reduce overhead.
|
||||
--
|
||||
function _profiler_hook_wrapper_by_call(action)
|
||||
if _profiler.running == nil then
|
||||
debug.sethook( nil )
|
||||
end
|
||||
_profiler.running:_internal_profile_by_call(action)
|
||||
end
|
||||
function _profiler_hook_wrapper_by_time(action)
|
||||
if _profiler.running == nil then
|
||||
debug.sethook( nil )
|
||||
end
|
||||
_profiler.running:_internal_profile_by_time(action)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- This is the main by-function-call function of the profiler and should not
|
||||
-- be called except by the hook wrapper
|
||||
--
|
||||
function _profiler._internal_profile_by_call(self,action)
|
||||
-- Since we can obtain the 'function' for the item we've had call us, we
|
||||
-- can use that...
|
||||
local caller_info = debug.getinfo( 3 )
|
||||
if caller_info == nil then
|
||||
print "No caller_info"
|
||||
return
|
||||
end
|
||||
|
||||
--SHG_LOG("[_profiler._internal_profile] "..(caller_info.name or "<nil>"))
|
||||
|
||||
-- Retrieve the most recent activation record...
|
||||
local latest_ar = nil
|
||||
if table.getn(self.callstack) > 0 then
|
||||
latest_ar = self.callstack[table.getn(self.callstack)]
|
||||
end
|
||||
|
||||
-- Are we allowed to profile this function?
|
||||
local should_not_profile = 0
|
||||
for k,v in pairs(self.prevented_functions) do
|
||||
if k == caller_info.func then
|
||||
should_not_profile = v
|
||||
end
|
||||
end
|
||||
-- Also check the top activation record...
|
||||
if latest_ar then
|
||||
if latest_ar.should_not_profile == 2 then
|
||||
should_not_profile = 2
|
||||
end
|
||||
end
|
||||
|
||||
-- Now then, are we in 'call' or 'return' ?
|
||||
-- print("Profile:", caller_info.name, "SNP:", should_not_profile,
|
||||
-- "Action:", action )
|
||||
if action == "call" then
|
||||
-- Making a call...
|
||||
local this_ar = {}
|
||||
this_ar.should_not_profile = should_not_profile
|
||||
this_ar.parent_ar = latest_ar
|
||||
this_ar.anon_child = 0
|
||||
this_ar.name_child = 0
|
||||
this_ar.children = {}
|
||||
this_ar.children_time = {}
|
||||
this_ar.clock_start = os.clock()
|
||||
-- Last thing to do on a call is to insert this onto the ar stack...
|
||||
table.insert( self.callstack, this_ar )
|
||||
else
|
||||
local this_ar = latest_ar
|
||||
if this_ar == nil then
|
||||
return -- No point in doing anything if no upper activation record
|
||||
end
|
||||
|
||||
-- Right, calculate the time in this function...
|
||||
this_ar.clock_end = os.clock()
|
||||
this_ar.this_time = this_ar.clock_end - this_ar.clock_start
|
||||
|
||||
-- Now, if we have a parent, update its call info...
|
||||
if this_ar.parent_ar then
|
||||
this_ar.parent_ar.children[caller_info.func] =
|
||||
(this_ar.parent_ar.children[caller_info.func] or 0) + 1
|
||||
this_ar.parent_ar.children_time[caller_info.func] =
|
||||
(this_ar.parent_ar.children_time[caller_info.func] or 0 ) +
|
||||
this_ar.this_time
|
||||
if caller_info.name == nil then
|
||||
this_ar.parent_ar.anon_child =
|
||||
this_ar.parent_ar.anon_child + this_ar.this_time
|
||||
else
|
||||
this_ar.parent_ar.name_child =
|
||||
this_ar.parent_ar.name_child + this_ar.this_time
|
||||
end
|
||||
end
|
||||
-- Now if we're meant to record information about ourselves, do so...
|
||||
if this_ar.should_not_profile == 0 then
|
||||
local inforec = self:_get_func_rec(caller_info.func,1)
|
||||
inforec.count = inforec.count + 1
|
||||
inforec.time = inforec.time + this_ar.this_time
|
||||
inforec.anon_child_time = inforec.anon_child_time + this_ar.anon_child
|
||||
inforec.name_child_time = inforec.name_child_time + this_ar.name_child
|
||||
inforec.func_info = caller_info
|
||||
for k,v in pairs(this_ar.children) do
|
||||
inforec.children[k] = (inforec.children[k] or 0) + v
|
||||
inforec.children_time[k] =
|
||||
(inforec.children_time[k] or 0) + this_ar.children_time[k]
|
||||
end
|
||||
end
|
||||
|
||||
-- Last thing to do on return is to drop the last activation record...
|
||||
table.remove( self.callstack, table.getn( self.callstack ) )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- This is the main by-time internal function of the profiler and should not
|
||||
-- be called except by the hook wrapper
|
||||
--
|
||||
function _profiler._internal_profile_by_time(self,action)
|
||||
-- we do this first so we add the minimum amount of extra time to this call
|
||||
local timetaken = os.clock() - self.lastclock
|
||||
|
||||
local depth = 3
|
||||
local at_top = true
|
||||
local last_caller
|
||||
local caller = debug.getinfo(depth)
|
||||
while caller do
|
||||
if not caller.func then caller.func = "(tail call)" end
|
||||
if self.prevented_functions[caller.func] == nil then
|
||||
local info = self:_get_func_rec(caller.func, 1, caller)
|
||||
info.count = info.count + 1
|
||||
info.time = info.time + timetaken
|
||||
if last_caller then
|
||||
-- we're not the head, so update the "children" times also
|
||||
if last_caller.name then
|
||||
info.name_child_time = info.name_child_time + timetaken
|
||||
else
|
||||
info.anon_child_time = info.anon_child_time + timetaken
|
||||
end
|
||||
info.children[last_caller.func] =
|
||||
(info.children[last_caller.func] or 0) + 1
|
||||
info.children_time[last_caller.func] =
|
||||
(info.children_time[last_caller.func] or 0) + timetaken
|
||||
end
|
||||
end
|
||||
depth = depth + 1
|
||||
last_caller = caller
|
||||
caller = debug.getinfo(depth)
|
||||
end
|
||||
|
||||
self.lastclock = os.clock()
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- This returns a (possibly empty) function record for
|
||||
-- the specified function. It is for internal profiler use.
|
||||
--
|
||||
function _profiler._get_func_rec(self,func,force,info)
|
||||
-- Find the function ref for 'func' (if force and not present, create one)
|
||||
local ret = self.rawstats[func]
|
||||
if ret == nil and force ~= 1 then
|
||||
return nil
|
||||
end
|
||||
if ret == nil then
|
||||
-- Build a new function statistics table
|
||||
ret = {}
|
||||
ret.func = func
|
||||
ret.count = 0
|
||||
ret.time = 0
|
||||
ret.anon_child_time = 0
|
||||
ret.name_child_time = 0
|
||||
ret.children = {}
|
||||
ret.children_time = {}
|
||||
ret.func_info = info
|
||||
self.rawstats[func] = ret
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- This writes a profile report to the output file object. If
|
||||
-- sort_by_total_time is nil or false the output is sorted by
|
||||
-- the function time minus the time in it's children.
|
||||
--
|
||||
function _profiler.report( self, outfile, sort_by_total_time )
|
||||
|
||||
outfile:write
|
||||
[[Lua Profile output created by profiler.lua. Copyright Pepperfish 2002+
|
||||
|
||||
]]
|
||||
|
||||
-- This is pretty awful.
|
||||
local terms = {}
|
||||
if self.variant == "time" then
|
||||
terms.capitalized = "Sample"
|
||||
terms.single = "sample"
|
||||
terms.pastverb = "sampled"
|
||||
elseif self.variant == "call" then
|
||||
terms.capitalized = "Call"
|
||||
terms.single = "call"
|
||||
terms.pastverb = "called"
|
||||
else
|
||||
assert(false)
|
||||
end
|
||||
|
||||
local total_time = 0
|
||||
local ordering = {}
|
||||
for func,record in pairs(self.rawstats) do
|
||||
table.insert(ordering, func)
|
||||
end
|
||||
|
||||
if sort_by_total_time then
|
||||
table.sort( ordering,
|
||||
function(a,b) return self.rawstats[a].time > self.rawstats[b].time end
|
||||
)
|
||||
else
|
||||
table.sort( ordering,
|
||||
function(a,b)
|
||||
local arec = self.rawstats[a]
|
||||
local brec = self.rawstats[b]
|
||||
local atime = arec.time - (arec.anon_child_time + arec.name_child_time)
|
||||
local btime = brec.time - (brec.anon_child_time + brec.name_child_time)
|
||||
return atime > btime
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
for i=1,#ordering do
|
||||
local func = ordering[i]
|
||||
local record = self.rawstats[func]
|
||||
local thisfuncname = " " .. self:_pretty_name(func) .. " "
|
||||
if string.len( thisfuncname ) < 42 then
|
||||
thisfuncname = string.rep( "-", math.floor((42 - string.len(thisfuncname))/2) ) .. thisfuncname
|
||||
thisfuncname = thisfuncname .. string.rep( "-", 42 - string.len(thisfuncname) )
|
||||
end
|
||||
|
||||
total_time = total_time + ( record.time - ( record.anon_child_time +
|
||||
record.name_child_time ) )
|
||||
outfile:write( string.rep( "-", 19 ) .. thisfuncname ..
|
||||
string.rep( "-", 19 ) .. "\n" )
|
||||
outfile:write( terms.capitalized.." count: " ..
|
||||
string.format( "%4d", record.count ) .. "\n" )
|
||||
outfile:write( "Time spend total: " ..
|
||||
string.format( "%4.3f", record.time ) .. "s\n" )
|
||||
outfile:write( "Time spent in children: " ..
|
||||
string.format("%4.3f",record.anon_child_time+record.name_child_time) ..
|
||||
"s\n" )
|
||||
local timeinself =
|
||||
record.time - (record.anon_child_time + record.name_child_time)
|
||||
outfile:write( "Time spent in self: " ..
|
||||
string.format("%4.3f", timeinself) .. "s\n" )
|
||||
outfile:write( "Time spent per " .. terms.single .. ": " ..
|
||||
string.format("%4.5f", record.time/record.count) ..
|
||||
"s/" .. terms.single .. "\n" )
|
||||
outfile:write( "Time spent in self per "..terms.single..": " ..
|
||||
string.format( "%4.5f", timeinself/record.count ) .. "s/" ..
|
||||
terms.single.."\n" )
|
||||
|
||||
-- Report on each child in the form
|
||||
-- Child <funcname> called n times and took a.bs
|
||||
local added_blank = 0
|
||||
for k,v in pairs(record.children) do
|
||||
if self.prevented_functions[k] == nil or
|
||||
self.prevented_functions[k] == 0
|
||||
then
|
||||
if added_blank == 0 then
|
||||
outfile:write( "\n" ) -- extra separation line
|
||||
added_blank = 1
|
||||
end
|
||||
outfile:write( "Child " .. self:_pretty_name(k) ..
|
||||
string.rep( " ", 41-string.len(self:_pretty_name(k)) ) .. " " ..
|
||||
terms.pastverb.." " .. string.format("%6d", v) )
|
||||
outfile:write( " times. Took " ..
|
||||
string.format("%4.2f", record.children_time[k] ) .. "s\n" )
|
||||
end
|
||||
end
|
||||
|
||||
outfile:write( "\n" ) -- extra separation line
|
||||
outfile:flush()
|
||||
end
|
||||
outfile:write( "\n\n" )
|
||||
outfile:write( "Total time spent in profiled functions: " ..
|
||||
string.format("%5.3g",total_time) .. "s\n" )
|
||||
outfile:write( [[
|
||||
|
||||
END
|
||||
]] )
|
||||
outfile:flush()
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- This writes the profile to the output file object as
|
||||
-- loadable Lua source.
|
||||
--
|
||||
function _profiler.lua_report(self,outfile)
|
||||
-- Purpose: Write out the entire raw state in a cross-referenceable form.
|
||||
local ordering = {}
|
||||
local functonum = {}
|
||||
for func,record in pairs(self.rawstats) do
|
||||
table.insert(ordering, func)
|
||||
functonum[func] = table.getn(ordering)
|
||||
end
|
||||
|
||||
outfile:write(
|
||||
"-- Profile generated by profiler.lua Copyright Pepperfish 2002+\n\n" )
|
||||
outfile:write( "-- Function names\nfuncnames = {}\n" )
|
||||
for i=1,table.getn(ordering) do
|
||||
local thisfunc = ordering[i]
|
||||
outfile:write( "funcnames[" .. i .. "] = " ..
|
||||
string.format("%q", self:_pretty_name(thisfunc)) .. "\n" )
|
||||
end
|
||||
outfile:write( "\n" )
|
||||
outfile:write( "-- Function times\nfunctimes = {}\n" )
|
||||
for i=1,table.getn(ordering) do
|
||||
local thisfunc = ordering[i]
|
||||
local record = self.rawstats[thisfunc]
|
||||
outfile:write( "functimes[" .. i .. "] = { " )
|
||||
outfile:write( "tot=" .. record.time .. ", " )
|
||||
outfile:write( "achild=" .. record.anon_child_time .. ", " )
|
||||
outfile:write( "nchild=" .. record.name_child_time .. ", " )
|
||||
outfile:write( "count=" .. record.count .. " }\n" )
|
||||
end
|
||||
outfile:write( "\n" )
|
||||
outfile:write( "-- Child links\nchildren = {}\n" )
|
||||
for i=1,table.getn(ordering) do
|
||||
local thisfunc = ordering[i]
|
||||
local record = self.rawstats[thisfunc]
|
||||
outfile:write( "children[" .. i .. "] = { " )
|
||||
for k,v in pairs(record.children) do
|
||||
if functonum[k] then -- non-recorded functions will be ignored now
|
||||
outfile:write( functonum[k] .. ", " )
|
||||
end
|
||||
end
|
||||
outfile:write( "}\n" )
|
||||
end
|
||||
outfile:write( "\n" )
|
||||
outfile:write( "-- Child call counts\nchildcounts = {}\n" )
|
||||
for i=1,table.getn(ordering) do
|
||||
local thisfunc = ordering[i]
|
||||
local record = self.rawstats[thisfunc]
|
||||
outfile:write( "children[" .. i .. "] = { " )
|
||||
for k,v in record.children do
|
||||
if functonum[k] then -- non-recorded functions will be ignored now
|
||||
outfile:write( v .. ", " )
|
||||
end
|
||||
end
|
||||
outfile:write( "}\n" )
|
||||
end
|
||||
outfile:write( "\n" )
|
||||
outfile:write( "-- Child call time\nchildtimes = {}\n" )
|
||||
for i=1,table.getn(ordering) do
|
||||
local thisfunc = ordering[i]
|
||||
local record = self.rawstats[thisfunc];
|
||||
outfile:write( "children[" .. i .. "] = { " )
|
||||
for k,v in pairs(record.children) do
|
||||
if functonum[k] then -- non-recorded functions will be ignored now
|
||||
outfile:write( record.children_time[k] .. ", " )
|
||||
end
|
||||
end
|
||||
outfile:write( "}\n" )
|
||||
end
|
||||
outfile:write( "\n\n-- That is all.\n\n" )
|
||||
outfile:flush()
|
||||
end
|
||||
|
||||
-- Internal function to calculate a pretty name for the profile output
|
||||
function _profiler._pretty_name(self,func)
|
||||
|
||||
-- Only the data collected during the actual
|
||||
-- run seems to be correct.... why?
|
||||
local info = self.rawstats[ func ].func_info
|
||||
-- local info = debug.getinfo( func )
|
||||
|
||||
local name = ""
|
||||
if info.what == "Lua" then
|
||||
name = "L:"
|
||||
end
|
||||
if info.what == "C" then
|
||||
name = "C:"
|
||||
end
|
||||
if info.what == "main" then
|
||||
name = " :"
|
||||
end
|
||||
|
||||
if info.name == nil then
|
||||
name = name .. "<"..tostring(func) .. ">"
|
||||
else
|
||||
name = name .. info.name
|
||||
end
|
||||
|
||||
if info.source then
|
||||
name = name
|
||||
else
|
||||
if info.what == "C" then
|
||||
name = name .. "@?"
|
||||
else
|
||||
name = name .. "@<string>"
|
||||
end
|
||||
end
|
||||
name = name .. ":"
|
||||
if info.what == "C" then
|
||||
name = name .. "?"
|
||||
else
|
||||
name = name .. info.linedefined
|
||||
end
|
||||
|
||||
return name
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- This allows you to specify functions which you do
|
||||
-- not want profiled. Setting level to 1 keeps the
|
||||
-- function from being profiled. Setting level to 2
|
||||
-- keeps both the function and its children from
|
||||
-- being profiled.
|
||||
--
|
||||
-- BUG: 2 will probably act exactly like 1 in "time" mode.
|
||||
-- If anyone cares, let me (zorba) know and it can be fixed.
|
||||
--
|
||||
function _profiler.prevent(self, func, level)
|
||||
self.prevented_functions[func] = (level or 1)
|
||||
end
|
||||
|
||||
|
||||
_profiler.prevented_functions = {
|
||||
[_profiler.start] = 2,
|
||||
[_profiler.stop] = 2,
|
||||
[_profiler._internal_profile_by_time] = 2,
|
||||
[_profiler._internal_profile_by_call] = 2,
|
||||
[_profiler_hook_wrapper_by_time] = 2,
|
||||
[_profiler_hook_wrapper_by_call] = 2,
|
||||
[_profiler.prevent] = 2,
|
||||
[_profiler._get_func_rec] = 2,
|
||||
[_profiler.report] = 2,
|
||||
[_profiler.lua_report] = 2,
|
||||
[_profiler._pretty_name] = 2
|
||||
}
|
||||
775
Src/external_dependencies/openmpt-trunk/include/genie/src/base/project.lua
vendored
Normal file
775
Src/external_dependencies/openmpt-trunk/include/genie/src/base/project.lua
vendored
Normal file
@@ -0,0 +1,775 @@
|
||||
--
|
||||
-- project.lua
|
||||
-- Functions for working with the project data.
|
||||
-- Copyright (c) 2002 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
premake.project = { }
|
||||
|
||||
|
||||
--
|
||||
-- Create a tree from a project's list of files, representing the filesystem hierarchy.
|
||||
--
|
||||
-- @param prj
|
||||
-- The project containing the files to map.
|
||||
-- @returns
|
||||
-- A new tree object containing a corresponding filesystem hierarchy. The root node
|
||||
-- contains a reference back to the original project: prj = tr.project.
|
||||
--
|
||||
|
||||
function premake.project.buildsourcetree(prj, allfiles)
|
||||
local tr = premake.tree.new(prj.name)
|
||||
tr.project = prj
|
||||
|
||||
local isvpath
|
||||
|
||||
local function onadd(node)
|
||||
node.isvpath = isvpath
|
||||
end
|
||||
|
||||
for fcfg in premake.project.eachfile(prj, allfiles) do
|
||||
isvpath = (fcfg.name ~= fcfg.vpath)
|
||||
local node = premake.tree.add(tr, fcfg.vpath, onadd)
|
||||
node.cfg = fcfg
|
||||
end
|
||||
|
||||
premake.tree.sort(tr)
|
||||
return tr
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Returns an iterator for a set of build configuration settings. If a platform is
|
||||
-- specified, settings specific to that platform and build configuration pair are
|
||||
-- returned.
|
||||
--
|
||||
|
||||
function premake.eachconfig(prj, platform)
|
||||
-- I probably have the project root config, rather than the actual project
|
||||
if prj.project then prj = prj.project end
|
||||
|
||||
local cfgs = prj.solution.configurations
|
||||
local i = 0
|
||||
|
||||
return function ()
|
||||
i = i + 1
|
||||
if i <= #cfgs then
|
||||
return premake.getconfig(prj, cfgs[i], platform)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Iterator for a project's files; returns a file configuration object.
|
||||
--
|
||||
|
||||
function premake.project.eachfile(prj, allfiles)
|
||||
-- project root config contains the file config list
|
||||
if not prj.project then prj = premake.getconfig(prj) end
|
||||
local i = 0
|
||||
local t = iif(allfiles, prj.allfiles, prj.files)
|
||||
local c = iif(allfiles, prj.__allfileconfigs, prj.__fileconfigs)
|
||||
return function ()
|
||||
i = i + 1
|
||||
if (i <= #t) then
|
||||
local fcfg = c[t[i]]
|
||||
fcfg.vpath = premake.project.getvpath(prj, fcfg.name)
|
||||
return fcfg
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Apply XML escaping to a value.
|
||||
--
|
||||
|
||||
function premake.esc(value)
|
||||
if (type(value) == "table") then
|
||||
local result = { }
|
||||
for _,v in ipairs(value) do
|
||||
table.insert(result, premake.esc(v))
|
||||
end
|
||||
return result
|
||||
else
|
||||
value = value:gsub('&', "&")
|
||||
value = value:gsub('"', """)
|
||||
value = value:gsub("'", "'")
|
||||
value = value:gsub('<', "<")
|
||||
value = value:gsub('>', ">")
|
||||
value = value:gsub('\r', "
")
|
||||
value = value:gsub('\n', "
")
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Given a map of supported platform identifiers, filters the solution's list
|
||||
-- of platforms to match. A map takes the form of a table like:
|
||||
--
|
||||
-- { x32 = "Win32", x64 = "x64" }
|
||||
--
|
||||
-- Only platforms that are listed in both the solution and the map will be
|
||||
-- included in the results. An optional default platform may also be specified;
|
||||
-- if the result set would otherwise be empty this platform will be used.
|
||||
--
|
||||
|
||||
function premake.filterplatforms(sln, map, default)
|
||||
local result = { }
|
||||
local keys = { }
|
||||
if sln.platforms then
|
||||
for _, p in ipairs(sln.platforms) do
|
||||
if map[p] and not table.contains(keys, map[p]) then
|
||||
table.insert(result, p)
|
||||
table.insert(keys, map[p])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #result == 0 and default then
|
||||
table.insert(result, default)
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Locate a project by name; case insensitive.
|
||||
--
|
||||
|
||||
function premake.findproject(name)
|
||||
for sln in premake.solution.each() do
|
||||
for prj in premake.solution.eachproject(sln) do
|
||||
if (prj.name == name) then
|
||||
return prj
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Locate a file in a project with a given extension; used to locate "special"
|
||||
-- items such as Windows .def files.
|
||||
--
|
||||
|
||||
function premake.findfile(prj, extension)
|
||||
for _, fname in ipairs(prj.files) do
|
||||
if fname:endswith(extension) then return fname end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve a configuration for a given project/configuration pairing.
|
||||
-- @param prj
|
||||
-- The project to query.
|
||||
-- @param cfgname
|
||||
-- The target build configuration; only settings applicable to this configuration
|
||||
-- will be returned. May be nil to retrieve project-wide settings.
|
||||
-- @param pltname
|
||||
-- The target platform; only settings applicable to this platform will be returned.
|
||||
-- May be nil to retrieve platform-independent settings.
|
||||
-- @returns
|
||||
-- A configuration object containing all the settings for the given platform/build
|
||||
-- configuration pair.
|
||||
--
|
||||
|
||||
function premake.getconfig(prj, cfgname, pltname)
|
||||
-- might have the root configuration, rather than the actual project
|
||||
prj = prj.project or prj
|
||||
|
||||
-- if platform is not included in the solution, use general settings instead
|
||||
if pltname == "Native" or not table.contains(prj.solution.platforms or {}, pltname) then
|
||||
pltname = nil
|
||||
end
|
||||
|
||||
local key = (cfgname or "")
|
||||
if pltname then key = key .. pltname end
|
||||
return prj.__configs[key]
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Build a name from a build configuration/platform pair. The short name
|
||||
-- is good for makefiles or anywhere a user will have to type it in. The
|
||||
-- long name is more readable.
|
||||
--
|
||||
|
||||
function premake.getconfigname(cfgname, platform, useshortname)
|
||||
if cfgname then
|
||||
local name = cfgname
|
||||
if platform and platform ~= "Native" then
|
||||
if useshortname then
|
||||
name = name .. premake.platforms[platform].cfgsuffix
|
||||
else
|
||||
name = name .. "|" .. platform
|
||||
end
|
||||
end
|
||||
return iif(useshortname, name:lower(), name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Returns a list of sibling projects on which the specified project depends.
|
||||
-- This is used to list dependencies within a solution or workspace. Must
|
||||
-- consider all configurations because Visual Studio does not support per-config
|
||||
-- project dependencies.
|
||||
--
|
||||
-- @param prj
|
||||
-- The project to query.
|
||||
-- @returns
|
||||
-- A list of dependent projects, as an array of objects.
|
||||
--
|
||||
|
||||
function premake.getdependencies(prj)
|
||||
-- make sure I've got the project and not root config
|
||||
prj = prj.project or prj
|
||||
|
||||
local results = { }
|
||||
for _, cfg in pairs(prj.__configs) do
|
||||
for _, link in ipairs(cfg.links) do
|
||||
local dep = premake.findproject(link)
|
||||
if dep and not table.contains(results, dep) then
|
||||
table.insert(results, dep)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return results
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Uses a pattern to format the basename of a file (i.e. without path).
|
||||
--
|
||||
-- @param prjname
|
||||
-- A project name (string) to use.
|
||||
-- @param pattern
|
||||
-- A naming pattern. The sequence "%%" will be replaced by the
|
||||
-- project name.
|
||||
-- @returns
|
||||
-- A filename (basename only) matching the specified pattern, without
|
||||
-- path components.
|
||||
--
|
||||
|
||||
function premake.project.getbasename(prjname, pattern)
|
||||
return pattern:gsub("%%%%", prjname)
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Uses information from a project (or solution) to format a filename.
|
||||
--
|
||||
-- @param prj
|
||||
-- A project or solution object with the file naming information.
|
||||
-- @param pattern
|
||||
-- A naming pattern. The sequence "%%" will be replaced by the
|
||||
-- project name.
|
||||
-- @returns
|
||||
-- A filename matching the specified pattern, with a relative path
|
||||
-- from the current directory to the project location.
|
||||
--
|
||||
|
||||
function premake.project.getfilename(prj, pattern)
|
||||
local fname = premake.project.getbasename(prj.name, pattern)
|
||||
fname = path.join(prj.location, fname)
|
||||
return path.getrelative(os.getcwd(), fname)
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Returns a list of link targets. Kind may be one of:
|
||||
-- siblings - linkable sibling projects
|
||||
-- system - system (non-sibling) libraries
|
||||
-- dependencies - all sibling dependencies, including non-linkable
|
||||
-- all - return everything
|
||||
--
|
||||
-- Part may be one of:
|
||||
-- name - the decorated library name with no directory
|
||||
-- basename - the undecorated library name
|
||||
-- directory - just the directory, no name
|
||||
-- fullpath - full path with decorated name
|
||||
-- object - return the project object of the dependency
|
||||
--
|
||||
|
||||
function premake.getlinks(cfg, kind, part)
|
||||
-- if I'm building a list of link directories, include libdirs
|
||||
local result = iif (part == "directory" and kind == "all", cfg.libdirs, {})
|
||||
|
||||
-- am I getting links for a configuration or a project?
|
||||
local cfgname = iif(cfg.name == cfg.project.name, "", cfg.name)
|
||||
|
||||
-- how should files be named?
|
||||
local pathstyle = premake.getpathstyle(cfg)
|
||||
local namestyle = premake.getnamestyle(cfg)
|
||||
|
||||
local function canlink(source, target)
|
||||
if (target.kind ~= "SharedLib" and target.kind ~= "StaticLib") then
|
||||
return false
|
||||
end
|
||||
if premake.iscppproject(source) then
|
||||
return premake.iscppproject(target)
|
||||
elseif premake.isdotnetproject(source) then
|
||||
return premake.isdotnetproject(target)
|
||||
elseif premake.isswiftproject(source) then
|
||||
return premake.isswiftproject(source) or premake.iscppproject(source)
|
||||
end
|
||||
end
|
||||
|
||||
for _, link in ipairs(cfg.links) do
|
||||
local item
|
||||
|
||||
-- is this a sibling project?
|
||||
local prj = premake.findproject(link)
|
||||
if prj and kind ~= "system" then
|
||||
|
||||
local prjcfg = premake.getconfig(prj, cfgname, cfg.platform)
|
||||
if kind == "dependencies" or canlink(cfg, prjcfg) then
|
||||
if (part == "directory") then
|
||||
item = path.rebase(prjcfg.linktarget.directory, prjcfg.location, cfg.location)
|
||||
elseif (part == "basename") then
|
||||
item = prjcfg.linktarget.basename
|
||||
elseif (part == "fullpath") then
|
||||
item = path.rebase(prjcfg.linktarget.fullpath, prjcfg.location, cfg.location)
|
||||
elseif (part == "object") then
|
||||
item = prjcfg
|
||||
end
|
||||
end
|
||||
|
||||
elseif not prj and (kind == "system" or kind == "all") then
|
||||
|
||||
if (part == "directory") then
|
||||
item = path.getdirectory(link)
|
||||
elseif (part == "fullpath") then
|
||||
item = link
|
||||
if namestyle == "windows" then
|
||||
if premake.iscppproject(cfg) then
|
||||
item = item .. ".lib"
|
||||
elseif premake.isdotnetproject(cfg) then
|
||||
item = item .. ".dll"
|
||||
end
|
||||
end
|
||||
elseif part == "name" then
|
||||
item = path.getname(link)
|
||||
elseif part == "basename" then
|
||||
item = path.getbasename(link)
|
||||
else
|
||||
item = link
|
||||
end
|
||||
|
||||
if item:find("/", nil, true) then
|
||||
item = path.getrelative(cfg.project.location, item)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if item then
|
||||
if pathstyle == "windows" and part ~= "object" then
|
||||
item = path.translate(item, "\\")
|
||||
end
|
||||
if not table.contains(result, item) then
|
||||
table.insert(result, item)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Gets the name style for a configuration, indicating what kind of prefix,
|
||||
-- extensions, etc. should be used in target file names.
|
||||
--
|
||||
-- @param cfg
|
||||
-- The configuration to check.
|
||||
-- @returns
|
||||
-- The target naming style, one of "windows", "posix", or "PS3".
|
||||
--
|
||||
|
||||
function premake.getnamestyle(cfg)
|
||||
return premake.platforms[cfg.platform].namestyle or premake.gettool(cfg).namestyle or "posix"
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Gets the path style for a configuration, indicating what kind of path separator
|
||||
-- should be used in target file names.
|
||||
--
|
||||
-- @param cfg
|
||||
-- The configuration to check.
|
||||
-- @returns
|
||||
-- The target path style, one of "windows" or "posix".
|
||||
--
|
||||
|
||||
function premake.getpathstyle(cfg)
|
||||
if premake.action.current().os == "windows" then
|
||||
return "windows"
|
||||
else
|
||||
return "posix"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Assembles a target for a particular tool/system/configuration.
|
||||
--
|
||||
-- @param cfg
|
||||
-- The configuration to be targeted.
|
||||
-- @param direction
|
||||
-- One of 'build' for the build target, or 'link' for the linking target.
|
||||
-- @param pathstyle
|
||||
-- The path format, one of "windows" or "posix". This comes from the current
|
||||
-- action: Visual Studio uses "windows", GMake uses "posix", etc.
|
||||
-- @param namestyle
|
||||
-- The file naming style, one of "windows" or "posix". This comes from the
|
||||
-- current tool: GCC uses "posix", MSC uses "windows", etc.
|
||||
-- @param system
|
||||
-- The target operating system, which can modify the naming style. For example,
|
||||
-- shared libraries on Mac OS X use a ".dylib" extension.
|
||||
-- @returns
|
||||
-- An object with these fields:
|
||||
-- basename - the target with no directory or file extension
|
||||
-- name - the target name and extension, with no directory
|
||||
-- directory - relative path to the target, with no file name
|
||||
-- prefix - the file name prefix
|
||||
-- suffix - the file name suffix
|
||||
-- fullpath - directory, name, and extension
|
||||
-- bundlepath - the relative path and file name of the bundle
|
||||
--
|
||||
|
||||
function premake.gettarget(cfg, direction, pathstyle, namestyle, system)
|
||||
if system == "bsd" then
|
||||
system = "linux"
|
||||
end
|
||||
|
||||
-- Fix things up based on the current system
|
||||
local kind = cfg.kind
|
||||
if premake.iscppproject(cfg) or premake.isvalaproject(cfg) then
|
||||
-- On Windows, shared libraries link against a static import library
|
||||
if (namestyle == "windows" or system == "windows")
|
||||
and kind == "SharedLib" and direction == "link"
|
||||
and not cfg.flags.NoImportLib
|
||||
then
|
||||
kind = "StaticLib"
|
||||
end
|
||||
|
||||
-- Posix name conventions only apply to static libs on windows (by user request)
|
||||
if namestyle == "posix" and system == "windows" and kind ~= "StaticLib" then
|
||||
namestyle = "windows"
|
||||
end
|
||||
end
|
||||
|
||||
-- Initialize the target components
|
||||
local field = "build"
|
||||
if direction == "link" and cfg.kind == "SharedLib" then
|
||||
field = "implib"
|
||||
end
|
||||
|
||||
local name = cfg[field.."name"] or cfg.targetname or cfg.project.name
|
||||
local dir = cfg[field.."dir"] or cfg.targetdir or path.getrelative(cfg.location, cfg.basedir)
|
||||
local subdir = cfg[field.."subdir"] or cfg.targetsubdir or "."
|
||||
local prefix = ""
|
||||
local suffix = ""
|
||||
local ext = ""
|
||||
local bundlepath, bundlename
|
||||
|
||||
-- targetpath/targetsubdir/bundlepath/prefix..name..suffix..ext
|
||||
|
||||
dir = path.join(dir, subdir)
|
||||
|
||||
|
||||
if namestyle == "windows" then
|
||||
if kind == "ConsoleApp" or kind == "WindowedApp" then
|
||||
ext = ".exe"
|
||||
elseif kind == "SharedLib" then
|
||||
ext = ".dll"
|
||||
elseif kind == "StaticLib" then
|
||||
ext = ".lib"
|
||||
end
|
||||
elseif namestyle == "posix" then
|
||||
if kind == "WindowedApp" and system == "macosx" and not cfg.options.SkipBundling then
|
||||
bundlename = name .. ".app"
|
||||
bundlepath = path.join(dir, bundlename)
|
||||
dir = path.join(bundlepath, "Contents/MacOS")
|
||||
elseif (kind == "ConsoleApp" or kind == "WindowedApp") and system == "os2" then
|
||||
ext = ".exe"
|
||||
elseif kind == "SharedLib" then
|
||||
prefix = "lib"
|
||||
ext = iif(system == "macosx", ".dylib", ".so")
|
||||
elseif kind == "StaticLib" then
|
||||
prefix = "lib"
|
||||
ext = ".a"
|
||||
end
|
||||
elseif namestyle == "PS3" then
|
||||
if kind == "ConsoleApp" or kind == "WindowedApp" then
|
||||
ext = ".elf"
|
||||
elseif kind == "StaticLib" then
|
||||
prefix = "lib"
|
||||
ext = ".a"
|
||||
end
|
||||
elseif namestyle == "Orbis" then
|
||||
if kind == "ConsoleApp" or kind == "WindowedApp" then
|
||||
ext = ".elf"
|
||||
elseif kind == "StaticLib" then
|
||||
prefix = "lib"
|
||||
ext = ".a"
|
||||
elseif kind == "SharedLib" then
|
||||
ext = ".prx"
|
||||
end
|
||||
elseif namestyle == "TegraAndroid" then
|
||||
-- the .so->.apk happens later for Application types
|
||||
if kind == "ConsoleApp" or kind == "WindowedApp" or kind == "SharedLib" then
|
||||
prefix = "lib"
|
||||
ext = ".so"
|
||||
elseif kind == "StaticLib" then
|
||||
prefix = "lib"
|
||||
ext = ".a"
|
||||
end
|
||||
elseif namestyle == "NX" then
|
||||
-- NOTE: it would be cleaner to just output $(TargetExt) for all cases, but
|
||||
-- there is logic elsewhere that assumes a '.' to be present in target name
|
||||
-- such that it can reverse engineer the extension set here.
|
||||
if kind == "ConsoleApp" or kind == "WindowedApp" then
|
||||
ext = ".nspd_root"
|
||||
elseif kind == "StaticLib" then
|
||||
ext = ".a"
|
||||
elseif kind == "SharedLib" then
|
||||
ext = ".nro"
|
||||
end
|
||||
elseif namestyle == "Emscripten" then
|
||||
if kind == "ConsoleApp" or kind == "WindowedApp" then
|
||||
ext = ".html"
|
||||
elseif kind == "StaticLib" then
|
||||
ext = ".bc"
|
||||
elseif kind == "SharedLib" then
|
||||
ext = ".js"
|
||||
end
|
||||
end
|
||||
|
||||
prefix = cfg[field.."prefix"] or cfg.targetprefix or prefix
|
||||
suffix = cfg[field.."suffix"] or cfg.targetsuffix or suffix
|
||||
ext = cfg[field.."extension"] or cfg.targetextension or ext
|
||||
|
||||
-- build the results object
|
||||
local result = { }
|
||||
result.basename = name .. suffix
|
||||
result.name = prefix .. name .. suffix .. ext
|
||||
result.directory = dir
|
||||
result.subdirectory = subdir
|
||||
result.prefix = prefix
|
||||
result.suffix = suffix
|
||||
result.fullpath = path.join(result.directory, result.name)
|
||||
result.bundlepath = bundlepath or result.fullpath
|
||||
|
||||
if pathstyle == "windows" then
|
||||
result.directory = path.translate(result.directory, "\\")
|
||||
result.subdirectory = path.translate(result.subdirectory, "\\")
|
||||
result.fullpath = path.translate(result.fullpath, "\\")
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Return the appropriate tool interface, based on the target language and
|
||||
-- any relevant command-line options.
|
||||
--
|
||||
|
||||
function premake.gettool(prj)
|
||||
if premake.iscppproject(prj) then
|
||||
if _OPTIONS.cc then
|
||||
return premake[_OPTIONS.cc]
|
||||
end
|
||||
local action = premake.action.current()
|
||||
if action.valid_tools then
|
||||
return premake[action.valid_tools.cc[1]]
|
||||
end
|
||||
return premake.gcc
|
||||
elseif premake.isdotnetproject(prj) then
|
||||
return premake.dotnet
|
||||
elseif premake.isswiftproject(prj) then
|
||||
return premake.swift
|
||||
else
|
||||
return premake.valac
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Given a source file path, return a corresponding virtual path based on
|
||||
-- the vpath entries in the project. If no matching vpath entry is found,
|
||||
-- the original path is returned.
|
||||
--
|
||||
|
||||
function premake.project.getvpath(prj, abspath)
|
||||
-- If there is no match, the result is the original filename
|
||||
local vpath = abspath
|
||||
|
||||
-- The file's name must be maintained in the resulting path; use these
|
||||
-- to make sure I don't cut off too much
|
||||
|
||||
local fname = path.getname(abspath)
|
||||
local max = abspath:len() - fname:len()
|
||||
|
||||
-- First check for an exact match from the inverse vpaths
|
||||
if prj.inversevpaths and prj.inversevpaths[abspath] then
|
||||
return path.join(prj.inversevpaths[abspath], fname)
|
||||
end
|
||||
|
||||
-- Look for matching patterns
|
||||
local matches = {}
|
||||
for replacement, patterns in pairs(prj.vpaths or {}) do
|
||||
for _, pattern in ipairs(patterns) do
|
||||
local i = abspath:find(path.wildcards(pattern))
|
||||
if i == 1 then
|
||||
|
||||
-- Trim out the part of the name that matched the pattern; what's
|
||||
-- left is the part that gets appended to the replacement to make
|
||||
-- the virtual path. So a pattern like "src/**.h" matching the
|
||||
-- file src/include/hello.h, I want to trim out the src/ part,
|
||||
-- leaving include/hello.h.
|
||||
|
||||
-- Find out where the wildcard appears in the match. If there is
|
||||
-- no wildcard, the match includes the entire pattern
|
||||
|
||||
i = pattern:find("*", 1, true) or (pattern:len() + 1)
|
||||
|
||||
-- Trim, taking care to keep the actual file name intact.
|
||||
|
||||
local leaf
|
||||
if i < max then
|
||||
leaf = abspath:sub(i)
|
||||
else
|
||||
leaf = fname
|
||||
end
|
||||
|
||||
if leaf:startswith("/") then
|
||||
leaf = leaf:sub(2)
|
||||
end
|
||||
|
||||
-- check for (and remove) stars in the replacement pattern.
|
||||
-- If there are none, then trim all path info from the leaf
|
||||
-- and use just the filename in the replacement (stars should
|
||||
-- really only appear at the end; I'm cheating here)
|
||||
|
||||
local stem = ""
|
||||
if replacement:len() > 0 then
|
||||
stem, stars = replacement:gsub("%*", "")
|
||||
if stars == 0 then
|
||||
leaf = path.getname(leaf)
|
||||
end
|
||||
else
|
||||
leaf = path.getname(leaf)
|
||||
end
|
||||
|
||||
table.insert(matches, path.join(stem, leaf))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #matches > 0 then
|
||||
-- for the sake of determinism, return the first alphabetically
|
||||
table.sort(matches)
|
||||
vpath = matches[1]
|
||||
end
|
||||
|
||||
return path.trimdots(vpath)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Returns true if the solution contains at least one C/C++ project.
|
||||
--
|
||||
|
||||
function premake.hascppproject(sln)
|
||||
for prj in premake.solution.eachproject(sln) do
|
||||
if premake.iscppproject(prj) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Returns true if the solution contains at least one .NET project.
|
||||
--
|
||||
|
||||
function premake.hasdotnetproject(sln)
|
||||
for prj in premake.solution.eachproject(sln) do
|
||||
if premake.isdotnetproject(prj) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Returns true if the project use the C language.
|
||||
--
|
||||
|
||||
function premake.project.iscproject(prj)
|
||||
local language = prj.language or prj.solution.language
|
||||
return language == "C"
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Returns true if the project uses a C/C++ language.
|
||||
--
|
||||
|
||||
function premake.iscppproject(prj)
|
||||
local language = prj.language or prj.solution.language
|
||||
return (language == "C" or language == "C++")
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Returns true if the project uses a .NET language.
|
||||
--
|
||||
|
||||
function premake.isdotnetproject(prj)
|
||||
local language = prj.language or prj.solution.language
|
||||
return (language == "C#")
|
||||
end
|
||||
|
||||
--
|
||||
-- Returns true if the project uses the Vala language.
|
||||
--
|
||||
|
||||
function premake.isvalaproject(prj)
|
||||
local language = prj.language or prj.solution.language
|
||||
return (language == "Vala")
|
||||
end
|
||||
|
||||
--
|
||||
-- Returns true if the project uses the Swift language.
|
||||
--
|
||||
|
||||
function premake.isswiftproject(prj)
|
||||
local language = prj.language or prj.solution.language
|
||||
return (language == "Swift")
|
||||
end
|
||||
77
Src/external_dependencies/openmpt-trunk/include/genie/src/base/set.lua
vendored
Normal file
77
Src/external_dependencies/openmpt-trunk/include/genie/src/base/set.lua
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
Set_mt = {}
|
||||
|
||||
function Set(t)
|
||||
local set = {}
|
||||
for k, l in ipairs(t) do
|
||||
set[l] = true
|
||||
end
|
||||
setmetatable(set, Set_mt)
|
||||
return set
|
||||
end
|
||||
|
||||
function Set_mt.union(a, b)
|
||||
local res = Set{}
|
||||
for k in pairs(a) do res[k] = true end
|
||||
for k in pairs(b) do res[k] = true end
|
||||
return res
|
||||
end
|
||||
|
||||
function Set_mt.intersection(a, b)
|
||||
local res = Set{}
|
||||
for k in pairs(a) do
|
||||
res[k] = b[k]
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
local function get_cache(a)
|
||||
if not rawget(a, "__cache") then
|
||||
rawset(a, "__cache", Set_mt.totable(a))
|
||||
end
|
||||
return rawget(a, "__cache")
|
||||
end
|
||||
|
||||
function Set_mt.len(a)
|
||||
return #get_cache(a)
|
||||
end
|
||||
|
||||
function Set_mt.implode(a, sep)
|
||||
return table.concat(get_cache(a), sep)
|
||||
end
|
||||
|
||||
function Set_mt.totable(a)
|
||||
local res = {}
|
||||
for k in pairs(a) do
|
||||
table.insert(res, k)
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
function Set_mt.difference(a, b)
|
||||
if getmetatable(b) ~= Set_mt then
|
||||
if type(b) ~= "table" then
|
||||
error(type(b).." is not a Set or table")
|
||||
end
|
||||
b=Set(b)
|
||||
end
|
||||
|
||||
local res = Set{}
|
||||
for k in pairs(a) do
|
||||
res[k] = not b[k] or nil
|
||||
end
|
||||
rawset(res, "__cache", nil)
|
||||
return res
|
||||
end
|
||||
|
||||
function Set_mt.__index(a, i)
|
||||
if type(i) == "number" then
|
||||
return get_cache(a)[i]
|
||||
end
|
||||
return Set_mt[i] or rawget(a, i)
|
||||
end
|
||||
|
||||
Set_mt.__add = Set_mt.union
|
||||
Set_mt.__mul = Set_mt.intersection
|
||||
Set_mt.__sub = Set_mt.difference
|
||||
Set_mt.__len = Set_mt.len
|
||||
Set_mt.__concat = Set_mt.implode
|
||||
148
Src/external_dependencies/openmpt-trunk/include/genie/src/base/solution.lua
vendored
Normal file
148
Src/external_dependencies/openmpt-trunk/include/genie/src/base/solution.lua
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
--
|
||||
-- solution.lua
|
||||
-- Work with the list of solutions loaded from the script.
|
||||
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
premake.solution = { }
|
||||
|
||||
|
||||
-- The list of defined solutions (which contain projects, etc.)
|
||||
|
||||
premake.solution.list = { }
|
||||
|
||||
|
||||
--
|
||||
-- Create a new solution and add it to the session.
|
||||
--
|
||||
-- @param name
|
||||
-- The new solution's name.
|
||||
--
|
||||
|
||||
function premake.solution.new(name)
|
||||
local sln = { }
|
||||
|
||||
-- add to master list keyed by both name and index
|
||||
table.insert(premake.solution.list, sln)
|
||||
premake.solution.list[name] = sln
|
||||
|
||||
-- attach a type descriptor
|
||||
setmetatable(sln, { __type="solution" })
|
||||
|
||||
sln.name = name
|
||||
sln.basedir = os.getcwd()
|
||||
sln.projects = { }
|
||||
sln.blocks = { }
|
||||
sln.configurations = { }
|
||||
sln.groups = { }
|
||||
sln.importedprojects = { }
|
||||
return sln
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Iterate over the collection of solutions in a session.
|
||||
--
|
||||
-- @returns
|
||||
-- An iterator function.
|
||||
--
|
||||
|
||||
function premake.solution.each()
|
||||
local i = 0
|
||||
return function ()
|
||||
i = i + 1
|
||||
if i <= #premake.solution.list then
|
||||
return premake.solution.list[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Iterate over the projects of a solution.
|
||||
--
|
||||
-- @param sln
|
||||
-- The solution.
|
||||
-- @returns
|
||||
-- An iterator function.
|
||||
--
|
||||
|
||||
function premake.solution.eachproject(sln)
|
||||
local i = 0
|
||||
return function ()
|
||||
i = i + 1
|
||||
if (i <= #sln.projects) then
|
||||
return premake.solution.getproject(sln, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Iterate over the groups of a solution
|
||||
--
|
||||
-- @param sln
|
||||
-- The solution.
|
||||
-- @returns
|
||||
-- An iterator function.
|
||||
|
||||
function premake.solution.eachgroup(sln)
|
||||
local i = 0
|
||||
return function()
|
||||
i = i + 1
|
||||
if(i <= #sln.groups) then
|
||||
return premake.solution.getgroup(sln, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve a solution by name or index.
|
||||
--
|
||||
-- @param key
|
||||
-- The solution key, either a string name or integer index.
|
||||
-- @returns
|
||||
-- The solution with the provided key.
|
||||
--
|
||||
|
||||
function premake.solution.get(key)
|
||||
return premake.solution.list[key]
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve the project at a particular index.
|
||||
--
|
||||
-- @param sln
|
||||
-- The solution.
|
||||
-- @param idx
|
||||
-- An index into the array of projects.
|
||||
-- @returns
|
||||
-- The project at the given index.
|
||||
--
|
||||
|
||||
function premake.solution.getproject(sln, idx)
|
||||
-- retrieve the root configuration of the project, with all of
|
||||
-- the global (not configuration specific) settings collapsed
|
||||
local prj = sln.projects[idx]
|
||||
local cfg = premake.getconfig(prj)
|
||||
|
||||
-- root configuration doesn't have a name; use the project's
|
||||
cfg.name = prj.name
|
||||
return cfg
|
||||
end
|
||||
|
||||
--
|
||||
-- Retrieve the group at a particular index
|
||||
--
|
||||
-- @param sln
|
||||
-- The solution.
|
||||
-- @param idx
|
||||
-- The index into the array of groups
|
||||
-- @returns
|
||||
-- The group at the given index
|
||||
|
||||
function premake.solution.getgroup(sln, idx)
|
||||
local grp = sln.groups[idx]
|
||||
return grp
|
||||
end
|
||||
62
Src/external_dependencies/openmpt-trunk/include/genie/src/base/string.lua
vendored
Normal file
62
Src/external_dependencies/openmpt-trunk/include/genie/src/base/string.lua
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
--
|
||||
-- string.lua
|
||||
-- Additions to Lua's built-in string functions.
|
||||
-- Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- Returns an array of strings, each of which is a substring of s
|
||||
-- formed by splitting on boundaries formed by `pattern`.
|
||||
--
|
||||
|
||||
function string.explode(s, pattern, plain)
|
||||
if (pattern == '') then return false end
|
||||
local pos = 0
|
||||
local arr = { }
|
||||
for st,sp in function() return s:find(pattern, pos, plain) end do
|
||||
table.insert(arr, s:sub(pos, st-1))
|
||||
pos = sp + 1
|
||||
end
|
||||
table.insert(arr, s:sub(pos))
|
||||
return arr
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Find the last instance of a pattern in a string.
|
||||
--
|
||||
|
||||
function string.findlast(s, pattern, plain)
|
||||
local curr = 0
|
||||
local term = nil
|
||||
repeat
|
||||
local next, nextterm = s:find(pattern, curr + 1, plain)
|
||||
if (next) then
|
||||
curr = next
|
||||
term = nextterm
|
||||
end
|
||||
until (not next)
|
||||
if (curr > 0) then
|
||||
return curr, term
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Returns true if `haystack` starts with the sequence `needle`.
|
||||
--
|
||||
|
||||
function string.startswith(haystack, needle)
|
||||
return (haystack:find(needle, 1, true) == 1)
|
||||
end
|
||||
|
||||
--
|
||||
-- remove leading and trailing whitespace from string.
|
||||
--
|
||||
|
||||
function string.trim(s)
|
||||
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||
end
|
||||
260
Src/external_dependencies/openmpt-trunk/include/genie/src/base/table.lua
vendored
Normal file
260
Src/external_dependencies/openmpt-trunk/include/genie/src/base/table.lua
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
--
|
||||
-- table.lua
|
||||
-- Additions to Lua's built-in table functions.
|
||||
-- Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- Returns true if the table contains the specified value.
|
||||
--
|
||||
|
||||
function table.contains(t, value)
|
||||
for _, v in pairs(t) do
|
||||
if v == value then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function table.icontains(t, value)
|
||||
for _, v in ipairs(t) do
|
||||
if v == value then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Make a complete copy of a table, including any child tables it contains.
|
||||
--
|
||||
|
||||
function table.deepcopy(object)
|
||||
-- keep track of already seen objects to avoid loops
|
||||
local seen = {}
|
||||
|
||||
local function copy(object)
|
||||
if type(object) ~= "table" then
|
||||
return object
|
||||
elseif seen[object] then
|
||||
return seen[object]
|
||||
end
|
||||
|
||||
local clone = {}
|
||||
seen[object] = clone
|
||||
for key, value in pairs(object) do
|
||||
clone[key] = copy(value)
|
||||
end
|
||||
|
||||
setmetatable(clone, getmetatable(object))
|
||||
return clone
|
||||
end
|
||||
|
||||
return copy(object)
|
||||
end
|
||||
|
||||
--
|
||||
-- Enumerates an array of objects and returns a new table containing
|
||||
-- only the value of one particular field.
|
||||
--
|
||||
|
||||
function table.extract(arr, fname)
|
||||
local result = { }
|
||||
for _,v in ipairs(arr) do
|
||||
table.insert(result, v[fname])
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Flattens a hierarchy of tables into a single array containing all
|
||||
-- of the values.
|
||||
--
|
||||
|
||||
function table.flatten(arr)
|
||||
local result = { }
|
||||
|
||||
local function flatten(arr)
|
||||
for _, v in ipairs(arr) do
|
||||
if type(v) == "table" then
|
||||
flatten(v)
|
||||
else
|
||||
table.insert(result, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
flatten(arr)
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Merges an array of items into a string.
|
||||
--
|
||||
|
||||
function table.implode(arr, before, after, between)
|
||||
local result = ""
|
||||
for _,v in ipairs(arr) do
|
||||
if (result ~= "" and between) then
|
||||
result = result .. between
|
||||
end
|
||||
result = result .. before .. v .. after
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Inserts a value of array of values into a table. If the value is
|
||||
-- itself a table, its contents are enumerated and added instead. So
|
||||
-- these inputs give these outputs:
|
||||
--
|
||||
-- "x" -> { "x" }
|
||||
-- { "x", "y" } -> { "x", "y" }
|
||||
-- { "x", { "y" }} -> { "x", "y" }
|
||||
--
|
||||
|
||||
function table.insertflat(tbl, values)
|
||||
if type(values) == "table" then
|
||||
for _, value in ipairs(values) do
|
||||
table.insertflat(tbl, value)
|
||||
end
|
||||
else
|
||||
table.insert(tbl, values)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Returns true if the table is empty, and contains no indexed or keyed values.
|
||||
--
|
||||
|
||||
function table.isempty(t)
|
||||
return next(t) == nil
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Adds the values from one array to the end of another and
|
||||
-- returns the result.
|
||||
--
|
||||
|
||||
function table.join(...)
|
||||
local arg={...}
|
||||
local result = { }
|
||||
for _,t in ipairs(arg) do
|
||||
if type(t) == "table" then
|
||||
for _,v in ipairs(t) do
|
||||
table.insert(result, v)
|
||||
end
|
||||
else
|
||||
table.insert(result, t)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Return a list of all keys used in a table.
|
||||
--
|
||||
|
||||
function table.keys(tbl)
|
||||
local keys = {}
|
||||
for k, _ in pairs(tbl) do
|
||||
table.insert(keys, k)
|
||||
end
|
||||
return keys
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Return an iterator over key/value pairs in a table, sorted by key.
|
||||
--
|
||||
|
||||
function table.sortedpairs(t)
|
||||
local keys = table.keys(t)
|
||||
local i = 0
|
||||
table.sort(keys)
|
||||
return function()
|
||||
i = i + 1
|
||||
if keys[i] == nil then
|
||||
return nil
|
||||
end
|
||||
return keys[i], t[keys[i]]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Adds the key-value associations from one table into another
|
||||
-- and returns the resulting merged table.
|
||||
--
|
||||
|
||||
function table.merge(...)
|
||||
local arg={...}
|
||||
local result = { }
|
||||
for _,t in ipairs(arg) do
|
||||
if type(t) == "table" then
|
||||
for k,v in pairs(t) do
|
||||
result[k] = v
|
||||
end
|
||||
else
|
||||
error("invalid value")
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Translates the values contained in array, using the specified
|
||||
-- translation table, and returns the results in a new array.
|
||||
--
|
||||
|
||||
function table.translate(arr, translation)
|
||||
local result = { }
|
||||
for _, value in ipairs(arr) do
|
||||
local tvalue
|
||||
if type(translation) == "function" then
|
||||
tvalue = translation(value)
|
||||
else
|
||||
tvalue = translation[value]
|
||||
end
|
||||
if (tvalue) then
|
||||
table.insert(result, tvalue)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- reverse table order
|
||||
--
|
||||
|
||||
function table.reverse(arr)
|
||||
for i=1, math.floor(#arr / 2) do
|
||||
arr[i], arr[#arr - i + 1] = arr[#arr - i + 1], arr[i]
|
||||
end
|
||||
return arr
|
||||
end
|
||||
|
||||
--
|
||||
-- reverse table order
|
||||
--
|
||||
|
||||
function table.arglist(arg, value)
|
||||
if #value > 0 then
|
||||
local args = {}
|
||||
for _, val in ipairs(value) do
|
||||
table.insert(args, string.format("%s %s", arg, val))
|
||||
end
|
||||
return table.concat(args, " ")
|
||||
else
|
||||
return ""
|
||||
end
|
||||
end
|
||||
231
Src/external_dependencies/openmpt-trunk/include/genie/src/base/tree.lua
vendored
Normal file
231
Src/external_dependencies/openmpt-trunk/include/genie/src/base/tree.lua
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
--
|
||||
-- tree.lua
|
||||
-- Functions for working with the source code tree.
|
||||
-- Copyright (c) 2009 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
premake.tree = { }
|
||||
local tree = premake.tree
|
||||
|
||||
|
||||
--
|
||||
-- Create a new tree.
|
||||
--
|
||||
-- @param n
|
||||
-- The name of the tree, applied to the root node (optional).
|
||||
--
|
||||
|
||||
function premake.tree.new(n)
|
||||
local t = {
|
||||
name = n,
|
||||
children = { }
|
||||
}
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Add a new node to the tree, or returns the current node if it already exists.
|
||||
--
|
||||
-- @param tr
|
||||
-- The tree to contain the new node.
|
||||
-- @param p
|
||||
-- The path of the new node.
|
||||
-- @param onaddfunc
|
||||
-- A function to call when a new node is added to the tree. Receives the
|
||||
-- new node as an argument.
|
||||
-- @returns
|
||||
-- The new tree node.
|
||||
--
|
||||
|
||||
function premake.tree.add(tr, p, onaddfunc)
|
||||
-- Special case "." refers to the current node
|
||||
if p == "." then
|
||||
return tr
|
||||
end
|
||||
|
||||
if p == "/" then
|
||||
return tr
|
||||
end
|
||||
|
||||
-- Look for the immediate parent for this new node, creating it if necessary.
|
||||
-- Recurses to create as much of the tree as necessary.
|
||||
local parentnode = tree.add(tr, path.getdirectory(p), onaddfunc)
|
||||
|
||||
-- Another special case, ".." refers to the parent node and doesn't create anything
|
||||
local childname = path.getname(p)
|
||||
if childname == ".." then
|
||||
return parentnode
|
||||
end
|
||||
|
||||
-- Create the child if necessary. If two children with the same name appear
|
||||
-- at the same level, make sure they have the same path to prevent conflicts
|
||||
-- i.e. ../Common and ../../Common can both appear at the top of the tree
|
||||
-- yet they have different paths (Bug #3016050)
|
||||
local childnode = parentnode.children[childname]
|
||||
if not childnode or childnode.path ~= p then
|
||||
childnode = tree.insert(parentnode, tree.new(childname))
|
||||
childnode.path = p
|
||||
if onaddfunc then
|
||||
onaddfunc(childnode)
|
||||
end
|
||||
end
|
||||
|
||||
return childnode
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Insert one tree into another.
|
||||
--
|
||||
-- @param parent
|
||||
-- The parent tree, to contain the child.
|
||||
-- @param child
|
||||
-- The child tree, to be inserted.
|
||||
--
|
||||
|
||||
function premake.tree.insert(parent, child)
|
||||
table.insert(parent.children, child)
|
||||
if child.name then
|
||||
parent.children[child.name] = child
|
||||
end
|
||||
child.parent = parent
|
||||
return child
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Gets the node's relative path from it's parent. If the parent does not have
|
||||
-- a path set (it is the root or other container node) returns the full node path.
|
||||
--
|
||||
-- @param node
|
||||
-- The node to query.
|
||||
--
|
||||
|
||||
function premake.tree.getlocalpath(node)
|
||||
if node.parent.path then
|
||||
return node.name
|
||||
elseif node.cfg then
|
||||
return node.cfg.name
|
||||
else
|
||||
return node.path
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Remove a node from a tree.
|
||||
--
|
||||
-- @param node
|
||||
-- The node to remove.
|
||||
--
|
||||
|
||||
function premake.tree.remove(node)
|
||||
local children = node.parent.children
|
||||
for i = 1, #children do
|
||||
if children[i] == node then
|
||||
table.remove(children, i)
|
||||
end
|
||||
end
|
||||
node.children = {}
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Sort the nodes of a tree in-place.
|
||||
--
|
||||
-- @param tr
|
||||
-- The tree to sort.
|
||||
--
|
||||
|
||||
function premake.tree.sort(tr)
|
||||
tree.traverse(tr, {
|
||||
onnode = function(node)
|
||||
table.sort(node.children, function(a,b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
end
|
||||
}, true)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Traverse a tree.
|
||||
--
|
||||
-- @param t
|
||||
-- The tree to traverse.
|
||||
-- @param fn
|
||||
-- A collection of callback functions, which may contain any or all of the
|
||||
-- following entries. Entries are called in this order.
|
||||
--
|
||||
-- onnode - called on each node encountered
|
||||
-- onbranchenter - called on branches, before processing children
|
||||
-- onbranch - called only on branch nodes
|
||||
-- onleaf - called only on leaf nodes
|
||||
-- onbranchexit - called on branches, after processing children
|
||||
--
|
||||
-- Callbacks receive two arguments: the node being processed, and the
|
||||
-- current traversal depth.
|
||||
--
|
||||
-- @param includeroot
|
||||
-- True to include the root node in the traversal, otherwise it will be skipped.
|
||||
-- @param initialdepth
|
||||
-- An optional starting value for the traversal depth; defaults to zero.
|
||||
--
|
||||
|
||||
function premake.tree.traverse(t, fn, includeroot, initialdepth)
|
||||
|
||||
-- forward declare my handlers, which call each other
|
||||
local donode, dochildren
|
||||
|
||||
-- process an individual node
|
||||
donode = function(node, fn, depth)
|
||||
if node.isremoved then
|
||||
return
|
||||
end
|
||||
|
||||
if fn.onnode then
|
||||
fn.onnode(node, depth)
|
||||
end
|
||||
|
||||
if #node.children > 0 then
|
||||
if fn.onbranchenter then
|
||||
fn.onbranchenter(node, depth)
|
||||
end
|
||||
if fn.onbranch then
|
||||
fn.onbranch(node, depth)
|
||||
end
|
||||
dochildren(node, fn, depth + 1)
|
||||
if fn.onbranchexit then
|
||||
fn.onbranchexit(node, depth)
|
||||
end
|
||||
else
|
||||
if fn.onleaf then
|
||||
fn.onleaf(node, depth)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- this goofy iterator allows nodes to be removed during the traversal
|
||||
dochildren = function(parent, fn, depth)
|
||||
local i = 1
|
||||
while i <= #parent.children do
|
||||
local node = parent.children[i]
|
||||
donode(node, fn, depth)
|
||||
if node == parent.children[i] then
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- set a default initial traversal depth, if one wasn't set
|
||||
if not initialdepth then
|
||||
initialdepth = 0
|
||||
end
|
||||
|
||||
if includeroot then
|
||||
donode(t, fn, initialdepth)
|
||||
else
|
||||
dochildren(t, fn, initialdepth)
|
||||
end
|
||||
end
|
||||
91
Src/external_dependencies/openmpt-trunk/include/genie/src/base/validate.lua
vendored
Normal file
91
Src/external_dependencies/openmpt-trunk/include/genie/src/base/validate.lua
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
--
|
||||
-- validate.lua
|
||||
-- Tests to validate the run-time environment before starting the action.
|
||||
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- Performs a sanity check of all of the solutions and projects
|
||||
-- in the session to be sure they meet some minimum requirements.
|
||||
--
|
||||
|
||||
function premake.checkprojects()
|
||||
local action = premake.action.current()
|
||||
|
||||
for sln in premake.solution.each() do
|
||||
|
||||
-- every solution must have at least one project
|
||||
if (#sln.projects == 0) then
|
||||
return nil, "solution '" .. sln.name .. "' needs at least one project"
|
||||
end
|
||||
|
||||
-- every solution must provide a list of configurations
|
||||
if (#sln.configurations == 0) then
|
||||
return nil, "solution '" .. sln.name .. "' needs configurations"
|
||||
end
|
||||
|
||||
for prj in premake.solution.eachproject(sln) do
|
||||
|
||||
-- every project must have a language
|
||||
if (not prj.language) then
|
||||
return nil, "project '" ..prj.name .. "' needs a language"
|
||||
end
|
||||
|
||||
-- and the action must support it
|
||||
if (action.valid_languages) then
|
||||
if (not table.contains(action.valid_languages, prj.language)) then
|
||||
return nil, "the " .. action.shortname .. " action does not support " .. prj.language .. " projects"
|
||||
end
|
||||
end
|
||||
|
||||
for cfg in premake.eachconfig(prj) do
|
||||
|
||||
-- every config must have a kind
|
||||
if (not cfg.kind) then
|
||||
return nil, "project '" ..prj.name .. "' needs a kind in configuration '" .. cfg.name .. "'"
|
||||
end
|
||||
|
||||
-- and the action must support it
|
||||
if (action.valid_kinds) then
|
||||
if (not table.contains(action.valid_kinds, cfg.kind)) then
|
||||
return nil, "the " .. action.shortname .. " action does not support " .. cfg.kind .. " projects"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- some actions have custom validation logic
|
||||
if action.oncheckproject then
|
||||
action.oncheckproject(prj)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Check the specified tools (/cc, /dotnet, etc.) against the current action
|
||||
-- to make sure they are compatible and supported.
|
||||
--
|
||||
|
||||
function premake.checktools()
|
||||
local action = premake.action.current()
|
||||
if (not action.valid_tools) then
|
||||
return true
|
||||
end
|
||||
|
||||
for tool, values in pairs(action.valid_tools) do
|
||||
if (_OPTIONS[tool]) then
|
||||
if (not table.contains(values, _OPTIONS[tool])) then
|
||||
return nil, "the " .. action.shortname .. " action does not support /" .. tool .. "=" .. _OPTIONS[tool] .. " (yet)"
|
||||
end
|
||||
else
|
||||
_OPTIONS[tool] = values[1]
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
Reference in New Issue
Block a user