Merge more file configuration functionality into new fileconfig class
This commit is contained in:
parent
3abbbc93f9
commit
b3fdb1457d
@ -9,6 +9,7 @@
|
||||
local cpp = premake.make.cpp
|
||||
local project = premake5.project
|
||||
local config = premake5.config
|
||||
local fileconfig = premake5.fileconfig
|
||||
|
||||
|
||||
--
|
||||
@ -160,8 +161,8 @@
|
||||
-- check to see if this file has custom rules
|
||||
local rules
|
||||
for cfg in project.eachconfig(prj) do
|
||||
local filecfg = config.getfileconfig(cfg, node.abspath)
|
||||
if config.hasCustomBuildRule(filecfg) then
|
||||
local filecfg = fileconfig.getconfig(node, cfg)
|
||||
if fileconfig.hasCustomBuildRule(filecfg) then
|
||||
rules = true
|
||||
break
|
||||
end
|
||||
@ -196,7 +197,7 @@
|
||||
|
||||
function cpp.customfilerules(prj, node)
|
||||
for cfg in project.eachconfig(prj) do
|
||||
local filecfg = config.getfileconfig(cfg, node.abspath)
|
||||
local filecfg = fileconfig.getconfig(node, cfg)
|
||||
if filecfg then
|
||||
_x('ifeq ($(config),%s)', cfg.shortname)
|
||||
|
||||
@ -286,10 +287,10 @@
|
||||
local inall = true
|
||||
local custom = false
|
||||
for cfg in project.eachconfig(prj) do
|
||||
local filecfg = config.getfileconfig(cfg, node.abspath)
|
||||
local filecfg = fileconfig.getconfig(node, cfg)
|
||||
if filecfg and not filecfg.flags.ExcludeFromBuild then
|
||||
incfg[cfg] = filecfg
|
||||
custom = config.hasCustomBuildRule(filecfg)
|
||||
custom = fileconfig.hasCustomBuildRule(filecfg)
|
||||
else
|
||||
inall = false
|
||||
end
|
||||
|
@ -5,10 +5,12 @@
|
||||
--
|
||||
|
||||
premake.vstudio.cs2005 = {}
|
||||
|
||||
local vstudio = premake.vstudio
|
||||
local cs2005 = premake.vstudio.cs2005
|
||||
local project = premake5.project
|
||||
local config = premake5.config
|
||||
local fileconfig = premake5.fileconfig
|
||||
local dotnet = premake.tools.dotnet
|
||||
|
||||
|
||||
@ -125,7 +127,7 @@
|
||||
local tr = project.getsourcetree(prj)
|
||||
premake.tree.traverse(tr, {
|
||||
onleaf = function(node, depth)
|
||||
local filecfg = config.getfileconfig(cfg, node.abspath)
|
||||
local filecfg = fileconfig.getconfig(node, cfg)
|
||||
local fname = path.translate(node.relpath)
|
||||
|
||||
-- Files that live outside of the project tree need to be "linked"
|
||||
|
@ -5,11 +5,13 @@
|
||||
--
|
||||
|
||||
premake.vstudio.vc200x = {}
|
||||
|
||||
local vstudio = premake.vstudio
|
||||
local vc200x = premake.vstudio.vc200x
|
||||
local config = premake5.config
|
||||
local context = premake.context
|
||||
local project = premake5.project
|
||||
local config = premake5.config
|
||||
local fileconfig = premake5.fileconfig
|
||||
|
||||
|
||||
---
|
||||
@ -823,7 +825,7 @@
|
||||
|
||||
function vc200x.fileConfiguration(cfg, node, depth)
|
||||
|
||||
local filecfg = config.getfileconfig(cfg, node.abspath)
|
||||
local filecfg = fileconfig.getconfig(node, cfg)
|
||||
|
||||
-- Generate the individual sections of the file configuration
|
||||
-- element and capture the results to a buffer. I will only
|
||||
@ -999,7 +1001,7 @@
|
||||
|
||||
function vc200x.compilerToolName(cfg, filecfg, depth)
|
||||
local name
|
||||
if config.hasCustomBuildRule(filecfg) then
|
||||
if fileconfig.hasCustomBuildRule(filecfg) then
|
||||
name = "VCCustomBuildTool"
|
||||
else
|
||||
name = iif(cfg.system == premake.XBOX360, "VCCLX360CompilerTool", "VCCLCompilerTool")
|
||||
@ -1020,7 +1022,7 @@
|
||||
|
||||
|
||||
function vc200x.customBuildTool(filecfg, depth)
|
||||
if config.hasCustomBuildRule(filecfg) then
|
||||
if fileconfig.hasCustomBuildRule(filecfg) then
|
||||
_x(depth, 'CommandLine="%s"', table.concat(filecfg.buildcommands,'\r\n'))
|
||||
|
||||
local outputs = project.getrelative(filecfg.project, filecfg.buildoutputs)
|
||||
@ -1098,7 +1100,7 @@
|
||||
if #deps > 0 then
|
||||
|
||||
-- This is a little odd: Visual Studio wants the "relative path to project"
|
||||
-- to relative to the *solution*, rather than the project doing the
|
||||
-- to be relative to the *solution*, rather than the project doing the
|
||||
-- referencing. Which, in theory, would break if the project is included
|
||||
-- in more than one solution. But that's how they do it.
|
||||
|
||||
|
@ -5,10 +5,12 @@
|
||||
--
|
||||
|
||||
premake.vstudio.vc2010 = {}
|
||||
|
||||
local vc2010 = premake.vstudio.vc2010
|
||||
local vstudio = premake.vstudio
|
||||
local project = premake5.project
|
||||
local config = premake5.config
|
||||
local fileconfig = premake5.fileconfig
|
||||
local tree = premake.tree
|
||||
|
||||
|
||||
@ -444,7 +446,7 @@
|
||||
for cfg in project.eachconfig(prj) do
|
||||
local condition = vc2010.condition(cfg)
|
||||
|
||||
local filecfg = config.getfileconfig(cfg, file.abspath)
|
||||
local filecfg = fileconfig.getconfig(file, cfg)
|
||||
vc2010.excludedFromBuild(cfg, filecfg)
|
||||
if filecfg then
|
||||
vc2010.objectFileName(filecfg)
|
||||
@ -471,8 +473,8 @@
|
||||
|
||||
for cfg in project.eachconfig(prj) do
|
||||
local condition = vc2010.condition(cfg)
|
||||
local filecfg = config.getfileconfig(cfg, file.abspath)
|
||||
if config.hasCustomBuildRule(filecfg) then
|
||||
local filecfg = fileconfig.getconfig(file, cfg)
|
||||
if fileconfig.hasCustomBuildRule(filecfg) then
|
||||
local commands = table.concat(filecfg.buildcommands,'\r\n')
|
||||
_p(3,'<Command %s>%s</Command>', condition, premake.esc(commands))
|
||||
|
||||
@ -508,8 +510,8 @@
|
||||
-- then they all must be marked as custom build
|
||||
local hasbuildrule = false
|
||||
for cfg in project.eachconfig(prj) do
|
||||
local filecfg = config.getfileconfig(cfg, node.abspath)
|
||||
if config.hasCustomBuildRule(filecfg) then
|
||||
local filecfg = fileconfig.getconfig(node, cfg)
|
||||
if fileconfig.hasCustomBuildRule(filecfg) then
|
||||
hasbuildrule = true
|
||||
break
|
||||
end
|
||||
|
@ -213,29 +213,6 @@
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve the configuration settings for a specific file.
|
||||
--
|
||||
-- @param cfg
|
||||
-- The configuration object to query.
|
||||
-- @param filename
|
||||
-- The full, absolute path of the file to query.
|
||||
-- @return
|
||||
-- A configuration object for the file, or nil if the file is
|
||||
-- not included in this configuration.
|
||||
--
|
||||
|
||||
function config.getfileconfig(cfg, filename)
|
||||
-- The project contains the cached list of file configurations. If I can't
|
||||
-- find an entry, it means this file was excluded from that configuration.
|
||||
local fcfg = cfg.project._.files[filename]
|
||||
if fcfg then
|
||||
return fcfg.configs[cfg]
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve linking information for a specific configuration. That is,
|
||||
-- the path information that is required to link against the library
|
||||
@ -426,19 +403,3 @@
|
||||
function config.gettargetinfo(cfg)
|
||||
return buildtargetinfo(cfg, cfg.kind, "target")
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Checks to see if the project or file configuration contains a
|
||||
-- custom build rule.
|
||||
--
|
||||
-- @param cfg
|
||||
-- A project or file configuration.
|
||||
-- @return
|
||||
-- True if the configuration contains settings for a custom
|
||||
-- build rule.
|
||||
--
|
||||
|
||||
function config.hasCustomBuildRule(cfg)
|
||||
return cfg and (#cfg.buildcommands > 0) and (#cfg.buildoutputs > 0)
|
||||
end
|
||||
|
@ -8,9 +8,27 @@
|
||||
|
||||
local fileconfig = premake5.fileconfig
|
||||
local context = premake.context
|
||||
local project = premake5.project
|
||||
|
||||
|
||||
--
|
||||
-- A little confusing: the file configuration actually contains two objects.
|
||||
-- The first object, the one that is returned by fileconfig.new() and later
|
||||
-- passed back in as *the* file configuration object, contains the common
|
||||
-- project-wide settings for the file. This object also contains a list of
|
||||
-- "sub-configurations", one for each project configuration to which the file
|
||||
-- belongs.
|
||||
--
|
||||
-- Internally, I'm calling the first object the "file configuration" (fcfg)
|
||||
-- and the children "file sub-configurations" (fsub). To distinguish them
|
||||
-- from the project configurations (cfg).
|
||||
--
|
||||
-- Define metatables for each of types; more info below.
|
||||
--
|
||||
|
||||
fileconfig.file_mt = {}
|
||||
fileconfig.fcfg_mt = {}
|
||||
fileconfig.fsub_mt = {}
|
||||
|
||||
|
||||
--
|
||||
-- Create a new file configuration object.
|
||||
@ -25,27 +43,22 @@
|
||||
|
||||
function fileconfig.new(fname, prj)
|
||||
local fcfg = {}
|
||||
setmetatable(fcfg, fileconfig.file_mt)
|
||||
|
||||
-- Compute all the variations on path information for this file once up
|
||||
-- front; will be reused by each of the configuration supported by this
|
||||
-- file, and referenced by tokens in the scripts.
|
||||
|
||||
fcfg.abspath = fname
|
||||
fcfg.relpath = premake5.project.getrelative(prj, fname)
|
||||
fcfg.name = path.getname(fname)
|
||||
fcfg.basename = path.getbasename(fname)
|
||||
|
||||
local vpath = premake5.project.getvpath(prj, fname)
|
||||
if vpath ~= fname then
|
||||
fcfg.vpath = vpath
|
||||
else
|
||||
fcfg.vpath = fcfg.relpath
|
||||
end
|
||||
|
||||
-- Start a list of configurations supported by this file.
|
||||
|
||||
fcfg.project = prj
|
||||
fcfg.configs = {}
|
||||
fcfg.abspath = fname
|
||||
|
||||
-- Most of the other path properties are computed on demand
|
||||
-- from the file's absolute path.
|
||||
|
||||
setmetatable(fcfg, fileconfig.fcfg_mt)
|
||||
|
||||
-- Except for the virtual path, which is expensive to compute, and
|
||||
-- can be used across all the sub-configurations
|
||||
|
||||
local vpath = project.getvpath(prj, fname)
|
||||
if vpath ~= fcfg.abspath then
|
||||
fcfg.vpath = vpath
|
||||
end
|
||||
|
||||
return fcfg
|
||||
end
|
||||
@ -69,10 +82,10 @@
|
||||
-- specific to the file.
|
||||
|
||||
local environ = {}
|
||||
local ctx = context.new(cfg.project.configset, environ, fcfg.abspath)
|
||||
context.copyterms(ctx, cfg)
|
||||
local fsub = context.new(cfg.project.configset, environ, fcfg.abspath)
|
||||
context.copyterms(fsub, cfg)
|
||||
|
||||
fcfg.configs[cfg] = ctx
|
||||
fcfg.configs[cfg] = fsub
|
||||
|
||||
-- set up an environment for expanding tokens contained by this file
|
||||
-- configuration; based on the configuration's environment so that
|
||||
@ -84,36 +97,29 @@
|
||||
|
||||
-- Make the context being built here accessible to tokens
|
||||
|
||||
environ.file = ctx
|
||||
|
||||
-- Merge in the file path information (virtual paths, etc.) that are
|
||||
-- computed at the project level, for token expansions to use
|
||||
|
||||
for key, value in pairs(fcfg) do
|
||||
if type(value) == "string" then
|
||||
ctx[key] = value
|
||||
end
|
||||
end
|
||||
environ.file = fsub
|
||||
|
||||
-- finish the setup
|
||||
|
||||
context.compile(ctx)
|
||||
ctx.path = fcfg.relpath
|
||||
ctx.config = cfg
|
||||
ctx.project = cfg.project
|
||||
context.compile(fsub)
|
||||
fsub.abspath = fcfg.abspath
|
||||
fsub.vpath = fcfg.vpath
|
||||
fsub.config = cfg
|
||||
fsub.project = cfg.project
|
||||
|
||||
-- Set the context's base directory to the project's file system
|
||||
-- location. Any path tokens which are expanded in non-path fields
|
||||
-- (such as the custom build commands) will be made relative to
|
||||
-- this path, ensuring a portable generated project.
|
||||
|
||||
context.basedir(ctx, premake5.project.getlocation(cfg.project))
|
||||
context.basedir(fsub, project.getlocation(cfg.project))
|
||||
|
||||
setmetatable(ctx, fileconfig.fcfg_mt)
|
||||
setmetatable(fsub, fileconfig.fsub_mt)
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Retrieve the configuration settings for a particular file/project
|
||||
-- configuration pairing.
|
||||
@ -134,28 +140,93 @@
|
||||
|
||||
|
||||
--
|
||||
-- The metatable computes most of the path related fields. I do this instead
|
||||
-- of functions to make it easier to access these values from tokens, and to
|
||||
-- avoid the memory overhead of all these strings for large solutions.
|
||||
-- Checks to see if the project or file configuration contains a
|
||||
-- custom build rule.
|
||||
--
|
||||
-- @param cfg
|
||||
-- A project or file configuration.
|
||||
-- @return
|
||||
-- True if the configuration contains settings for a custom
|
||||
-- build rule.
|
||||
--
|
||||
|
||||
function fileconfig.hasCustomBuildRule(fcfg)
|
||||
return fcfg and (#fcfg.buildcommands > 0) and (#fcfg.buildoutputs > 0)
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Rather than store pre-computed strings for all of the path variations
|
||||
-- (abspath, relpath, vpath, name, etc.) for each file (there can be quite
|
||||
-- a lot of them) I assign a metatable to the file configuration objects
|
||||
-- that will build these values on the fly.
|
||||
--
|
||||
-- I am using these pseudo-properties, rather than explicit functions, to make
|
||||
-- it easier to fetch them script tokens (i.e. %{file.relpath} with no need
|
||||
-- for knowledge of the internal Premake APIs.
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- The indexer for the file configurations. If I have a path building function
|
||||
-- to fulfill the request, call it. Else this is a missing index so return nil.
|
||||
--
|
||||
|
||||
local file_mt = fileconfig.file_mt
|
||||
local fcfg_mt = fileconfig.fcfg_mt
|
||||
|
||||
file_mt.__index = function(file, key)
|
||||
if type(file_mt[key]) == "function" then
|
||||
return file_mt[key](file)
|
||||
fcfg_mt.__index = function(file, key)
|
||||
if type(fcfg_mt[key]) == "function" then
|
||||
return fcfg_mt[key](file)
|
||||
end
|
||||
end
|
||||
|
||||
fcfg_mt.__index = function(fcfg, key)
|
||||
return file_mt.__index(fcfg, key) or context.__mt.__index(fcfg, key)
|
||||
|
||||
--
|
||||
-- The indexer for the file sub-configurations. Check for a path building
|
||||
-- function first, and then fall back to the context's own value lookups.
|
||||
-- TODO: Would be great if this didn't require inside knowledge of context.
|
||||
--
|
||||
|
||||
fileconfig.fsub_mt.__index = function(fcfg, key)
|
||||
return fcfg_mt.__index(fcfg, key) or context.__mt.__index(fcfg, key)
|
||||
end
|
||||
|
||||
function file_mt.objname(fcfg)
|
||||
|
||||
--
|
||||
-- And here are the path building functions.
|
||||
--
|
||||
|
||||
function fcfg_mt.basename(fcfg)
|
||||
return path.getbasename(fcfg.abspath)
|
||||
end
|
||||
|
||||
|
||||
function fcfg_mt.name(fcfg)
|
||||
return path.getname(fcfg.abspath)
|
||||
end
|
||||
|
||||
|
||||
function fcfg_mt.objname(fcfg)
|
||||
if fcfg.sequence ~= nil and fcfg.sequence > 0 then
|
||||
return fcfg.basename .. fcfg.sequence
|
||||
else
|
||||
return fcfg.basename
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function fcfg_mt.path(fcfg)
|
||||
return fcfg.relpath
|
||||
end
|
||||
|
||||
|
||||
function fcfg_mt.relpath(fcfg)
|
||||
return project.getrelative(fcfg.project, fcfg.abspath)
|
||||
end
|
||||
|
||||
|
||||
function fcfg_mt.vpath(fcfg)
|
||||
-- This only gets called if no explicit virtual path was set
|
||||
return fcfg.relpath
|
||||
end
|
||||
|
@ -656,15 +656,9 @@
|
||||
-- @param sorter
|
||||
-- An optional comparator function for the sorting pass.
|
||||
-- @return
|
||||
-- A tree object containing the source file hierarchy. Leaf nodes
|
||||
-- representing the individual files contain the fields:
|
||||
-- abspath - the absolute path of the file
|
||||
-- relpath - the relative path from the project to the file
|
||||
-- vpath - the file's virtual path
|
||||
-- All nodes contain the fields:
|
||||
-- path - the node's path within the tree
|
||||
-- realpath - the node's file system path (nil for virtual paths)
|
||||
-- name - the directory or file name represented by the node
|
||||
-- A tree object containing the source file hierarchy. Leaf nodes,
|
||||
-- representing the individual files, are file configuration
|
||||
-- objects.
|
||||
--
|
||||
|
||||
function project.getsourcetree(prj, sorter)
|
||||
|
@ -1,154 +0,0 @@
|
||||
--
|
||||
-- tests/config/test_fileconfig.lua
|
||||
-- Test the config object's file configuration accessor.
|
||||
-- Copyright (c) 2012 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
T.config_fileconfig = { }
|
||||
local suite = T.config_fileconfig
|
||||
local project = premake5.project
|
||||
local config = premake5.config
|
||||
|
||||
|
||||
--
|
||||
-- Setup and teardown
|
||||
--
|
||||
|
||||
local sln, prj, fcfg
|
||||
|
||||
function suite.setup()
|
||||
sln, prj = test.createsolution()
|
||||
end
|
||||
|
||||
local function prepare(filename)
|
||||
local cfg = project.getconfig(prj, "Debug")
|
||||
fcfg = config.getfileconfig(cfg, path.join(os.getcwd(), filename or "hello.c"))
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- A file specified at the project level should be present in all configurations.
|
||||
--
|
||||
|
||||
function suite.isPresent_onProjectLevel()
|
||||
files "hello.c"
|
||||
prepare()
|
||||
test.isnotnil(fcfg)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- A file specified only in the current configuration should return a value.
|
||||
--
|
||||
|
||||
function suite.isPresent_onCurrentConfigOnly()
|
||||
configuration "Debug"
|
||||
files "hello.c"
|
||||
prepare()
|
||||
test.isnotnil(fcfg)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- A file specified only in a different configuration should return nil.
|
||||
--
|
||||
|
||||
function suite.isNotPresent_onDifferentConfigOnly()
|
||||
configuration "Release"
|
||||
files "hello.c"
|
||||
prepare()
|
||||
test.isnil(fcfg)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- A file specified at the project, and excluded in the current configuration
|
||||
-- should return nil.
|
||||
--
|
||||
|
||||
function suite.isNotPresent_onExcludedInCurrent()
|
||||
files "hello.c"
|
||||
configuration "Debug"
|
||||
excludes "hello.c"
|
||||
prepare()
|
||||
test.isnil(fcfg)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- A file specified at the project, and excluded in a different configuration
|
||||
-- should return a value.
|
||||
--
|
||||
|
||||
function suite.isNotPresent_onExcludedInCurrent()
|
||||
files "hello.c"
|
||||
configuration "Release"
|
||||
excludes "hello.c"
|
||||
prepare()
|
||||
test.isnotnil(fcfg)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- A build option specified on a specific set of files should appear in the
|
||||
-- file configuration
|
||||
--
|
||||
|
||||
function suite.settingIsPresent_onFileSpecificFilter()
|
||||
files "hello.c"
|
||||
configuration "**.c"
|
||||
buildoptions "-Xc"
|
||||
prepare()
|
||||
test.isequal({ "-Xc" }, fcfg.buildoptions)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- A "not" filter should not provide the positive match for a
|
||||
-- file configuration filename mask.
|
||||
--
|
||||
|
||||
function suite.fileIsUnmatched_onNotFilter()
|
||||
files "hello.c"
|
||||
configuration "not Debug"
|
||||
buildoptions "-Xc"
|
||||
prepare()
|
||||
test.isequal({}, fcfg.buildoptions)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Check case-sensitivity of file name tests.
|
||||
--
|
||||
|
||||
function suite.fileMatches_onCaseMismatch()
|
||||
files "Hello.c"
|
||||
configuration "HeLLo.c"
|
||||
buildoptions "-Xc"
|
||||
prepare("Hello.c")
|
||||
test.isequal({ "-Xc" }, fcfg.buildoptions)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- A leading single star should match files in the same
|
||||
-- folder as the project script, for consistency with files(),
|
||||
-- but not files in other folders.
|
||||
--
|
||||
|
||||
function suite.singleStarMatches_onSameFolder()
|
||||
files "hello.c"
|
||||
configuration "*.c"
|
||||
buildoptions "-Xc"
|
||||
prepare()
|
||||
test.isequal({ "-Xc" }, fcfg.buildoptions)
|
||||
end
|
||||
|
||||
function suite.singleStarNoMatch_onDifferentFolder()
|
||||
files "src/hello.c"
|
||||
configuration "*.c"
|
||||
buildoptions "-Xc"
|
||||
prepare("src/hello.c")
|
||||
test.isequal({}, fcfg.buildoptions)
|
||||
end
|
||||
|
@ -67,7 +67,6 @@
|
||||
dofile("project/test_vpaths.lua")
|
||||
|
||||
-- Configuration object tests
|
||||
dofile("config/test_fileconfig.lua")
|
||||
dofile("config/test_linkinfo.lua")
|
||||
dofile("config/test_links.lua")
|
||||
dofile("config/test_targetinfo.lua")
|
||||
|
Loading…
Reference in New Issue
Block a user