Port solution() to new container API

This commit is contained in:
Jason Perkins 2014-10-07 16:56:53 -04:00
parent 30b6631b37
commit f73a2206ef
6 changed files with 160 additions and 130 deletions

View File

@ -17,6 +17,9 @@
-- scope (e.g. solutions, projects, groups, and configurations). Initialize
-- it with a "root" container to contain the other containers, as well as the
-- global configuration settings which should apply to all of them.
--
-- TODO: this should be hidden, with a perhaps a read-only accessor to fetch
-- individual scopes for testing.
---
api.scope = {}
@ -78,6 +81,22 @@
---
-- Recursively clear any child scopes for a container class. For example,
-- if a solution is being activated, clear the project and group scopes,
-- as those are children of solutions. If the root scope is made active,
-- all child scopes will be cleared.
---
function api._clearChildScopes(cc)
for ch in cc:eachChildClass() do
api.scope[ch.name] = nil
api._clearChildScopes(ch)
end
end
---
-- Activate a new configuration container, making it the target for all
-- subsequent configuration settings. When you call solution() or project()
@ -89,28 +108,54 @@
-- @param name
-- The name of the container instance to be activated. If a container
-- (e.g. project) with this name does not already exist it will be
-- created.
-- created. If name is not set, the last activated container of this
-- class will be made current again.
-- @return
-- The container instance.
---
function api._setScope(cc, name)
local instance
-- for backward compatibility, "*" activates the parent container
if name == "*" then
return api._setScope(cc.parent)
end
-- << handle (name == nil) >>
-- if name is not set, use whatever was last made current
local container
if not name then
container = api.scope[cc.name]
if not container then
error("no " .. cc.name .. " in scope", 3)
end
end
-- << handle "*" >>
if not container then
-- all containers should be contained within a parent
local parent = api.scope[cc.parent.name]
if not parent then
error("no active " .. cc.parent.name, 3)
end
-- Fetch (creating if necessary) the container
local parentContainer = api._target(cc.parent)
local container = parentContainer:fetchContainer(cc, name)
-- fetch (creating if necessary) the container
container = parent:fetchChild(cc, name)
if not container then
container = parent:createChild(cc, name, parent)
else
configset.addFilter(container, {}, os.getcwd())
end
end
-- << start a new settings block >>
-- clear out any active child container types
api._clearChildScopes(cc)
-- Activate the container
api.scope[cc.name] = container -- TODO: do I still need this?
-- activate the container, as well as its ancestors
api.scope.current = container
return container
while container.parent do
api.scope[container.class.name] = container
container = container.parent
end
return api.scope.current
end
@ -630,6 +675,9 @@
---
function api.reset()
-- Clear out all top level objects
api.scope.root.solutions = {}
-- Remove all custom variables
local vars = api.getCustomVars()
for i, var in ipairs(vars) do
@ -1034,6 +1082,23 @@
local _slnContainerClass = api.container {
name = "solution",
}
api.container {
name = "group",
parent = "solution",
}
api.container {
name = "project",
parent = "solution",
}
---
-- Begin a new solution group, which will contain any subsequent projects.
---
@ -1056,15 +1121,6 @@
-- The active project object.
--
api.container {
name = "solution",
}
api.container {
name = "project",
parent = "solution",
}
function project(name)
if not name then
if api.scope.project then
@ -1081,6 +1137,7 @@
local prj
if name ~= "*" then
sln.projects = sln.projects or {}
prj = sln.projects[name]
if not prj then
prj = premake.project.new(sln, name)
@ -1120,44 +1177,6 @@
--
-- Set the current configuration scope to a solution.
--
-- @param name
-- The name of the solution. If a solution with this name already
-- exists, it is made current, otherwise a new solution is created
-- with this name. If no name is provided, the most recently defined
-- solution is made active.
-- @return
-- The active solution object.
--
function solution(name)
if not name then
if api.scope.solution then
name = api.scope.solution.name
else
return nil
end
end
local sln
if name ~= "*" then
sln = premake.solution.get(name) or premake.solution.new(name)
sln.class = p.containerClass.get("solution")
end
api.scope.solution = sln
api.scope.project = nil
api.scope.group = nil
api.scope.current = sln
configuration {}
return sln
end
--
-- Define a new action.
--

View File

@ -73,6 +73,8 @@
-- An initializer function to call for new instances of this class.
-- Should accept the new instance object as its only argument.
--
-- Other keys are allowed and will be left intact.
--
-- @return
-- A new container class object if successful, else nil and an
-- error message.
@ -102,8 +104,8 @@
-- Looks good, set myself up and add to master list
def.children = {}
def.listKey = def.name:plural()
def._children = {}
def._listKey = def.name:plural()
setmetatable(def, p.containerClass)
container._classes[def.name] = def
@ -111,7 +113,7 @@
def.parent = container._classes[def.parent]
if def.parent then
table.insert(def.parent.children, def)
table.insert(def.parent._children, def)
end
return def
@ -119,6 +121,23 @@
---
-- Enumerate the child container class of a given class.
---
function p.containerClass:eachChildClass()
local children = self._children
local i = 0
return function ()
i = i + 1
if i <= #children then
return children[i]
end
end
end
---
-- Retrieve a container class by name.
--
@ -158,6 +177,32 @@
---
-- Create a new child container of the given class, with the specified name.
--
-- @param cc
-- The class of child container to be fetched.
-- @param key
-- A string key or array index for the container.
-- @param parent
-- The parent container instance.
-- @return
-- The child container instance.
---
function container:createChild(cc, key, parent)
self[cc._listKey] = self[cc._listKey] or {}
local list = self[cc._listKey]
local child = cc:new(key, parent)
table.insert(list, child)
list[key] = child
return child
end
---
-- Return an iterator for the child containers of a particular class.
--
@ -165,8 +210,8 @@
-- The class of child container to be enumerated.
---
function container:eachContainer(cc)
local children = self[cc.listKey] or {}
function container:eachChild(cc)
local children = self[cc._listKey] or {}
local i = 0
return function ()
i = i + 1
@ -180,28 +225,16 @@
---
-- Fetch the child container with the given container class and instance name.
-- If it doesn't exist, a new container is created.
--
-- @param cc
-- The class of child container to be fetched.
-- @param key
-- A string key or array index for the container. If a string key is
-- provided, the container will be created if it doesn't exist. If an
-- array index is provided, nil will be returned if it does not exist.
-- A string key or array index for the container.
-- @return
-- The child container instance.
---
function container:fetchContainer(cc, key)
self[cc.listKey] = self[cc.listKey] or {}
local children = self[cc.listKey]
local c = children[key]
if not c and type(key) == "string" then
c = cc:new(key, parent)
table.insert(children, c)
children[key] = c
end
return c
function container:fetchChild(cc, key)
self[cc._listKey] = self[cc._listKey] or {}
return self[cc._listKey][key]
end

View File

@ -10,14 +10,16 @@
--
premake.oven = {}
local oven = premake.oven
local solution = premake.solution
local project = premake.project
local config = premake.config
local fileconfig = premake.fileconfig
local configset = premake.configset
local context = premake.context
local p = premake
local solution = p.solution
local project = p.project
local config = p.config
local fileconfig = p.fileconfig
local configset = p.configset
local context = p.context
---
@ -34,15 +36,15 @@
---
function oven.bake(root)
-- I haven't yet ported the project objects to containers
local result = {}
for i, sln in ipairs(solution.list) do
local root = p.api.rootContainer()
root.solutions = root.solutions or {}
for i, sln in ipairs(root.solutions) do
result[i] = oven.bakeSolution(sln)
end
solution.list = result
-- Start container implementation
root.solutions = result
end
@ -104,6 +106,7 @@
-- store that for future reference
local projects = {}
sln.projects = sln.projects or {}
for i, prj in ipairs(sln.projects) do
projects[i] = oven.bakeProject(prj, ctx)
projects[prj.name] = projects[i]

View File

@ -31,7 +31,7 @@
---
function rules.each()
return p.api.rootContainer():eachContainer(_ruleContainerClass)
return p.api.rootContainer():eachChild(_ruleContainerClass)
end
@ -46,5 +46,5 @@
---
function rules.fetch(key)
return p.api.rootContaiiner():fetchContainer(_ruleContainerClass, key)
return p.api.rootContainer():fetchChild(_ruleContainerClass, key)
end

View File

@ -6,41 +6,12 @@
premake.solution = {}
local solution = premake.solution
local project = premake.project
local configset = premake.configset
local context = premake.context
local tree = premake.tree
local p = premake
local project = p.project
local context = p.context
local tree = p.tree
-- The list of defined solutions (which contain projects, etc.)
solution.list = {}
--
-- Create a new solution and add it to the session.
--
-- @param name
-- The new solution's name.
-- @return
-- A new solution object.
--
function solution.new(name)
sln = configset.new(premake.api.rootContainer())
setmetatable(sln, configset.metatable(sln))
sln.name = name
sln.projects = {}
sln.basedir = os.getcwd()
sln.filename = name
-- Add to master list keyed by both name and index
table.insert(premake.solution.list, sln)
premake.solution.list[name] = sln
return sln
end
--
@ -67,11 +38,13 @@
--
function solution.each()
local root = p.api.rootContainer()
local i = 0
return function ()
i = i + 1
if i <= #premake.solution.list then
return premake.solution.list[i]
if i <= #root.solutions then
return root.solutions[i]
end
end
end
@ -153,7 +126,10 @@
--
function solution.get(key)
return premake.solution.list[key]
local root = p.api.rootContainer()
if root.solutions then
return root.solutions[key]
end
end

View File

@ -339,7 +339,6 @@
stderr_capture = nil
premake.solution.list = { }
premake.clearWarnings()
premake.eol("\n")
premake.escaper(nil)