Enable token expansions on simple string fields

This commit is contained in:
Jason Perkins 2012-04-18 15:15:56 -04:00
parent 2c339eacfa
commit b930597f58
4 changed files with 142 additions and 13 deletions

View File

@ -16,7 +16,9 @@
local nomerge =
{
keywords = true,
removes = true
project = true,
removes = true,
solution = true,
}
@ -41,14 +43,15 @@
filterTerms = filterTerms or {}
-- keyword/term tests are case-insensitive; convert all terms to lowercase
local casedTerms = {}
for key, value in pairs(filterTerms) do
filterTerms[key] = value:lower()
casedTerms[key] = value:lower()
end
-- If I'm baking a project, start with the values from the solution level
local cfg
if container.solution then
cfg = oven.bake(container.solution, filterTerms, filterField)
cfg = oven.bake(container.solution, casedTerms, filterField)
else
cfg = {}
end
@ -59,13 +62,19 @@
-- Walk the blocks available in this container, and merge their values
-- into my configuration-in-progress, if they pass the keyword filter
for _, block in ipairs(container.blocks) do
if oven.filter(block, filterTerms) then
if oven.filter(block, casedTerms) then
oven.merge(cfg, block, filterField)
end
end
-- Remember the list of terms used to create this config
cfg.terms = filterTerms
-- Store the filter terms in the configuration (i.e. buildcfg, platform)
cfg.terms = casedTerms
for key, value in pairs(filterTerms) do
cfg[key] = value
end
-- Expand inline tokens
oven.expandtokens(cfg)
return cfg
end
@ -104,6 +113,60 @@
end
--
-- Scan an object for expandable tokens, and expand them, in place.
--
function oven.expandtokens(target)
-- build a context for the tokens to use
local context = {
_G = _G,
sln = target.solution,
prj = target.project,
cfg = target
}
-- function to do the work of replacing the tokens
local expander = function(token)
-- convert the token into a function to execute
local func, err = loadstring("return " .. token)
if not func then
return nil, err
end
-- give the function access to the project objects
setfenv(func, context)
-- run it and return the result
local result = func()
if not result then
return nil, "Invalid token '" .. token .. "'"
end
return result
end
-- scan the object and replace all tokens encountered
for key, value in pairs(target) do
if type(value) == "string" then
target[key] = string.gsub(value, "%%{(.-)}", function(token)
result, err = expander(token)
if not result then
error(err, 0)
end
return result
end)
elseif not nomerge[key] then
-- recurse
end
end
end
--
--
-- Compare a list of block keywords against a set of filter terms. Keywords
-- are Lua patterns applied to the block when it is specified in the script
@ -215,6 +278,9 @@
oven.remove(cfg, block.removes, filterField)
end
-- remember the container object (solution, project, etc.)
cfg[type(block)] = block
return cfg
end

View File

@ -97,6 +97,9 @@
--
function project.getconfig(prj, buildcfg, platform, field, filename)
-- make sure I've got the actual project, and not a baked configuration
prj = prj.project or prj
-- check for a cached version, built by bakeconfigs()
if not filename and prj.configs then
local key = (buildcfg or "*") .. (platform or "")
@ -114,14 +117,16 @@
end
-- Figure out the target operating environment for this configuration
local cfg = premake5.oven.bake(prj, { buildcfg, platform, _ACTION }, "system")
system = cfg.system or system or premake.action.current().os or os.get()
local filter = {
["buildcfg"] = buildcfg,
["platform"] = platform,
["action"] = _ACTION
}
local cfg = premake5.oven.bake(prj, filter, "system")
filter.system = cfg.system or system or premake.action.current().os or os.get()
cfg = premake5.oven.bake(prj, { buildcfg, platform, _ACTION, system }, field)
cfg.project = prj
cfg.buildcfg = buildcfg
cfg.platform = platform
cfg.system = system
cfg = premake5.oven.bake(prj, filter, field)
cfg.architecture = cfg.architecture or architecture
return cfg
end

View File

@ -0,0 +1,57 @@
--
-- tests/oven/test_tokens.lua
-- Test the Premake oven's handling of tokens.
-- Copyright (c) 2012 Jason Perkins and the Premake project
--
T.oven_tokens = { }
local suite = T.oven_tokens
local oven = premake5.oven
local project = premake5.project
--
-- Setup and teardown
--
local sln, prj, cfg
function suite.setup()
premake.api.register {
name = "testapi",
kind = "string",
scope = "config",
}
sln, prj = test.createsolution()
end
function suite.teardown()
testapi = nil
end
function prepare()
cfg = project.getconfig(prj, "Debug")
end
--
-- Verify that solution values can be expanded.
--
function suite.doesExpandSolutionValues()
testapi "bin/%{sln.name}"
prepare()
test.isequal("bin/MySolution", cfg.testapi)
end
--
-- Verify that multiple values can be expanded.
--
function suite.doesExpandMultipleValues()
testapi "bin/%{prj.name}/%{cfg.buildcfg}"
prepare()
test.isequal("bin/MyProject/Debug", cfg.testapi)
end

View File

@ -89,6 +89,7 @@
dofile("oven/test_lists.lua")
dofile("oven/test_objects.lua")
dofile("oven/test_removes.lua")
dofile("oven/test_tokens.lua")
-- Toolset tests
dofile("tools/test_gcc.lua")