Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added support for basic token expansion; more work still needed

  • Loading branch information...
commit 87e6832bb0b49ab213db5bef541c1b33e4951794 1 parent ea18aa7
@starkos starkos authored
View
54 src/base/api.lua
@@ -19,12 +19,14 @@
{
kind = "list",
scope = "config",
+ tokens = true,
},
buildrule =
{
kind = "object",
scope = "config",
+ tokens = true,
},
configurations =
@@ -37,18 +39,21 @@
{
kind = "list",
scope = "config",
+ tokens = true,
},
debugenvs =
{
kind = "list",
scope = "config",
+ tokens = true,
},
defines =
{
kind = "list",
scope = "config",
+ tokens = true,
},
deploymentoptions =
@@ -56,6 +61,7 @@
kind = "list",
scope = "config",
usagecopy = true,
+ tokens = true,
},
excludes =
@@ -121,6 +127,7 @@
{
kind = "list",
scope = "config",
+ tokens = true,
},
includedirs =
@@ -128,6 +135,7 @@
kind = "dirlist",
scope = "config",
usagecopy = true,
+ tokens = true,
},
libdirs =
@@ -135,12 +143,14 @@
kind = "dirlist",
scope = "config",
linkagecopy = true,
+ tokens = true,
},
linkoptions =
{
kind = "list",
scope = "config",
+ tokens = true,
},
links =
@@ -155,12 +165,14 @@
return value
end,
linkagecopy = true,
+ tokens = true,
},
makesettings =
{
kind = "list",
scope = "config",
+ tokens = true,
},
platforms =
@@ -173,36 +185,42 @@
{
kind = "list",
scope = "config",
+ tokens = true,
},
prebuildcommands =
{
kind = "list",
scope = "config",
+ tokens = true,
},
prelinkcommands =
{
kind = "list",
scope = "config",
+ tokens = true,
},
resdefines =
{
kind = "list",
scope = "config",
+ tokens = true,
},
resincludedirs =
{
kind = "dirlist",
scope = "config",
+ tokens = true,
},
resoptions =
{
kind = "list",
scope = "config",
+ tokens = true,
},
trimpaths =
@@ -221,6 +239,7 @@
{
kind = "key-pathlist",
scope = "container",
+ tokens = true,
},
}
@@ -438,13 +457,15 @@
api.register {
name = "debugcommand",
scope = "config",
- kind = "path"
+ kind = "path",
+ tokens = true,
}
api.register {
name = "debugdir",
scope = "config",
- kind = "path"
+ kind = "path",
+ tokens = true,
}
api.register {
@@ -473,37 +494,43 @@
api.register {
name = "imagepath",
scope = "config",
- kind = "path"
+ kind = "path",
+ tokens = true,
}
api.register {
name = "implibdir",
scope = "config",
- kind = "path"
+ kind = "path",
+ tokens = true,
}
api.register {
name = "implibextension",
scope = "config",
kind = "string",
+ tokens = true,
}
api.register {
name = "implibname",
scope = "config",
kind = "string",
+ tokens = true,
}
api.register {
name = "implibprefix",
scope = "config",
kind = "string",
+ tokens = true,
}
api.register {
name = "implibsuffix",
scope = "config",
kind = "string",
+ tokens = true,
}
api.register {
@@ -532,25 +559,29 @@
api.register {
name = "location",
scope = "project",
- kind = "path"
+ kind = "path",
+ tokens = true,
}
api.register {
name = "objdir",
scope = "config",
- kind = "path"
+ kind = "path",
+ tokens = true,
}
api.register {
name = "pchheader",
scope = "config",
- kind = "string"
+ kind = "string",
+ tokens = true,
}
api.register {
name = "pchsource",
scope = "config",
- kind = "path"
+ kind = "path",
+ tokens = true,
}
api.register {
@@ -570,31 +601,36 @@
api.register {
name = "targetdir",
scope = "config",
- kind = "path"
+ kind = "path",
+ tokens = true,
}
api.register {
name = "targetextension",
scope = "config",
kind = "string",
+ tokens = true,
}
api.register {
name = "targetname",
scope = "config",
kind = "string",
+ tokens = true,
}
api.register {
name = "targetprefix",
scope = "config",
kind = "string",
+ tokens = true,
}
api.register {
name = "targetsuffix",
scope = "config",
kind = "string",
+ tokens = true,
}
api.register {
View
68 src/base/solution.lua
@@ -41,6 +41,69 @@
end
+
+--
+-- Assigns a unique objects directory to every configuration of every project
+-- in the solution, taking into any objdir settings into account. Ensures that
+-- builds from different configurations will not step on each others' object
+-- files. The path is built from these choices, in order:
+--
+-- [1] -> the objects directory as set in the config
+-- [2] -> [1] + the platform name
+-- [3] -> [2] + the build configuration name
+-- [4] -> [3] + the project name
+--
+
+ function solution.bakeobjdirs(sln)
+ -- function to compute the four options for a specific configuration
+ local function getobjdirs(cfg)
+ local dirs = {}
+
+ local dir = path.getabsolute(path.join(project.getlocation(cfg.project), cfg.objdir or "obj"))
+ table.insert(dirs, dir)
+
+ if cfg.platform then
+ dir = path.join(dir, cfg.platform)
+ table.insert(dirs, dir)
+ end
+
+ dir = path.join(dir, cfg.buildcfg)
+ table.insert(dirs, dir)
+
+ dir = path.join(dir, cfg.project.name)
+ table.insert(dirs, dir)
+
+ return dirs
+ end
+
+ -- walk all of the configs in the solution, and count the number of
+ -- times each obj dir gets used
+ local counts = {}
+ local configs = {}
+
+ for prj in premake.solution.eachproject_ng(sln) do
+ for cfg in project.eachconfig(prj, "objdir") do
+ -- get the dirs for this config, and remember the association
+ local dirs = getobjdirs(cfg)
+ configs[cfg] = dirs
+
+ for _, dir in ipairs(dirs) do
+ counts[dir] = (counts[dir] or 0) + 1
+ end
+ end
+ end
+
+ -- now walk the list again, and assign the first unique value
+ for cfg, dirs in pairs(configs) do
+ for _, dir in ipairs(dirs) do
+ if counts[dir] == 1 then
+ cfg.objdir = project.getrelative(cfg.project, dir)
+ end
+ end
+ end
+ end
+
+
--
-- Flattens the configurations of each of the projects in the solution
-- and stores the results, which are then returned from subsequent
@@ -269,9 +332,6 @@
return prj.rootcfg
else
-- "raw" version, accessible during scripting
- local cfg = oven.merge({}, sln)
- cfg = oven.merge(cfg, prj)
- cfg = oven.merge(cfg, project.getconfig(prj))
- return cfg
+ return oven.bake(prj)
end
end
View
74 src/project/oven.lua
@@ -15,6 +15,7 @@
local nomerge =
{
+ blocks = true,
keywords = true,
project = true,
removes = true,
@@ -56,6 +57,9 @@
cfg = {}
end
+ -- Merge container level (solution, project) in the result
+ cfg = oven.merge(cfg, container)
+
-- Attach a reference to the source container, as "solution" or "project"
cfg[type(container)] = container
@@ -94,7 +98,13 @@
--
function oven.bakefile(cfg, filename)
- local fcfg = {}
+ local fcfg = {
+ solution = cfg.solution,
+ project = cfg.project,
+ buildcfg = cfg.buildcfg,
+ platform = cfg.platform
+ }
+
filename = { filename }
for _, block in ipairs(cfg.solution.blocks) do
@@ -109,6 +119,7 @@
end
end
+ oven.expandtokens(cfg, fcfg)
return fcfg
end
@@ -117,16 +128,41 @@
-- Scan an object for expandable tokens, and expand them, in place.
--
- function oven.expandtokens(target)
+ function oven.expandtokens(cfg, filecfg)
-- build a context for the tokens to use
local context = {
_G = _G,
- sln = target.solution,
- prj = target.project,
- cfg = target
+ sln = cfg.solution,
+ prj = cfg.project,
+ cfg = cfg,
+ file = filecfg
}
- -- function to do the work of replacing the tokens
+ function expand(target, field)
+ local value = target[field]
+ if type(value) == "string" then
+ target[field] = oven.expandvalue(value, context)
+ else
+ for key in pairs(value) do
+ expand(value, key)
+ end
+ end
+ end
+
+ local target = filecfg or cfg
+ for key, value in pairs(target) do
+ -- to avoid unexpected errors or recursions, I only process
+ -- Premake's own API fields, and only those marked for it
+ local field = premake.fields[key]
+ if field ~= nil and field.tokens then
+ expand(target, key)
+ end
+ end
+ end
+
+
+ function oven.expandvalue(value, context)
+ -- function to do the work of replacing a single token
local expander = function(token)
-- convert the token into a function to execute
local func, err = loadstring("return " .. token)
@@ -144,28 +180,18 @@
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
-
+
+ return string.gsub(value, "%%{(.-)}", function(token)
+ result, err = expander(token)
+ if not result then
+ error(err, 0)
end
- end
+ return result
+ end)
end
+
--
--
-- Compare a list of block keywords against a set of filter terms. Keywords
View
4 tests/oven/test_keyvalues.lua
@@ -26,7 +26,7 @@
function suite.valuePresentInResult()
configmap { ["key"] = "value" }
- local cfg = oven.merge({}, sln)
+ local cfg = oven.bake(sln)
test.isequal("value", cfg.configmap["key"][1])
end
@@ -40,6 +40,6 @@
configmap { ["sln"] = "slnvalue" }
prj = project("MyProject")
configmap { ["prj"] = "prjvalue" }
- local cfg = oven.merge(oven.merge({}, sln), prj)
+ local cfg = oven.bake(prj)
test.istrue(cfg.configmap.sln ~= nil and cfg.configmap.prj ~= nil)
end
View
4 tests/oven/test_removes.lua
@@ -80,8 +80,6 @@
configurations { "Debug", "Release" }
local prj = project "MyProject"
removeconfigurations { "Debug" }
-
- cfg = oven.merge({}, sln)
- cfg = oven.merge(cfg, prj)
+ cfg = oven.bake(prj)
test.isequal({ "Release" }, cfg.configurations)
end
View
48 tests/oven/test_tokens.lua
@@ -8,6 +8,7 @@
local suite = T.oven_tokens
local oven = premake5.oven
local project = premake5.project
+ local config = premake5.config
--
@@ -21,6 +22,7 @@
name = "testapi",
kind = "string",
scope = "config",
+ tokens = true
}
sln, prj = test.createsolution()
@@ -55,3 +57,49 @@
prepare()
test.isequal("bin/MyProject/Debug", cfg.testapi)
end
+
+
+--
+-- Verify that project level values are expanded too.
+--
+
+ function suite.doesExpandTokens_onProjects()
+ location "build/%{prj.name}"
+ prj = premake.solution.getproject_ng(sln, 1)
+ test.isequal(os.getcwd().."/build/MyProject", prj.location)
+ end
+
+
+--
+-- Verify that file-specific values are expanded.
+--
+
+ function suite.doesExpandTokens_onFileCfg()
+ files { "hello.c" }
+ configuration "**/hello.c"
+ testapi "%{cfg.buildcfg}"
+ prepare()
+ local fcfg = config.getfileconfig(cfg, os.getcwd().."/hello.c")
+ test.isequal("Debug", fcfg.testapi)
+ end
+
+
+--
+-- Verify handling of tokens in a build rule.
+--
+
+ function suite.doesExpandFileTokens_inBuildRules()
+ files { "shaders/hello.cg" }
+ configuration { "**.cg" }
+ buildrule {
+ commands = {
+ "cgc --profile gp5vp %{file.path} -o %{cfg.objdir}/%{file.basename}.gxp",
+ },
+ outputs = {
+ "%{cfg.objdir}/%{file.basename}.o"
+ }
+ }
+ prepare()
+ local fcfg = config.getfileconfig(cfg, os.getcwd().."/shaders/hello.cg")
+ test.isequal("cgc --profile gp5vp shaders/hello.cg -o obj/hello.gxp", fcfg.buildrule.commands[1])
+ end

0 comments on commit 87e6832

Please sign in to comment.
Something went wrong with that request. Please try again.