Port unique objects directory logic to the new platforms API
This commit is contained in:
parent
9749188cc4
commit
fa4813cf3b
@ -82,8 +82,11 @@
|
||||
local architecture = vstudio.architecture(cfg)
|
||||
_p(3,'Name="%s|%s"', premake.esc(platform), premake.esc(architecture))
|
||||
|
||||
_p(3,'OutputDirectory="%s"', premake.esc(config.gettargetinfo(cfg).directory))
|
||||
_p(3,'IntermediateDirectory="%s"', premake.esc("obj\\" .. cfg.buildcfg .. "\\" .. cfg.project.name))
|
||||
local outdir = path.translate(config.gettargetinfo(cfg).directory)
|
||||
_p(3,'OutputDirectory="%s"', premake.esc(outdir))
|
||||
|
||||
local objdir = path.translate(config.getuniqueobjdir(cfg))
|
||||
_p(3,'IntermediateDirectory="%s"', premake.esc(objdir))
|
||||
|
||||
local cfgtype
|
||||
if (cfg.kind == "SharedLib") then
|
||||
|
@ -73,7 +73,7 @@
|
||||
debugformat =
|
||||
{
|
||||
kind = "string",
|
||||
scope = "container",
|
||||
scope = "config",
|
||||
allowed = {
|
||||
"c7",
|
||||
}
|
||||
@ -596,20 +596,15 @@
|
||||
error(err, 4)
|
||||
end
|
||||
|
||||
if not container[fieldname] then
|
||||
container[fieldname] = {}
|
||||
end
|
||||
|
||||
if type(values) ~= "table" then
|
||||
error("invalid value; table expected", 4)
|
||||
end
|
||||
|
||||
local field = container[fieldname]
|
||||
container[fieldname] = container[fieldname] or {}
|
||||
local field = container[fieldname] or {}
|
||||
|
||||
for key,value in pairs(values) do
|
||||
if not field[key] then
|
||||
field[key] = {}
|
||||
end
|
||||
field[key] = field[key] or {}
|
||||
table.insertflat(field[key], value)
|
||||
end
|
||||
|
||||
|
@ -45,6 +45,11 @@
|
||||
--
|
||||
|
||||
function config.gettargetinfo(cfg)
|
||||
-- have I cached results from a previous call?
|
||||
if cfg.targetinfo then
|
||||
return cfg.targetinfo
|
||||
end
|
||||
|
||||
local basedir = project.getlocation(prj)
|
||||
|
||||
local directory = cfg.targetdir or basedir
|
||||
@ -108,10 +113,62 @@
|
||||
info.prefix = prefix
|
||||
info.suffix = suffix
|
||||
|
||||
if config.getpathstyle(cfg) == premake.WINDOWS then
|
||||
info.directory = path.translate(info.directory, "\\")
|
||||
info.fullpath = path.translate(info.fullpath, "\\")
|
||||
end
|
||||
|
||||
-- cache the results for future calls
|
||||
cfg.targetinfo = info
|
||||
return info
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve the objects (or intermediates) directory for this configuration
|
||||
-- that is unique for this entire solution. This ensures that builds of
|
||||
-- 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
|
||||
--
|
||||
--
|
||||
-- @param cfg
|
||||
-- The configuration object to query.
|
||||
-- @return
|
||||
-- A objects directory that is unique for the solution.
|
||||
--
|
||||
|
||||
function config.getuniqueobjdir(cfg)
|
||||
-- compute the four options for a specific configuration
|
||||
local function getobjdirs(cfg)
|
||||
local dirs = { }
|
||||
dirs[1] = path.getabsolute(path.join(project.getlocation(cfg.project), cfg.objdir or "obj"))
|
||||
dirs[2] = path.join(dirs[1], cfg.platform or "")
|
||||
dirs[3] = path.join(dirs[2], cfg.buildcfg)
|
||||
dirs[4] = path.join(dirs[3], cfg.project.name)
|
||||
return dirs
|
||||
end
|
||||
|
||||
-- walk all of the configs in the solution, and count the number of
|
||||
-- times each obj dir gets used
|
||||
local counts = {}
|
||||
for sln in premake.solution.each() do
|
||||
for _, prj in ipairs(sln.projects) do
|
||||
for testcfg in project.eachconfig(prj, "objdir") do
|
||||
local dirs = getobjdirs(testcfg)
|
||||
for _, dir in ipairs(dirs) do
|
||||
counts[dir] = (counts[dir] or 0) + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- now test for dirs for the request configuration, and use the
|
||||
-- first one that isn't in conflict
|
||||
local dirs = getobjdirs(cfg)
|
||||
for _, dir in ipairs(dirs) do
|
||||
if counts[dir] == 1 then
|
||||
local prjlocation = project.getlocation(cfg.project)
|
||||
return path.getrelative(prjlocation, dir)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -29,11 +29,14 @@
|
||||
-- @param filterterms
|
||||
-- An optional list of filter terms. Only configuration blocks which
|
||||
-- match all of the terms in the list will be included in the result.
|
||||
-- @returns
|
||||
-- @param filterfield
|
||||
-- An optional configuration field name. If set, that specific field,
|
||||
-- and only that field, will be baked and returned.
|
||||
-- @return
|
||||
-- A configuration object.
|
||||
--
|
||||
|
||||
function oven.bake(container, filterTerms)
|
||||
function oven.bake(container, filterTerms, filterField)
|
||||
filterTerms = filterTerms or {}
|
||||
|
||||
-- keyword/term tests are case-insensitive; convert all terms to lowercase
|
||||
@ -45,7 +48,7 @@
|
||||
-- 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)
|
||||
cfg = oven.bake(container.solution, filterTerms, filterField)
|
||||
else
|
||||
cfg = {}
|
||||
end
|
||||
@ -57,7 +60,7 @@
|
||||
-- into my configuration-in-progress, if they pass the keyword filter
|
||||
for _, block in ipairs(container.blocks) do
|
||||
if oven.filter(block, filterTerms) then
|
||||
oven.merge(cfg, block)
|
||||
oven.merge(cfg, block, filterField)
|
||||
end
|
||||
end
|
||||
|
||||
@ -130,21 +133,59 @@
|
||||
-- Merge from an individual block into the configuration object.
|
||||
--
|
||||
-- @param cfg
|
||||
-- The configuration currently being built.
|
||||
-- The configuration currently being built; will contain the new values.
|
||||
-- @param block
|
||||
-- The block containing the values to merge.
|
||||
-- @param filterField
|
||||
-- An optional configuration field name. If present, only this specific
|
||||
-- field will be merged.
|
||||
-- @return
|
||||
-- The configuration object, which is also modified in place.
|
||||
--
|
||||
|
||||
function oven.merge(cfg, block)
|
||||
for key, value in pairs(block) do
|
||||
if not nomerge[key] then
|
||||
if type(value) == "table" then
|
||||
cfg[key] = oven.mergetables(cfg[key] or {}, value)
|
||||
else
|
||||
cfg[key] = value
|
||||
function oven.merge(cfg, block, filterField)
|
||||
if filterField then
|
||||
oven.mergefield(cfg, filterField, block[filterField])
|
||||
else
|
||||
for key, value in pairs(block) do
|
||||
if not nomerge[key] then
|
||||
oven.mergefield(cfg, key, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
return cfg
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Merges a single field from a configuration block into a baked
|
||||
-- configuration object.
|
||||
-- @param cfg
|
||||
-- The configuration currently being built; will contain the new values.
|
||||
-- @param name
|
||||
-- The name of the field being merged.
|
||||
-- @param value
|
||||
-- The value of the field being merged.
|
||||
--
|
||||
|
||||
function oven.mergefield(cfg, name, value)
|
||||
-- is this field part of the Premake API? If no, just copy and done
|
||||
local field = premake.fields[name]
|
||||
if not field then
|
||||
cfg[name] = value
|
||||
return
|
||||
end
|
||||
|
||||
if field.kind == "keyvalue" or field.kind == "keypath" then
|
||||
cfg[name] = cfg[name] or {}
|
||||
for key, keyvalue in pairs(value) do
|
||||
cfg[name][key] = oven.mergetables(cfg[name][key] or {}, keyvalue)
|
||||
end
|
||||
elseif type(value) == "table" then
|
||||
cfg[name] = oven.mergetables(cfg[name] or {}, value)
|
||||
else
|
||||
cfg[name] = value
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -161,7 +202,11 @@
|
||||
|
||||
function oven.mergetables(original, additions)
|
||||
for _, item in ipairs(additions) do
|
||||
table.insert(original, item)
|
||||
-- prevent duplicates
|
||||
if not original[item] then
|
||||
original[item] = item
|
||||
table.insert(original, item)
|
||||
end
|
||||
end
|
||||
return original
|
||||
end
|
||||
|
@ -15,11 +15,14 @@
|
||||
--
|
||||
-- @param prj
|
||||
-- The project object to query.
|
||||
-- @param field
|
||||
-- An optional field name. If specified, only that field will be
|
||||
-- included in the resulting configuration object.
|
||||
-- @return
|
||||
-- An iterator function returning configuration objects.
|
||||
--
|
||||
|
||||
function project.eachconfig(prj)
|
||||
function project.eachconfig(prj, field)
|
||||
local buildconfigs = prj.solution.configurations or {}
|
||||
local platforms = prj.solution.platforms or {}
|
||||
|
||||
@ -37,7 +40,7 @@
|
||||
return nil
|
||||
end
|
||||
|
||||
return project.getconfig(prj, buildconfigs[i], platforms[j])
|
||||
return project.getconfig(prj, buildconfigs[i], platforms[j], field)
|
||||
end
|
||||
end
|
||||
|
||||
@ -52,12 +55,15 @@
|
||||
-- The name of the build configuration on which to filter.
|
||||
-- @param platform
|
||||
-- Optional; the name of the platform on which to filter.
|
||||
-- @param field
|
||||
-- An optional field name. If specified, only that field will be
|
||||
-- included in the resulting configuration object.
|
||||
-- @return
|
||||
-- A configuration object.
|
||||
--
|
||||
|
||||
function project.getconfig(prj, buildcfg, platform)
|
||||
local cfg = premake5.oven.bake(prj, { buildcfg, platform })
|
||||
function project.getconfig(prj, buildcfg, platform, field)
|
||||
local cfg = premake5.oven.bake(prj, { buildcfg, platform }, field)
|
||||
cfg.buildcfg = buildcfg
|
||||
cfg.platform = platform
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="."
|
||||
IntermediateDirectory="obj\Debug\MyProject"
|
||||
IntermediateDirectory="obj\Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
>
|
||||
@ -72,3 +72,18 @@
|
||||
Name="Debug x64|x64"
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- The output directory should use backslashes
|
||||
--
|
||||
|
||||
function suite.usesX64Architecture_onX64Platform()
|
||||
targetdir("../bin")
|
||||
prepare()
|
||||
test.capture [[
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="..\bin"
|
||||
]]
|
||||
end
|
||||
|
@ -1,99 +0,0 @@
|
||||
--
|
||||
-- tests/baking/test_merging.lua
|
||||
-- Verifies different field types are merged properly during baking.
|
||||
-- Copyright (c) 2011 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
T.baking_merging = { }
|
||||
local suite = T.baking_merging
|
||||
|
||||
--
|
||||
-- Setup code
|
||||
--
|
||||
|
||||
local sln, prj, cfg
|
||||
function suite.setup()
|
||||
sln = solution "MySolution"
|
||||
configurations { "Debug", "Release" }
|
||||
end
|
||||
|
||||
local function prepare()
|
||||
premake.bake.buildconfigs()
|
||||
prj = premake.solution.getproject(sln, 1)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- String value tests
|
||||
--
|
||||
|
||||
function suite.Strings_AreReplaced()
|
||||
kind "SharedLib"
|
||||
project "MyProject"
|
||||
kind "StaticLib"
|
||||
prepare()
|
||||
test.isequal("StaticLib", prj.kind)
|
||||
end
|
||||
|
||||
function suite.Strings_KeepPreviousValue()
|
||||
kind "SharedLib"
|
||||
project "MyProject"
|
||||
prepare()
|
||||
test.isequal("SharedLib", prj.kind)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- List tests
|
||||
--
|
||||
|
||||
function suite.Lists_KeepPreviousValue()
|
||||
project "MyProject"
|
||||
prepare()
|
||||
test.isequal("Debug:Release", table.concat(prj.configurations, ":"))
|
||||
end
|
||||
|
||||
function suite.Lists_AreJoined()
|
||||
defines { "SOLUTION" }
|
||||
project "MyProject"
|
||||
defines { "PROJECT" }
|
||||
prepare()
|
||||
test.isequal("SOLUTION:PROJECT", table.concat(prj.defines, ":"))
|
||||
end
|
||||
|
||||
function suite.Lists_RemoveDuplicates()
|
||||
defines { "SOLUTION", "DUPLICATE" }
|
||||
project "MyProject"
|
||||
defines { "PROJECT", "DUPLICATE" }
|
||||
prepare()
|
||||
test.isequal("SOLUTION:DUPLICATE:PROJECT", table.concat(prj.defines, ":"))
|
||||
end
|
||||
|
||||
function suite.Lists_FlattensNestedTables()
|
||||
defines { "ROOT", { "NESTED" } }
|
||||
project "MyProject"
|
||||
prepare()
|
||||
test.isequal("ROOT:NESTED", table.concat(prj.defines, ":"))
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Key/value tests
|
||||
--
|
||||
|
||||
function suite.KeyValue_AreMerged()
|
||||
vpaths { ["Solution"] = "*.sln" }
|
||||
project "MyProject"
|
||||
vpaths { ["Project"] = "*.prj" }
|
||||
prepare()
|
||||
test.isequal({"*.sln"}, prj.vpaths["Solution"])
|
||||
test.isequal({"*.prj"}, prj.vpaths["Project"])
|
||||
end
|
||||
|
||||
function suite.KeyValue_MergesValues()
|
||||
vpaths { ["Solution"] = "*.sln", ["Project"] = "*.prj" }
|
||||
project "MyProject"
|
||||
vpaths { ["Project"] = "*.prjx" }
|
||||
prepare()
|
||||
test.isequal({"*.prj","*.prjx"}, prj.vpaths["Project"])
|
||||
end
|
92
tests/config/test_objdir.lua
Executable file
92
tests/config/test_objdir.lua
Executable file
@ -0,0 +1,92 @@
|
||||
--
|
||||
-- tests/config/test_objdir.lua
|
||||
-- Test the config object's build target accessor.
|
||||
-- Copyright (c) 2012 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
T.config_objdir = { }
|
||||
local suite = T.config_objdir
|
||||
local config = premake5.config
|
||||
|
||||
|
||||
--
|
||||
-- Setup and teardown
|
||||
--
|
||||
|
||||
local sln, prj, cfg
|
||||
|
||||
function suite.setup()
|
||||
_ACTION = "test"
|
||||
sln = solution("MySolution")
|
||||
prj = project("MyProject")
|
||||
system "macosx"
|
||||
end
|
||||
|
||||
local function prepare()
|
||||
local platforms = sln.platforms or {}
|
||||
cfg = premake5.project.getconfig(prj, "Debug", platforms[1])
|
||||
return config.getuniqueobjdir(cfg)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Objects directory should "obj" by default.
|
||||
--
|
||||
|
||||
function suite.directoryIsObj_onNoValueSet()
|
||||
configurations { "Debug" }
|
||||
local dir = prepare()
|
||||
test.isequal("obj", dir)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If a conflict occurs between platforms, the platform names should
|
||||
-- be used to make unique.
|
||||
--
|
||||
|
||||
function suite.directoryIncludesPlatform_onConflictAndPlatform()
|
||||
configurations { "Debug" }
|
||||
platforms { "x32", "x64" }
|
||||
local dir = prepare()
|
||||
test.isequal("obj/x32", dir)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If a conflict occurs between build configurations, the build
|
||||
-- configuration names should be used to make unique.
|
||||
--
|
||||
|
||||
function suite.directoryIncludesBuildCfg_onConflictAndNoPlatforms()
|
||||
configurations { "Debug", "Release" }
|
||||
local dir = prepare()
|
||||
test.isequal("obj/Debug", dir)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If a conflict occurs between both build configurations and platforms,
|
||||
-- both should be used to make unique.
|
||||
--
|
||||
|
||||
function suite.directoryIncludesBuildCfg_onConflictAndNoPlatforms()
|
||||
configurations { "Debug", "Release" }
|
||||
platforms { "x32", "x64" }
|
||||
local dir = prepare()
|
||||
test.isequal("obj/x32/Debug", dir)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If a conflict occurs between projects, the project name should be
|
||||
-- used to make unique.
|
||||
--
|
||||
|
||||
function suite.directoryIncludesBuildCfg_onConflictAndNoPlatforms()
|
||||
configurations { "Debug", "Release" }
|
||||
project "MyProject2"
|
||||
local dir = prepare()
|
||||
test.isequal("obj/Debug/MyProject", dir)
|
||||
end
|
||||
|
@ -49,19 +49,6 @@
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- A backslash path separator should be used when the target
|
||||
-- action requires one.
|
||||
--
|
||||
|
||||
function suite.directoryUsesBackslash_onWindows()
|
||||
_ACTION = "vs2008"
|
||||
targetdir "../bin"
|
||||
i = prepare()
|
||||
test.isequal("..\\bin", i.directory)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Base name should use the project name by default.
|
||||
--
|
||||
|
@ -59,6 +59,7 @@
|
||||
|
||||
-- Project API tests
|
||||
dofile("test_project.lua")
|
||||
dofile("config/test_objdir.lua")
|
||||
dofile("config/test_targetinfo.lua")
|
||||
dofile("project/test_baking.lua")
|
||||
dofile("project/test_eachconfig.lua")
|
||||
@ -67,7 +68,6 @@
|
||||
|
||||
-- Baking tests
|
||||
dofile("base/test_baking.lua")
|
||||
dofile("baking/test_merging.lua")
|
||||
|
||||
-- Clean tests
|
||||
dofile("actions/test_clean.lua")
|
||||
|
@ -1,7 +1,7 @@
|
||||
--
|
||||
-- tests/project/test_baking.lua
|
||||
-- Test the Premake 5.0 oven.
|
||||
-- Copyright (c) 2011 Jason Perkins and the Premake project
|
||||
-- Test the Premake oven, which handles flattening of configurations.
|
||||
-- Copyright (c) 2011-2012 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
T.project_baking = { }
|
||||
@ -53,6 +53,7 @@
|
||||
test.isequal(0, #cfg.defines)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Values defined at the solution level should be included in configurations
|
||||
-- built from the solution.
|
||||
@ -139,9 +140,9 @@
|
||||
|
||||
function suite.configValuePresent_ifMatchingFilterTerm()
|
||||
configuration("Debug")
|
||||
defines("DEBUG")
|
||||
kind "SharedLib"
|
||||
cfg = oven.bake(sln, {"Debug"})
|
||||
test.isequal("DEBUG", cfg.defines[1])
|
||||
test.isequal("SharedLib", cfg.kind)
|
||||
end
|
||||
|
||||
|
||||
@ -174,3 +175,60 @@
|
||||
cfg = oven.bake(sln)
|
||||
test.isnil(cfg.keywords)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Requests for a single field should return just that value.
|
||||
--
|
||||
|
||||
function suite.fieldValueReturned_onFilterFieldPresent()
|
||||
configuration("Debug")
|
||||
kind "SharedLib"
|
||||
cfg = oven.bake(sln, {"Debug"}, "kind")
|
||||
test.isequal("SharedLib", cfg.kind)
|
||||
end
|
||||
|
||||
function suite.otherFieldsNotReturned_onFilterFieldPresent()
|
||||
configuration("Debug")
|
||||
kind("SharedLib")
|
||||
defines("DEBUG")
|
||||
cfg = oven.bake(sln, {"Debug"}, "kind")
|
||||
test.isnil(cfg.defines)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Duplicate values should be removed from list values.
|
||||
--
|
||||
|
||||
function suite.removesDuplicateValues()
|
||||
defines { "SOLUTION", "DUPLICATE" }
|
||||
prj = project("MyProject")
|
||||
defines { "PROJECT", "DUPLICATE" }
|
||||
cfg = oven.bake(prj, {"Debug"})
|
||||
test.isequal("SOLUTION|DUPLICATE|PROJECT", table.concat(cfg.defines, "|"))
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Multiple calls to key-value functions should be merged into a single key-value table.
|
||||
-- I don't have any config-level key-value fields yet, so have to bake project instead.
|
||||
--
|
||||
|
||||
function suite.keyValuesAreMerged_onMultipleKeys()
|
||||
vpaths { ["Solution"] = "*.sln" }
|
||||
prj = project("MyProject")
|
||||
vpaths { ["Project"] = "*.prj" }
|
||||
cfg = oven.merge(oven.merge({}, sln), prj)
|
||||
test.isequal({"*.sln"}, cfg.vpaths["Solution"])
|
||||
test.isequal({"*.prj"}, cfg.vpaths["Project"])
|
||||
end
|
||||
|
||||
|
||||
function suite.keyValuesAreMerged_onMultipleValues()
|
||||
vpaths { ["Solution"] = "*.sln", ["Project"] = "*.prj" }
|
||||
prj = project "MyProject"
|
||||
vpaths { ["Project"] = "*.prjx" }
|
||||
cfg = oven.merge(oven.merge({}, sln), prj)
|
||||
test.isequal({"*.prj","*.prjx"}, cfg.vpaths["Project"])
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user