Merge new custom rule file support
This commit is contained in:
commit
0a4c3e6853
@ -41,7 +41,7 @@
|
||||
"base/project.lua",
|
||||
"base/config.lua",
|
||||
"base/fileconfig.lua",
|
||||
"base/rules.lua",
|
||||
"base/rule.lua",
|
||||
|
||||
-- project script processing
|
||||
"base/oven.lua",
|
||||
|
@ -162,13 +162,6 @@
|
||||
tokens = true,
|
||||
}
|
||||
|
||||
api.register {
|
||||
name = "customRules",
|
||||
scope = "project",
|
||||
kind = "list:file",
|
||||
tokens = true,
|
||||
}
|
||||
|
||||
api.register {
|
||||
name = "debugargs",
|
||||
scope = "config",
|
||||
@ -624,6 +617,12 @@
|
||||
tokens = true,
|
||||
}
|
||||
|
||||
api.register {
|
||||
name = "rules",
|
||||
scope = "project",
|
||||
kind = "list:string",
|
||||
}
|
||||
|
||||
api.register {
|
||||
name = "startproject",
|
||||
scope = "solution",
|
||||
|
@ -241,7 +241,7 @@
|
||||
m.elements.itemDefinitionGroup = function(cfg)
|
||||
if cfg.kind == p.UTILITY then
|
||||
return {
|
||||
m.customRuleVars,
|
||||
m.ruleVars,
|
||||
m.buildEvents,
|
||||
}
|
||||
else
|
||||
@ -253,7 +253,7 @@
|
||||
m.buildEvents,
|
||||
m.imageXex,
|
||||
m.deploy,
|
||||
m.customRuleVars,
|
||||
m.ruleVars,
|
||||
}
|
||||
end
|
||||
end
|
||||
@ -491,23 +491,19 @@
|
||||
-- Write out project-level custom rule variables.
|
||||
---
|
||||
|
||||
function m.customRuleVars(cfg)
|
||||
local vars = p.api.getCustomVars()
|
||||
table.foreachi(cfg.project._customRules, function(rule)
|
||||
function m.ruleVars(cfg)
|
||||
for i = 1, #cfg.rules do
|
||||
local rule = p.global.getRule(cfg.rules[i])
|
||||
|
||||
local contents = p.capture(function ()
|
||||
p.push()
|
||||
for _, var in ipairs(vars) do
|
||||
if cfg[var] then
|
||||
local key = p.api.getCustomVarKey(var)
|
||||
local value = cfg[var]
|
||||
|
||||
if type(value) == "table" then
|
||||
local fmt = p.api.getCustomListFormat(var)
|
||||
value = table.concat(value, fmt[1])
|
||||
end
|
||||
|
||||
if value and #value > 0 then
|
||||
m.element(key, nil, '%s', value)
|
||||
for prop in p.rule.eachProperty(rule) do
|
||||
local fld = p.rule.getPropertyField(rule, prop)
|
||||
local value = cfg[fld.name]
|
||||
if value ~= nil then
|
||||
value = p.rule.getPropertyString(rule, prop, value)
|
||||
if value ~= nil and #value > 0 then
|
||||
m.element(prop.name, nil, '%s', value)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -515,11 +511,11 @@
|
||||
end)
|
||||
|
||||
if #contents > 0 then
|
||||
p.push('<%s>', rule)
|
||||
p.push('<%s>', rule.name)
|
||||
p.outln(contents)
|
||||
p.pop('</%s>', rule)
|
||||
p.pop('</%s>', rule.name)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -559,12 +555,12 @@
|
||||
---
|
||||
|
||||
m.elements.fileGroups = {
|
||||
"ClInclude",
|
||||
"ClCompile",
|
||||
"None",
|
||||
"ResourceCompile",
|
||||
"CustomBuild",
|
||||
"CustomRule"
|
||||
"clInclude",
|
||||
"clCompile",
|
||||
"none",
|
||||
"resourceCompile",
|
||||
"customBuild",
|
||||
"customRule"
|
||||
}
|
||||
|
||||
m.elements.files = function(prj, groups)
|
||||
@ -583,7 +579,7 @@
|
||||
end
|
||||
|
||||
|
||||
function m.ClCompileFiles(prj, group)
|
||||
function m.clCompileFiles(prj, group)
|
||||
local files = group.ClCompile or {}
|
||||
if #files > 0 then
|
||||
p.push('<ItemGroup>')
|
||||
@ -622,7 +618,7 @@
|
||||
end
|
||||
|
||||
|
||||
function m.ClIncludeFiles(prj, groups)
|
||||
function m.clIncludeFiles(prj, groups)
|
||||
local files = groups.ClInclude or {}
|
||||
if #files > 0 then
|
||||
p.push('<ItemGroup>')
|
||||
@ -634,7 +630,7 @@
|
||||
end
|
||||
|
||||
|
||||
function m.CustomBuildFiles(prj, groups)
|
||||
function m.customBuildFiles(prj, groups)
|
||||
local files = groups.CustomBuild or {}
|
||||
if #files > 0 then
|
||||
p.push('<ItemGroup>')
|
||||
@ -672,48 +668,42 @@
|
||||
end
|
||||
|
||||
|
||||
function m.CustomRuleFiles(prj, groups)
|
||||
local vars = p.api.getCustomVars()
|
||||
|
||||
-- Look for rules that aren't in the built-in rule list
|
||||
for rule, files in pairs(groups) do
|
||||
if not table.contains(m.elements.fileGroups, rule) and #files > 0 then
|
||||
function m.customRuleFiles(prj, groups)
|
||||
for i = 1, #prj.rules do
|
||||
local rule = p.global.getRule(prj.rules[i])
|
||||
local files = groups[rule.name]
|
||||
if files and #files > 0 then
|
||||
p.push('<ItemGroup>')
|
||||
for _, file in ipairs(files) do
|
||||
|
||||
-- Capture any rule variables that have been set
|
||||
for _, file in ipairs(files) do
|
||||
local contents = p.capture(function()
|
||||
p.push()
|
||||
for _, var in ipairs(vars) do
|
||||
for prop in p.rule.eachProperty(rule) do
|
||||
local fld = p.rule.getPropertyField(rule, prop)
|
||||
|
||||
for cfg in project.eachconfig(prj) do
|
||||
local condition = m.condition(cfg)
|
||||
local fcfg = fileconfig.getconfig(file, cfg)
|
||||
if fcfg and fcfg[var] then
|
||||
local key = p.api.getCustomVarKey(var)
|
||||
local value = fcfg[var]
|
||||
|
||||
if type(value) == "table" then
|
||||
local fmt = p.api.getCustomListFormat(var)
|
||||
value = table.concat(value, fmt[1])
|
||||
end
|
||||
|
||||
if fcfg and fcfg[fld.name] then
|
||||
local value = p.rule.getPropertyString(rule, prop, fcfg[fld.name])
|
||||
if value and #value > 0 then
|
||||
m.element(key, condition, '%s', value)
|
||||
m.element(prop.name, m.condition(cfg), '%s', value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
p.pop()
|
||||
end)
|
||||
|
||||
if #contents > 0 then
|
||||
p.push('<%s Include=\"%s\">', rule, path.translate(file.relpath))
|
||||
p.push('<%s Include=\"%s\">', rule.name, path.translate(file.relpath))
|
||||
p.outln(contents)
|
||||
p.pop('</%s>', rule)
|
||||
p.pop('</%s>', rule.name)
|
||||
else
|
||||
p.x('<%s Include=\"%s\" />', rule, path.translate(file.relpath))
|
||||
p.x('<%s Include=\"%s\" />', rule.name, path.translate(file.relpath))
|
||||
end
|
||||
end
|
||||
|
||||
p.pop('</ItemGroup>')
|
||||
end
|
||||
end
|
||||
@ -721,7 +711,7 @@
|
||||
|
||||
|
||||
|
||||
function m.NoneFiles(prj, groups)
|
||||
function m.noneFiles(prj, groups)
|
||||
local files = groups.None or {}
|
||||
if #files > 0 then
|
||||
p.push('<ItemGroup>')
|
||||
@ -733,7 +723,7 @@
|
||||
end
|
||||
|
||||
|
||||
function m.ResourceCompileFiles(prj, groups)
|
||||
function m.resourceCompileFiles(prj, groups)
|
||||
local files = groups.ResourceCompile or {}
|
||||
if #files > 0 then
|
||||
p.push('<ItemGroup>')
|
||||
@ -764,17 +754,21 @@
|
||||
|
||||
|
||||
function m.categorize(prj, file)
|
||||
-- If any configuration for this file uses a custom build step or a
|
||||
-- custom, externally defined rule, that's the category to use
|
||||
-- If any configuration for this file uses a custom build step,
|
||||
-- that's the category to use
|
||||
for cfg in project.eachconfig(prj) do
|
||||
local fcfg = fileconfig.getconfig(file, cfg)
|
||||
if fileconfig.hasCustomBuildRule(fcfg) then
|
||||
return "CustomBuild"
|
||||
elseif fcfg and fcfg._customRule then
|
||||
return fcfg._customRule
|
||||
end
|
||||
end
|
||||
|
||||
-- If there is a custom rule associated with it, use that
|
||||
local rule = p.global.getRuleForFile(file.name, prj.rules)
|
||||
if rule then
|
||||
return rule.name
|
||||
end
|
||||
|
||||
-- Otherwise use the file extension to deduce a category
|
||||
if path.iscppfile(file.name) then
|
||||
return "ClCompile"
|
||||
@ -1155,11 +1149,13 @@
|
||||
function m.importExtensionTargets(prj)
|
||||
p.w('<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" />')
|
||||
p.push('<ImportGroup Label="ExtensionTargets">')
|
||||
table.foreachi(prj.customRules, function(value)
|
||||
value = path.translate(project.getrelative(prj, value))
|
||||
value = path.appendExtension(value, ".targets")
|
||||
p.x('<Import Project="%s" />', value)
|
||||
end)
|
||||
|
||||
for i = 1, #prj.rules do
|
||||
local rule = p.global.getRule(prj.rules[i])
|
||||
local loc = project.getrelative(prj, premake.filename(rule, ".targets"))
|
||||
p.x('<Import Project="%s" />', path.translate(loc))
|
||||
end
|
||||
|
||||
p.pop('</ImportGroup>')
|
||||
end
|
||||
|
||||
@ -1174,11 +1170,13 @@
|
||||
function m.importExtensionSettings(prj)
|
||||
p.w('<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props" />')
|
||||
p.push('<ImportGroup Label="ExtensionSettings">')
|
||||
table.foreachi(prj.customRules, function(value)
|
||||
value = path.translate(project.getrelative(prj, value))
|
||||
value = path.appendExtension(value, ".props")
|
||||
p.x('<Import Project="%s" />', value)
|
||||
end)
|
||||
|
||||
for i = 1, #prj.rules do
|
||||
local rule = p.global.getRule(prj.rules[i])
|
||||
local loc = project.getrelative(prj, premake.filename(rule, ".props"))
|
||||
p.x('<Import Project="%s" />', path.translate(loc))
|
||||
end
|
||||
|
||||
p.pop('</ImportGroup>')
|
||||
end
|
||||
|
||||
|
211
src/base/api.lua
211
src/base/api.lua
@ -49,6 +49,12 @@
|
||||
return api._setContainer(class, name)
|
||||
end
|
||||
|
||||
_G["external" .. containerName:capitalized()] = function(name)
|
||||
local c = _G[containerName](name)
|
||||
c.external = true
|
||||
return c
|
||||
end
|
||||
|
||||
return class
|
||||
end
|
||||
|
||||
@ -238,7 +244,7 @@
|
||||
|
||||
-- create a setter function for it
|
||||
_G[name] = function(value)
|
||||
return api.callback(field, value)
|
||||
return api.storeField(field, value)
|
||||
end
|
||||
|
||||
if premake.field.removes(field) then
|
||||
@ -460,8 +466,8 @@
|
||||
-- gets parceled out to the individual set...() functions.
|
||||
--
|
||||
|
||||
function api.callback(field, value)
|
||||
if not value then
|
||||
function api.storeField(field, value)
|
||||
if value == nil then
|
||||
return
|
||||
end
|
||||
|
||||
@ -486,6 +492,7 @@
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- The remover: adds values to be removed to the "removes" field on
|
||||
-- current configuration. Removes are keyed by the associated field,
|
||||
@ -496,7 +503,7 @@
|
||||
function api.remove(field, value)
|
||||
-- right now, ignore calls with no value; later might want to
|
||||
-- return the current baked value
|
||||
if not value then return end
|
||||
if value == nil then return end
|
||||
|
||||
local target = api.target(field)
|
||||
if not target then
|
||||
@ -639,18 +646,9 @@
|
||||
---
|
||||
|
||||
function api.reset()
|
||||
-- Clear out all top level objects
|
||||
-- Clear out all top level objects, but keep the root config
|
||||
api.scope.global.rules = {}
|
||||
api.scope.global.solutions = {}
|
||||
|
||||
-- Remove all custom variables
|
||||
local vars = api.getCustomVars()
|
||||
for i, var in ipairs(vars) do
|
||||
local f = premake.field.get(var)
|
||||
api.unregister(f)
|
||||
end
|
||||
|
||||
-- Remove all custom list variable formats
|
||||
api._customVarFormats = {}
|
||||
end
|
||||
|
||||
|
||||
@ -687,6 +685,47 @@
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Boolean field kind; converts common yes/no strings into true/false values.
|
||||
---
|
||||
|
||||
premake.field.kind("boolean", {
|
||||
store = function(field, current, value, processor)
|
||||
local mapping = {
|
||||
["false"] = false,
|
||||
["no"] = false,
|
||||
["off"] = false,
|
||||
["on"] = true,
|
||||
["true"] = true,
|
||||
["yes"] = true,
|
||||
}
|
||||
|
||||
if type(value) == "string" then
|
||||
value = mapping[value:lower()]
|
||||
if value == nil then
|
||||
error { msg="expected boolean; got " .. value }
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
if type(value) == "boolean" then
|
||||
return value
|
||||
end
|
||||
|
||||
if type(value) == "number" then
|
||||
return (value ~= 0)
|
||||
end
|
||||
|
||||
return (value ~= nil)
|
||||
end,
|
||||
compare = function(field, a, b, processor)
|
||||
return (a == b)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Directory data kind; performs wildcard directory searches, converts
|
||||
-- results to absolute paths.
|
||||
@ -1044,26 +1083,6 @@
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Activates a reference to an external, non-Premake generated project.
|
||||
--
|
||||
-- @param name
|
||||
-- The name of the project. If a project with this name already
|
||||
-- exists, it is made current, otherwise a new project is created
|
||||
-- with this name. If no name is provided, the most recently defined
|
||||
-- project is made active.
|
||||
-- @return
|
||||
-- The active project object.
|
||||
--
|
||||
|
||||
function external(name)
|
||||
local prj = project(name)
|
||||
prj.external = true;
|
||||
return prj
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Define a new action.
|
||||
--
|
||||
@ -1086,125 +1105,3 @@
|
||||
function newoption(opt)
|
||||
premake.option.add(opt)
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
--
|
||||
-- The custom*() functions act as wrappers that define new ad-hoc fields
|
||||
-- on the fly, to support arbitrary custom rule variables. These should be
|
||||
-- considered experimental and temporary for now as a more complete rule-
|
||||
-- generating solution will certainly be needed, but I will do my best to
|
||||
-- deprecate them cleanly when that time comes.
|
||||
--
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
api._customVarFormats = {}
|
||||
|
||||
function api.getCustomVars()
|
||||
local vars = {}
|
||||
for f in premake.field.each() do
|
||||
if f.name:startswith("_custom_") then
|
||||
table.insert(vars, f.name)
|
||||
end
|
||||
end
|
||||
return vars
|
||||
end
|
||||
|
||||
|
||||
function api.getCustomVarKey(var)
|
||||
return var:sub(9)
|
||||
end
|
||||
|
||||
|
||||
function api.getCustomListFormat(var)
|
||||
local key = api.getCustomVarKey(var)
|
||||
return api._customVarFormats[key] or { " " }
|
||||
end
|
||||
|
||||
|
||||
function api.setCustomVar(name, kind, value)
|
||||
local fieldName = "_custom_" .. name
|
||||
local field = premake.field.get(fieldName)
|
||||
if not field then
|
||||
field = premake.field.new {
|
||||
name = fieldName,
|
||||
scope = "config",
|
||||
kind = kind,
|
||||
tokens = true,
|
||||
}
|
||||
end
|
||||
api.callback(field, value)
|
||||
end
|
||||
|
||||
|
||||
function customVar(value)
|
||||
if type(value) ~= "table" or #value ~= 2 then
|
||||
error("invalid value for customVar()")
|
||||
end
|
||||
api.setCustomVar(value[1], "string", value[2])
|
||||
end
|
||||
|
||||
|
||||
function customList(value)
|
||||
if type(value) ~= "table" or #value < 2 then
|
||||
error("invalid value for customList()")
|
||||
end
|
||||
|
||||
local name = value[1]
|
||||
table.remove(value, 1)
|
||||
api.setCustomVar(name, "list:string", value)
|
||||
end
|
||||
|
||||
|
||||
function customListFormat(value)
|
||||
if type(value) ~= "table" or #value < 2 then
|
||||
error("invalid value for customListFormat()")
|
||||
end
|
||||
|
||||
local name = value[1]
|
||||
table.remove(value, 1)
|
||||
api._customVarFormats[name] = value
|
||||
end
|
||||
|
||||
|
||||
function customRule(value)
|
||||
-- Store the rule name in the current configuration, like a
|
||||
-- normal set-field operation would
|
||||
local fieldName = "_customRule"
|
||||
local field = premake.field.get(fieldName)
|
||||
if not field then
|
||||
field = premake.field.new {
|
||||
name = fieldName,
|
||||
scope = "config",
|
||||
kind = "string",
|
||||
}
|
||||
end
|
||||
api.callback(field, value)
|
||||
|
||||
-- Wild hack: I need a way to get all of the custom rule names that are
|
||||
-- in use within a project. The rule names are currently only associated
|
||||
-- with individual files. Rather than iterating over all the files after
|
||||
-- the fact, keep a master list of rule names in the first configuration
|
||||
-- block of the project. This way it will come out of the baking system
|
||||
-- looking like a normal list:string field.
|
||||
fieldName = "_customRules"
|
||||
field = premake.field.get(fieldName)
|
||||
if not field then
|
||||
field = premake.field.new {
|
||||
name = fieldName,
|
||||
scope = "config",
|
||||
kind = "list:string"
|
||||
}
|
||||
end
|
||||
|
||||
local cset = api.target(field)
|
||||
if not cset then
|
||||
local err = string.format("unable to set rule in %s scope, should be project", api.scope.current.class.name)
|
||||
error(err, 2)
|
||||
end
|
||||
|
||||
local current = cset.current
|
||||
cset.current = cset.blocks[1]
|
||||
api.callback(field, value)
|
||||
cset.current = current
|
||||
end
|
||||
|
@ -89,12 +89,12 @@
|
||||
|
||||
-- If the filter contains a file path, make it relative to
|
||||
-- this block's basedir
|
||||
if value and abspath and not cset.compiled and block._basedir ~= basedir then
|
||||
if value ~= nil and abspath and not cset.compiled and block._basedir ~= basedir then
|
||||
basedir = block._basedir
|
||||
filter.files = path.getrelative(basedir, abspath)
|
||||
end
|
||||
|
||||
if value and (cset.compiled or criteria.matches(block._criteria, filter)) then
|
||||
if value ~= nil and (cset.compiled or criteria.matches(block._criteria, filter)) then
|
||||
-- If value is an object, return a copy of it so that any
|
||||
-- changes later made to it by the caller won't alter the
|
||||
-- original value (that was a tough bug to find)
|
||||
|
@ -70,8 +70,10 @@
|
||||
|
||||
self.class = class
|
||||
self.name = name
|
||||
self.filename = name
|
||||
self.script = _SCRIPT
|
||||
self.basedir = os.getcwd()
|
||||
self.external = false
|
||||
|
||||
for childClass in container.eachChildClass(class) do
|
||||
self[childClass.pluralName] = {}
|
||||
|
@ -79,6 +79,10 @@
|
||||
end
|
||||
|
||||
function expandvalue(value)
|
||||
if type(value) ~= "string" then
|
||||
return
|
||||
end
|
||||
|
||||
local count
|
||||
repeat
|
||||
value, count = value:gsub("%%{(.-)}", function(token)
|
||||
|
@ -290,7 +290,7 @@
|
||||
local kinds = string.explode(f._kind, ":", true)
|
||||
for i, kind in ipairs(kinds) do
|
||||
local value = field._kinds[kind][tag]
|
||||
if value then
|
||||
if value ~= nil then
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
@ -47,6 +47,48 @@
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Retrieve a rule by name or index.
|
||||
--
|
||||
-- @param key
|
||||
-- The rule key, either a string name or integer index.
|
||||
-- @returns
|
||||
-- The rule with the provided key.
|
||||
---
|
||||
|
||||
function global.getRule(key)
|
||||
local root = p.api.rootContainer()
|
||||
return root.rules[key]
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Retrieve the rule to applies to the provided file name, if any such
|
||||
-- rule exists.
|
||||
--
|
||||
-- @param fname
|
||||
-- The name of the file.
|
||||
-- @param rules
|
||||
-- A list of rule names to be included in the search. If not specified,
|
||||
-- all rules will be checked.
|
||||
-- @returns
|
||||
-- The rule, is one has been registered, or nil.
|
||||
---
|
||||
|
||||
function global.getRuleForFile(fname, rules)
|
||||
local ext = path.getextension(fname):lower()
|
||||
for rule in global.eachRule() do
|
||||
if not rules or table.contains(rules, rule.name) then
|
||||
if rule.fileExtension == ext then
|
||||
return rule
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Retrieve a solution by name or index.
|
||||
--
|
||||
@ -58,7 +100,5 @@
|
||||
|
||||
function global.getSolution(key)
|
||||
local root = p.api.rootContainer()
|
||||
if root.solutions then
|
||||
return root.solutions[key]
|
||||
end
|
||||
return root.solutions[key]
|
||||
end
|
||||
|
@ -94,7 +94,6 @@
|
||||
-- to project configurations.
|
||||
|
||||
self.configs = oven.bakeConfigs(self)
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -194,6 +193,14 @@
|
||||
|
||||
|
||||
|
||||
function p.rule.bake(r)
|
||||
table.sort(r.propertyDefinition, function (a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Assigns a unique objects directory to every configuration of every project
|
||||
-- in the solution, taking any objdir settings into account, to ensure builds
|
||||
|
@ -4,10 +4,12 @@
|
||||
-- Copyright (c) 2002-2014 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
local solution = premake.solution
|
||||
local project = premake.project
|
||||
local config = premake.config
|
||||
local field = premake.field
|
||||
local p = premake
|
||||
|
||||
local solution = p.solution
|
||||
local project = p.project
|
||||
local config = p.config
|
||||
local field = p.field
|
||||
|
||||
|
||||
|
||||
@ -180,7 +182,7 @@
|
||||
---
|
||||
|
||||
function premake.filename(obj, ext)
|
||||
local fname = obj.location
|
||||
local fname = obj.location or obj.basedir
|
||||
if ext and not ext:startswith(".") then
|
||||
fname = path.join(fname, ext)
|
||||
else
|
||||
@ -189,7 +191,7 @@ function premake.filename(obj, ext)
|
||||
fname = fname .. ext
|
||||
end
|
||||
end
|
||||
return fname
|
||||
return path.getabsolute(fname)
|
||||
end
|
||||
|
||||
|
||||
@ -367,6 +369,14 @@ end
|
||||
premake.error("project '%s' does not have a language", prj.name)
|
||||
end
|
||||
|
||||
-- all rules must exist
|
||||
for i = 1, #prj.rules do
|
||||
local rule = prj.rules[i]
|
||||
if not p.global.getRule(rule) then
|
||||
premake.error("project '%s' uses missing rule '%s'", prj.name, rule)
|
||||
end
|
||||
end
|
||||
|
||||
-- check for out of scope fields
|
||||
premake.validateScopes(prj, "project", ctx)
|
||||
end
|
||||
|
@ -12,6 +12,15 @@
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Alias the old external() call to the new externalProject(), to distinguish
|
||||
-- between it and externalRule().
|
||||
---
|
||||
|
||||
external = externalProject
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Create a new project container instance.
|
||||
---
|
||||
@ -19,7 +28,6 @@
|
||||
function project.new(name)
|
||||
local prj = p.container.new(project, name)
|
||||
prj.uuid = os.uuid(name)
|
||||
prj.filename = name
|
||||
|
||||
if p.api.scope.group then
|
||||
prj.group = p.api.scope.group.name
|
||||
|
157
src/base/rule.lua
Normal file
157
src/base/rule.lua
Normal file
@ -0,0 +1,157 @@
|
||||
---
|
||||
-- base/rule.lua
|
||||
-- Defines rule sets for generated custom rule files.
|
||||
-- Copyright (c) 2014 Jason Perkins and the Premake project
|
||||
---
|
||||
|
||||
local p = premake
|
||||
p.rule = p.api.container("rule", p.global)
|
||||
|
||||
local rule = p.rule
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Create a new rule container instance.
|
||||
---
|
||||
|
||||
function rule.new(name)
|
||||
local self = p.container.new(rule, name)
|
||||
|
||||
-- create a variable setting function
|
||||
name = name:gsub("^%u+", string.lower)
|
||||
_G[name .. "Vars"] = function(vars)
|
||||
rule.setVars(self, vars)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Enumerate the property definitions for a rule.
|
||||
---
|
||||
|
||||
function rule.eachProperty(self)
|
||||
local props = self.propertyDefinition
|
||||
local i = 0
|
||||
return function ()
|
||||
i = i + 1
|
||||
if i <= #props then
|
||||
return props[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Find a property definition by its name.
|
||||
--
|
||||
-- @param name
|
||||
-- The property name.
|
||||
-- @returns
|
||||
-- The property definition if found, nil otherwise.
|
||||
---
|
||||
|
||||
function rule.getProperty(self, name)
|
||||
local props = self.propertyDefinition
|
||||
for i = 1, #props do
|
||||
local prop = props[i]
|
||||
if prop.name == name then
|
||||
return prop
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Find the field definition for one this rule's properties. This field
|
||||
-- can then be used with the api.* functions to manipulate the property's
|
||||
-- values in the current configuration scope.
|
||||
--
|
||||
-- @param prop
|
||||
-- The property definition.
|
||||
-- @return
|
||||
-- The field definition for the property; this will be created if it
|
||||
-- does not already exist.
|
||||
---
|
||||
|
||||
function rule.getPropertyField(self, prop)
|
||||
if prop._field then
|
||||
return prop._field
|
||||
end
|
||||
|
||||
local kind = prop.kind or "string"
|
||||
if kind == "list" then
|
||||
kind = "list:string"
|
||||
end
|
||||
|
||||
local fld = p.field.new {
|
||||
name = "_rule_" .. self.name .. "_" .. prop.name,
|
||||
scope = "config",
|
||||
kind = kind,
|
||||
tokens = true,
|
||||
}
|
||||
|
||||
prop._field = fld
|
||||
return fld
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Given the value for a particular property, returns a formatted string.
|
||||
--
|
||||
-- @param prop
|
||||
-- The property definition.
|
||||
-- @param value
|
||||
-- The value of the property to be formatted.
|
||||
-- @returns
|
||||
-- A string value.
|
||||
---
|
||||
|
||||
function rule.getPropertyString(self, prop, value)
|
||||
-- list?
|
||||
if type(value) == "table" then
|
||||
local sep = prop.separator or " "
|
||||
return table.concat(value, sep)
|
||||
end
|
||||
|
||||
-- enum?
|
||||
if prop.values then
|
||||
local i = table.indexof(prop.values, value)
|
||||
return tostring(i)
|
||||
end
|
||||
|
||||
-- primitive
|
||||
value = tostring(value)
|
||||
if #value > 0 then
|
||||
return value
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Set one or more rule variables in the current configuration scope.
|
||||
--
|
||||
-- @param vars
|
||||
-- A key-value list of variables to set and their corresponding values.
|
||||
---
|
||||
|
||||
function rule.setVars(self, vars)
|
||||
for key, value in pairs(vars) do
|
||||
local prop = rule.getProperty(self, key)
|
||||
if not prop then
|
||||
error (string.format("rule '%s' does not have property '%s'", self.name, key))
|
||||
end
|
||||
|
||||
local fld = rule.getPropertyField(self, prop)
|
||||
p.api.storeField(fld, value)
|
||||
end
|
||||
end
|
@ -1,20 +0,0 @@
|
||||
---
|
||||
-- base/rules.lua
|
||||
-- Defines rule sets for generated custom rule files.
|
||||
-- Copyright (c) 2014 Jason Perkins and the Premake project
|
||||
---
|
||||
|
||||
local p = premake
|
||||
p.rule = p.api.container("rule", p.global)
|
||||
|
||||
local rule = p.rule
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Create a new rule container instance.
|
||||
---
|
||||
|
||||
function rule.new(name)
|
||||
return p.container.new(rule, name)
|
||||
end
|
@ -18,7 +18,6 @@
|
||||
|
||||
function solution.new(name)
|
||||
local sln = p.container.new(solution, name)
|
||||
sln.filename = name
|
||||
return sln
|
||||
end
|
||||
|
||||
|
@ -5,6 +5,16 @@
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- Capitalize the first letter of the string.
|
||||
--
|
||||
|
||||
function string.capitalized(self)
|
||||
return self:gsub("^%l", string.upper)
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Returns true if the string has a match for the plain specified pattern
|
||||
--
|
||||
|
@ -168,15 +168,15 @@
|
||||
--
|
||||
|
||||
function table.indexof(tbl, obj)
|
||||
local count = #tbl
|
||||
for i = 1, count do
|
||||
if tbl[i] == obj then
|
||||
return i
|
||||
for k, v in pairs(tbl) do
|
||||
if v == obj then
|
||||
return k
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Insert a new value into a table in the position after the specified
|
||||
-- existing value. If the specified value does not exist in the table,
|
||||
|
@ -37,6 +37,7 @@ return {
|
||||
"oven/test_objdirs.lua",
|
||||
|
||||
-- API tests
|
||||
"api/test_boolean_kind.lua",
|
||||
"api/test_containers.lua",
|
||||
"api/test_directory_kind.lua",
|
||||
"api/test_list_kind.lua",
|
||||
@ -114,6 +115,7 @@ return {
|
||||
"actions/vstudio/vc2010/test_project_refs.lua",
|
||||
"actions/vstudio/vc2010/test_prop_sheet.lua",
|
||||
"actions/vstudio/vc2010/test_resource_compile.lua",
|
||||
"actions/vstudio/vc2010/test_rule_vars.lua",
|
||||
|
||||
-- Visual Studio 2012
|
||||
"actions/vs2012/test_csproj_common_props.lua",
|
||||
|
@ -184,7 +184,7 @@ EndProject
|
||||
--
|
||||
|
||||
function suite.translatesEnvironmentVars()
|
||||
external "MyProject"
|
||||
externalProject "MyProject"
|
||||
location "$(SDK_LOCATION)/MyProject"
|
||||
uuid "30A1B994-C2C6-485F-911B-FB4674366DA8"
|
||||
kind "SharedLib"
|
||||
|
@ -16,6 +16,8 @@
|
||||
local sln
|
||||
|
||||
function suite.setup()
|
||||
rule "MyRules"
|
||||
rule "MyOtherRules"
|
||||
sln = test.createsolution()
|
||||
end
|
||||
|
||||
@ -45,8 +47,7 @@
|
||||
--
|
||||
|
||||
function suite.addsImport_onEachRulesFile()
|
||||
customRules "MyRules"
|
||||
customRules "MyOtherRules"
|
||||
rules { "MyRules", "MyOtherRules" }
|
||||
prepare()
|
||||
test.capture [[
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
@ -63,13 +64,13 @@
|
||||
--
|
||||
|
||||
function suite.usesProjectRelativePaths()
|
||||
customRules "path/to/MyRules"
|
||||
rules "MyRules"
|
||||
location "build"
|
||||
prepare()
|
||||
test.capture [[
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="..\path\to\MyRules.props" />
|
||||
<Import Project="..\MyRules.props" />
|
||||
</ImportGroup>
|
||||
]]
|
||||
end
|
||||
|
@ -16,6 +16,8 @@
|
||||
local sln
|
||||
|
||||
function suite.setup()
|
||||
rule "MyRules"
|
||||
rule "MyOtherRules"
|
||||
sln = test.createsolution()
|
||||
end
|
||||
|
||||
@ -45,8 +47,7 @@
|
||||
--
|
||||
|
||||
function suite.addsImport_onEachRulesFile()
|
||||
customRules "MyRules"
|
||||
customRules "MyOtherRules"
|
||||
rules { "MyRules", "MyOtherRules" }
|
||||
prepare()
|
||||
test.capture [[
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
@ -63,13 +64,13 @@
|
||||
--
|
||||
|
||||
function suite.usesProjectRelativePaths()
|
||||
customRules "path/to/MyRules"
|
||||
rules { "MyRules" }
|
||||
location "build"
|
||||
prepare()
|
||||
test.capture [[
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\path\to\MyRules.targets" />
|
||||
<Import Project="..\MyRules.targets" />
|
||||
</ImportGroup>
|
||||
]]
|
||||
end
|
||||
|
@ -16,6 +16,15 @@
|
||||
|
||||
function suite.setup()
|
||||
_ACTION = "vs2010"
|
||||
|
||||
rule "Animation"
|
||||
fileExtension ".dae"
|
||||
propertyDefinition {
|
||||
name = "AdditionalOptions",
|
||||
kind = "list",
|
||||
separator = ";"
|
||||
}
|
||||
|
||||
sln = test.createsolution()
|
||||
end
|
||||
|
||||
@ -522,12 +531,11 @@
|
||||
-- Check handling of files using custom rule definitions.
|
||||
--
|
||||
|
||||
function suite.correctlyCategorized_onCustomRule()
|
||||
function suite.isCategorizedByRule()
|
||||
rules "Animation"
|
||||
files { "hello.dae" }
|
||||
filter "files:**.dae"
|
||||
customRule "Animation"
|
||||
prepare()
|
||||
test.capture [[
|
||||
test.capture [[
|
||||
<ItemGroup>
|
||||
<Animation Include="hello.dae" />
|
||||
</ItemGroup>
|
||||
@ -535,107 +543,20 @@
|
||||
end
|
||||
|
||||
|
||||
function suite.customRule_onLiteralVars()
|
||||
function suite.listsPerConfigRuleVars()
|
||||
rules "Animation"
|
||||
files { "hello.dae" }
|
||||
filter "files:**.dae"
|
||||
customRule "Animation"
|
||||
customVar { "GenerateDebugInfo", "True" }
|
||||
filter { "files:hello.*", "configurations:Debug" }
|
||||
animationVars { AdditionalOptions = { "File1", "File2" }}
|
||||
filter { "files:hello.*", "configurations:Release" }
|
||||
animationVars { AdditionalOptions = { "File3" }}
|
||||
prepare()
|
||||
test.capture [[
|
||||
<ItemGroup>
|
||||
<Animation Include="hello.dae">
|
||||
<GenerateDebugInfo Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">True</GenerateDebugInfo>
|
||||
<GenerateDebugInfo Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">True</GenerateDebugInfo>
|
||||
<AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">File1;File2</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">File3</AdditionalOptions>
|
||||
</Animation>
|
||||
</ItemGroup>
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
function suite.customRule_onLiteralPath()
|
||||
targetdir "../bin/%{cfg.buildcfg}"
|
||||
files { "hello.dae" }
|
||||
filter "files:**.dae"
|
||||
customRule "Animation"
|
||||
customVar { "OutputDirectory", "%{cfg.targetdir}/anim" }
|
||||
prepare()
|
||||
test.capture [[
|
||||
<ItemGroup>
|
||||
<Animation Include="hello.dae">
|
||||
<OutputDirectory Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../bin/Debug/anim</OutputDirectory>
|
||||
<OutputDirectory Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../bin/Release/anim</OutputDirectory>
|
||||
</Animation>
|
||||
</ItemGroup>
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
function suite.customRule_onPerConfigLiteralVars()
|
||||
files { "hello.dae" }
|
||||
filter { "files:**.dae" }
|
||||
customRule "Animation"
|
||||
filter { "files:**.dae", "configurations:Debug" }
|
||||
customVar { "GenerateDebugInfo", "True" }
|
||||
prepare()
|
||||
test.capture [[
|
||||
<ItemGroup>
|
||||
<Animation Include="hello.dae">
|
||||
<GenerateDebugInfo Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">True</GenerateDebugInfo>
|
||||
</Animation>
|
||||
</ItemGroup>
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
function suite.customRule_onListVars()
|
||||
files { "hello.dae" }
|
||||
filter "files:**.dae"
|
||||
customRule "Animation"
|
||||
customList { "ExtraDependencies", "File1", "File2" }
|
||||
prepare()
|
||||
test.capture [[
|
||||
<ItemGroup>
|
||||
<Animation Include="hello.dae">
|
||||
<ExtraDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">File1 File2</ExtraDependencies>
|
||||
<ExtraDependencies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">File1 File2</ExtraDependencies>
|
||||
</Animation>
|
||||
</ItemGroup>
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
function suite.customRule_onPerConfigListVars()
|
||||
files { "hello.dae" }
|
||||
filter { "files:**.dae" }
|
||||
customRule "Animation"
|
||||
customList { "ExtraDependencies", "File1", "File2" }
|
||||
filter { "files:**.dae", "configurations:Release" }
|
||||
customList { "ExtraDependencies", "File3" }
|
||||
prepare()
|
||||
test.capture [[
|
||||
<ItemGroup>
|
||||
<Animation Include="hello.dae">
|
||||
<ExtraDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">File1 File2</ExtraDependencies>
|
||||
<ExtraDependencies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">File1 File2 File3</ExtraDependencies>
|
||||
</Animation>
|
||||
</ItemGroup>
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
function suite.customRule_onListVarsWithCustomFormat()
|
||||
files { "hello.dae" }
|
||||
filter "files:**.dae"
|
||||
customRule "Animation"
|
||||
customListFormat { "ExtraDependencies", ";" }
|
||||
customList { "ExtraDependencies", "File1", "File2" }
|
||||
prepare()
|
||||
test.capture [[
|
||||
<ItemGroup>
|
||||
<Animation Include="hello.dae">
|
||||
<ExtraDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">File1;File2</ExtraDependencies>
|
||||
<ExtraDependencies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">File1;File2</ExtraDependencies>
|
||||
</Animation>
|
||||
</ItemGroup>
|
||||
]]
|
||||
end
|
@ -171,9 +171,12 @@
|
||||
--
|
||||
|
||||
function suite.filter_onCustomRule()
|
||||
rules "Animation"
|
||||
files { "hello.dae" }
|
||||
filter "files:**.dae"
|
||||
customRule "Animation"
|
||||
|
||||
rule "Animation"
|
||||
fileExtension ".dae"
|
||||
|
||||
prepare()
|
||||
test.capture [[
|
||||
<ItemGroup>
|
||||
|
108
tests/actions/vstudio/vc2010/test_rule_vars.lua
Normal file
108
tests/actions/vstudio/vc2010/test_rule_vars.lua
Normal file
@ -0,0 +1,108 @@
|
||||
--
|
||||
-- tests/actions/vstudio/vc2010/test_rule_vars.lua
|
||||
-- Validate generation of custom rule variables at the project level.
|
||||
-- Copyright (c) 2014 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
local suite = test.declare("vstudio_vs2010_rule_vars")
|
||||
|
||||
local vc2010 = premake.vstudio.vc2010
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Setup
|
||||
--
|
||||
|
||||
local sln, prj
|
||||
|
||||
function suite.setup()
|
||||
rule "MyRule"
|
||||
sln, prj = test.createsolution()
|
||||
rules { "MyRule" }
|
||||
end
|
||||
|
||||
local function createVar(def)
|
||||
rule "MyRule"
|
||||
propertyDefinition(def)
|
||||
project "MyProject"
|
||||
end
|
||||
|
||||
local function prepare()
|
||||
local cfg = test.getconfig(prj, "Debug")
|
||||
vc2010.ruleVars(cfg)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If the configuration has a rule, but does not set any variables,
|
||||
-- nothing should be written.
|
||||
--
|
||||
|
||||
function suite.noOutput_onNoVars()
|
||||
prepare()
|
||||
test.isemptycapture()
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Test setting the various property kinds.
|
||||
--
|
||||
|
||||
function suite.onStringVar()
|
||||
createVar { name="MyVar", kind="string" }
|
||||
myRuleVars { MyVar = "hello" }
|
||||
prepare()
|
||||
test.capture [[
|
||||
<MyRule>
|
||||
<MyVar>hello</MyVar>
|
||||
</MyRule>
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
function suite.onBooleanVar()
|
||||
createVar { name="MyVar", kind="boolean" }
|
||||
myRuleVars { MyVar = false }
|
||||
prepare()
|
||||
test.capture [[
|
||||
<MyRule>
|
||||
<MyVar>false</MyVar>
|
||||
</MyRule>
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
function suite.onListVar()
|
||||
createVar { name="MyVar", kind="list" }
|
||||
myRuleVars { MyVar = { "a", "b", "c" } }
|
||||
prepare()
|
||||
test.capture [[
|
||||
<MyRule>
|
||||
<MyVar>a b c</MyVar>
|
||||
</MyRule>
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
function suite.onEnumVar()
|
||||
createVar {
|
||||
name = "MyVar",
|
||||
values = {
|
||||
[0] = "Win32",
|
||||
[1] = "Win64",
|
||||
},
|
||||
switch = {
|
||||
[0] = "-m32",
|
||||
[1] = "-m64",
|
||||
},
|
||||
value = 0,
|
||||
}
|
||||
myRuleVars { MyVar = "Win32" }
|
||||
prepare()
|
||||
test.capture [[
|
||||
<MyRule>
|
||||
<MyVar>0</MyVar>
|
||||
</MyRule>
|
||||
]]
|
||||
end
|
79
tests/api/test_boolean_kind.lua
Normal file
79
tests/api/test_boolean_kind.lua
Normal file
@ -0,0 +1,79 @@
|
||||
--
|
||||
-- tests/api/test_boolean_kind.lua
|
||||
-- Tests the boolean API value type.
|
||||
-- Copyright (c) 2014 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
local suite = test.declare("api_boolean_kind")
|
||||
local api = premake.api
|
||||
|
||||
|
||||
--
|
||||
-- Setup and teardown
|
||||
--
|
||||
|
||||
function suite.setup()
|
||||
api.register {
|
||||
name = "testapi",
|
||||
kind = "boolean",
|
||||
scope = "project",
|
||||
}
|
||||
test.createsolution()
|
||||
end
|
||||
|
||||
function suite.teardown()
|
||||
testapi = nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Check setting of true values.
|
||||
--
|
||||
|
||||
function suite.setsTrue_onYes()
|
||||
testapi "yes"
|
||||
test.istrue(api.scope.project.testapi)
|
||||
end
|
||||
|
||||
function suite.setsTrue_onBooleanTrue()
|
||||
testapi (true)
|
||||
test.istrue(api.scope.project.testapi)
|
||||
end
|
||||
|
||||
function suite.setsTrue_onNonZero()
|
||||
testapi (1)
|
||||
test.istrue(api.scope.project.testapi)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Check setting of false values.
|
||||
--
|
||||
|
||||
function suite.setsFalse_onNo()
|
||||
testapi "no"
|
||||
test.isfalse(api.scope.project.testapi)
|
||||
end
|
||||
|
||||
function suite.setsFalse_onBooleanFalse()
|
||||
testapi (false)
|
||||
test.isfalse(api.scope.project.testapi)
|
||||
end
|
||||
|
||||
function suite.setsFalse_onZero()
|
||||
testapi (0)
|
||||
test.isfalse(api.scope.project.testapi)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Raise an error on an invalid string value.
|
||||
--
|
||||
|
||||
function suite.raisesError_onDisallowedValue()
|
||||
ok, err = pcall(function ()
|
||||
testapi "maybe"
|
||||
end)
|
||||
test.isfalse(ok)
|
||||
end
|
@ -130,3 +130,17 @@
|
||||
premake.validate()
|
||||
test.stderr("'configurations' on config")
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If a rule is specified for inclusion, it must have been defined.
|
||||
--
|
||||
|
||||
function suite.fails_onNoSuchRule()
|
||||
solution "MySolution"
|
||||
configurations { "Debug", "Release" }
|
||||
project "MyProject"
|
||||
rules { "NoSuchRule" }
|
||||
test.isfalse(pcall(premake.validate))
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user