Merged premake/premake-dev into default

This commit is contained in:
M Skibbe 2014-11-13 10:19:36 +01:00
commit 97af7fb9b2
50 changed files with 946 additions and 467 deletions

View File

@ -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",

View File

@ -130,18 +130,35 @@
tokens = true,
}
api.register {
name = "cleanExtensions",
scope = "config",
kind = "list:string",
}
api.register {
name = "clr",
scope = "config",
kind = "string",
allowed = {
"Off",
"On",
"Pure",
"Safe",
"Unsafe",
}
}
api.register {
name = "configmap",
scope = "config",
kind = "list:keyed:array:string",
}
api.register {
name = "configFile",
scope = "config",
@ -162,13 +179,6 @@
tokens = true,
}
api.register {
name = "customRules",
scope = "project",
kind = "list:file",
tokens = true,
}
api.register {
name = "debugargs",
scope = "config",
@ -241,6 +251,13 @@
}
api.register {
name = "editAndContinue",
scope = "config",
kind = "boolean",
}
-- For backward compatibility, excludes() is now an alias for removefiles()
function excludes(value)
removefiles(value)
@ -285,14 +302,14 @@
"FloatFast", -- DEPRECATED
"FloatStrict", -- DEPRECATED
"LinkTimeOptimization",
"Managed",
"Managed", -- DEPRECATED
"Maps",
"MFC",
"MultiProcessorCompile",
"NativeWChar", -- DEPRECATED
"No64BitChecks",
"NoCopyLocal",
"NoEditAndContinue",
"NoEditAndContinue", -- DEPRECATED
"NoExceptions",
"NoFramePointer",
"NoImplicitLink",
@ -312,10 +329,12 @@
"OptimizeSpeed", -- DEPRECATED
"ReleaseRuntime",
"SEH",
"ShadowedVariables",
"StaticRuntime",
"Symbols",
"UndefinedIdentifiers",
"Unicode",
"Unsafe",
"Unsafe", -- DEPRECATED
"WinMain",
"WPF",
},
@ -624,6 +643,12 @@
tokens = true,
}
api.register {
name = "rules",
scope = "project",
kind = "list:string",
}
api.register {
name = "startproject",
scope = "solution",
@ -631,6 +656,18 @@
tokens = true,
}
api.register {
name = "strictaliasing",
scope = "config",
kind = "string",
allowed = {
"Off",
"Level1",
"Level2",
"Level3",
}
}
api.register {
name = "system",
scope = "config",
@ -764,7 +801,7 @@
-- 09 Apr 2013
api.deprecateField("buildrule", DOC_URL .. "Custom_Build_Commands",
api.deprecateField("buildrule", nil,
function(value)
if value.description then
buildmessage(value.description)
@ -773,16 +810,18 @@
buildoutputs(value.outputs)
end)
-- 17 Jun 2013
api.deprecateValue("flags", "Component", DOC_URL .. "buildaction",
api.deprecateValue("flags", "Component", nil,
function(value)
buildaction "Component"
end)
-- 26 Sep 2013
api.deprecateValue("flags", { "EnableSSE", "EnableSSE2" }, DOC_URL .. "vectorextensions",
api.deprecateValue("flags", { "EnableSSE", "EnableSSE2" }, nil,
function(value)
vectorextensions(value:sub(7))
end,
@ -790,7 +829,8 @@
vectorextension "Default"
end)
api.deprecateValue("flags", { "FloatFast", "FloatStrict" }, DOC_URL .. "floatingpoint",
api.deprecateValue("flags", { "FloatFast", "FloatStrict" }, nil,
function(value)
floatingpoint(value:sub(6))
end,
@ -798,7 +838,8 @@
floatingpoint "Default"
end)
api.deprecateValue("flags", { "NativeWChar", "NoNativeWChar" }, DOC_URL .. "nativewchar",
api.deprecateValue("flags", { "NativeWChar", "NoNativeWChar" }, nil,
function(value)
local map = { NativeWChar = "On", NoNativeWChar = "Off" }
nativewchar(map[value] or "Default")
@ -807,7 +848,8 @@
nativewchar "Default"
end)
api.deprecateValue("flags", { "Optimize", "OptimizeSize", "OptimizeSpeed" }, DOC_URL .. "optimize",
api.deprecateValue("flags", { "Optimize", "OptimizeSize", "OptimizeSpeed" }, nil,
function(value)
local map = { Optimize = "On", OptimizeSize = "Size", OptimizeSpeed = "Speed" }
optimize (map[value] or "Off")
@ -816,7 +858,8 @@
optimize "Off"
end)
api.deprecateValue("flags", { "Optimise", "OptimiseSize", "OptimiseSpeed" }, DOC_URL .. "optimize",
api.deprecateValue("flags", { "Optimise", "OptimiseSize", "OptimiseSpeed" }, nil,
function(value)
local map = { Optimise = "On", OptimiseSize = "Size", OptimiseSpeed = "Speed" }
optimize (map[value] or "Off")
@ -825,7 +868,8 @@
optimize "Off"
end)
api.deprecateValue("flags", { "ExtraWarnings", "NoWarnings" }, DOC_URL .. "warnings",
api.deprecateValue("flags", { "ExtraWarnings", "NoWarnings" }, nil,
function(value)
local map = { ExtraWarnings = "Extra", NoWarnings = "Off" }
warnings (map[value] or "Default")
@ -835,6 +879,36 @@
end)
-- 10 Nov 2014
api.deprecateValue("flags", "Managed", nil,
function(value)
clr "On"
end,
function(value)
clr "Off"
end)
api.deprecateValue("flags", "NoEditAndContinue", nil,
function(value)
editAndContinue "Off"
end,
function(value)
editAndContinue "On"
end)
api.deprecateValue("flags", "Unsafe", nil,
function(value)
clr "Unsafe"
end,
function(value)
clr "On"
end)
-----------------------------------------------------------------------------
--
-- Install Premake's default set of command line arguments.
@ -934,6 +1008,9 @@
--
-----------------------------------------------------------------------------
clr "Off"
editAndContinue "On"
-- Setting a default language makes some validation easier later
language "C++"

View File

@ -401,7 +401,7 @@
function make.ldFlags(cfg, toolset)
local flags = table.join(toolset.getLibraryDirectories(cfg), toolset.getldflags(cfg))
local flags = table.join(toolset.getLibraryDirectories(cfg), toolset.getldflags(cfg), cfg.linkoptions)
_p(' ALL_LDFLAGS += $(LDFLAGS)%s', make.list(flags))
end

View File

@ -222,7 +222,7 @@
_p(2,'<ErrorReport>prompt</ErrorReport>')
_p(2,'<WarningLevel>4</WarningLevel>')
if cfg.flags.Unsafe then
if cfg.clr == "Unsafe" then
_p(2,'<AllowUnsafeBlocks>true</AllowUnsafeBlocks>')
end

View File

@ -749,9 +749,9 @@
return 1
else
-- Edit-and-continue doesn't work for some configurations
if cfg.flags.NoEditAndContinue or
if not cfg.editAndContinue or
config.isOptimizedBuild(cfg) or
cfg.flags.Managed or
cfg.clr ~= p.OFF or
cfg.system == "x64"
then
return 3
@ -856,7 +856,7 @@
function m.additionalLinkerOptions(cfg, toolset)
local flags
if toolset then
flags = toolset.getldflags(cfg)
flags = table.join(toolset.getldflags(cfg), cfg.linkoptions)
else
flags = cfg.linkoptions
end
@ -922,7 +922,7 @@
local cfg, filecfg = config.normalize(cfg)
if not filecfg
and not config.isOptimizedBuild(cfg)
and not cfg.flags.Managed
and cfg.clr == p.OFF
and not cfg.flags.NoRuntimeChecks
then
p.w('BasicRuntimeChecks="3"')
@ -1062,7 +1062,7 @@
function m.detect64BitPortabilityProblems(cfg)
local prjcfg, filecfg = config.normalize(cfg)
if _ACTION < "vs2008" and not cfg.flags.Managed and cfg.warnings ~= "Off" and not filecfg then
if _ACTION < "vs2008" and cfg.clr == p.OFF and cfg.warnings ~= p.OFF and not filecfg then
p.w('Detect64BitPortabilityProblems="%s"', tostring(not cfg.flags.No64BitChecks))
end
end
@ -1164,7 +1164,7 @@
local windows, managed, makefile
for cfg in project.eachconfig(prj) do
if cfg.system == p.WINDOWS then windows = true end
if cfg.flags.Managed then managed = true end
if cfg.clr ~= p.OFF then managed = true end
if vstudio.isMakefile(cfg) then makefile = true end
end
@ -1261,7 +1261,7 @@
function m.managedExtensions(cfg)
if cfg.flags.Managed then
if cfg.clr ~= p.OFF then
p.w('ManagedExtensions="1"')
end
end
@ -1272,7 +1272,7 @@
if config.isDebugBuild(cfg) and
cfg.debugformat ~= "c7" and
not cfg.flags.NoMinimalRebuild and
not cfg.flags.Managed and
cfg.clr == p.OFF and
not cfg.flags.MultiProcessorCompile
then
p.w('MinimalRebuild="true"')
@ -1500,7 +1500,7 @@
function m.runtimeTypeInfo(cfg)
if cfg.flags.NoRTTI and not cfg.flags.Managed then
if cfg.flags.NoRTTI and cfg.clr == p.OFF then
p.w('RuntimeTypeInfo="false"')
end
end
@ -1607,7 +1607,7 @@
function m.warnAsError(cfg)
if cfg.flags.FatalCompileWarnings and cfg.warnings ~= "Off" then
if cfg.flags.FatalCompileWarnings and cfg.warnings ~= p.OFF then
p.w('WarnAsError="true"')
end
end
@ -1618,7 +1618,7 @@
local prjcfg, filecfg = config.normalize(cfg)
local level
if cfg.warnings == "Off" then
if cfg.warnings == p.OFF then
level = "0"
elseif cfg.warnings == "Extra" then
level = "4"

View File

@ -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"
@ -823,7 +817,7 @@
--
m.elements.projectReferences = function(prj, ref)
if prj.flags.Managed then
if prj.clr ~= p.OFF then
return {
m.referenceProject,
m.referencePrivate,
@ -957,8 +951,14 @@
function m.clrSupport(cfg)
if cfg.flags.Managed then
_p(2,'<CLRSupport>true</CLRSupport>')
local value
if cfg.clr == "On" or cfg.clr == "Unsafe" then
value = "true"
elseif cfg.clr ~= p.OFF then
value = cfg.clr
end
if value then
p.w('<CLRSupport>%s</CLRSupport>', value)
end
end
@ -998,9 +998,9 @@
if cfg.debugformat == "c7" then
value = "OldStyle"
elseif cfg.architecture == "x64" or
cfg.flags.Managed or
cfg.clr ~= p.OFF or
config.isOptimizedBuild(cfg) or
cfg.flags.NoEditAndContinue
not cfg.editAndContinue
then
value = "ProgramDatabase"
else
@ -1045,7 +1045,7 @@
function m.entryPointSymbol(cfg)
if (cfg.kind == premake.CONSOLEAPP or cfg.kind == premake.WINDOWEDAPP) and
not cfg.flags.WinMain and
not cfg.flags.Managed and
cfg.clr == p.OFF and
cfg.system ~= premake.XBOX360
then
_p(3,'<EntryPointSymbol>mainCRTStartup</EntryPointSymbol>')
@ -1155,11 +1155,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 +1176,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
@ -1212,7 +1216,7 @@
if cfg.system == premake.WINDOWS then
isWin = true
end
if cfg.flags.Managed then
if cfg.clr ~= p.OFF then
isManaged = true
end
if vstudio.isMakefile(cfg) then
@ -1486,7 +1490,7 @@
function m.runtimeTypeInfo(cfg)
if cfg.flags.NoRTTI and not cfg.flags.Managed then
if cfg.flags.NoRTTI and cfg.clr == p.OFF then
_p(3,'<RuntimeTypeInfo>false</RuntimeTypeInfo>')
end
end
@ -1546,7 +1550,7 @@
function m.treatWarningAsError(cfg)
if cfg.flags.FatalCompileWarnings and cfg.warnings ~= "Off" then
if cfg.flags.FatalCompileWarnings and cfg.warnings ~= p.OFF then
p.w('<TreatWarningAsError>true</TreatWarningAsError>')
end
end

View File

@ -46,7 +46,17 @@
end
_G[containerName] = function(name)
return api._setContainer(class, name)
local c = api._setContainer(class, name)
if api._isIncludingExternal then
c.external = true
end
return c
end
_G["external" .. containerName:capitalized()] = function(name)
local c = _G[containerName](name)
c.external = true
return c
end
return class
@ -54,6 +64,20 @@
---
-- Register a general-purpose includeExternal() call which works just like
-- include(), but marks any containers created while evaluating the included
-- scripts as external.
---
function includeExternal(fname)
api._isIncludingExternal = true
include(fname)
api._isIncludingExternal = nil
end
---
-- Return the global configuration container. You could just call global()
-- too, but this is much faster.
@ -238,7 +262,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,15 +484,15 @@
-- 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
if field.deprecated and type(field.deprecated.handler) == "function" then
field.deprecated.handler(value)
if api._deprecations ~= "off" then
premake.warnOnce(field.name, "the field %s has been deprecated.\n %s", field.name, field.deprecated.message or "")
if field.deprecated.message and api._deprecations ~= "off" then
premake.warnOnce(field.name, "the field %s has been deprecated.\n %s", field.name, field.deprecated.message)
if api._deprecations == "error" then error("deprecation errors enabled", 3) end
end
end
@ -486,6 +510,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 +521,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
@ -517,9 +542,9 @@
if field.deprecated[value] then
local handler = field.deprecated[value]
if handler.remove then handler.remove(value) end
if api._deprecations ~= "off" then
if handler.message and api._deprecations ~= "off" then
local key = field.name .. "_" .. value
premake.warnOnce(key, "the %s value %s has been deprecated.\n %s", field.name, value, handler.message or "")
premake.warnOnce(key, "the %s value %s has been deprecated.\n %s", field.name, value, handler.message)
if api._deprecations == "error" then
error { msg="deprecation errors enabled" }
end
@ -618,9 +643,9 @@
if field.deprecated and field.deprecated[canonical] then
local handler = field.deprecated[canonical]
handler.add(canonical)
if api._deprecations ~= "off" then
if handler.message and api._deprecations ~= "off" then
local key = field.name .. "_" .. value
premake.warnOnce(key, "the %s value %s has been deprecated.\n %s", field.name, canonical, handler.message or "")
premake.warnOnce(key, "the %s value %s has been deprecated.\n %s", field.name, canonical, handler.message)
if api._deprecations == "error" then
return nil, "deprecation errors enabled"
end
@ -639,18 +664,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 +703,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 +1101,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 +1123,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

View File

@ -4,9 +4,12 @@
-- Copyright (c) 2011-2013 Jason Perkins and the Premake project
--
premake.config = {}
local project = premake.project
local config = premake.config
local p = premake
p.config = {}
local project = p.project
local config = p.config
---
@ -91,8 +94,8 @@
-- Can't link managed and unmanaged projects
local cfgManaged = project.isdotnet(cfg.project) or (cfg.flags.Managed ~= nil)
local tgtManaged = project.isdotnet(target.project) or (target.flags.Managed ~= nil)
local cfgManaged = project.isdotnet(cfg.project) or (cfg.clr ~= p.OFF)
local tgtManaged = project.isdotnet(target.project) or (target.clr ~= p.OFF)
return (cfgManaged == tgtManaged)
end
@ -111,7 +114,7 @@
-- Unmanaged projects can never link managed assemblies
if isManaged and not cfg.flags.Managed then
if isManaged and cfg.clr == p.OFF then
return false
end
@ -438,7 +441,7 @@
--
function config.isOptimizedBuild(cfg)
return cfg.optimize ~= nil and cfg.optimize ~= "Off" and cfg.optimize ~= "Debug"
return cfg.optimize ~= nil and cfg.optimize ~= p.OFF and cfg.optimize ~= "Debug"
end

View File

@ -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)

View File

@ -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] = {}

View File

@ -79,6 +79,10 @@
end
function expandvalue(value)
if type(value) ~= "string" then
return
end
local count
repeat
value, count = value:gsub("%%{(.-)}", function(token)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

161
src/base/rule.lua Normal file
View File

@ -0,0 +1,161 @@
---
-- 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. Do a version with lowercased
-- first letter(s) to match Premake's naming style for other calls
_G[name .. "Vars"] = function(vars)
rule.setVars(self, vars)
end
local lowerName = name:gsub("^%u+", string.lower)
_G[lowerName .. "Vars"] = _G[name .. "Vars"]
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

View File

@ -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

View File

@ -18,7 +18,6 @@
function solution.new(name)
local sln = p.container.new(solution, name)
sln.filename = name
return sln
end

View File

@ -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
--

View File

@ -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,

View File

@ -49,7 +49,7 @@ LUALIB_API int luaL_loadfile (lua_State* L, const char* filename)
const char* script_dir;
lua_getglobal(L, "_SCRIPT_DIR");
script_dir = lua_tostring(L, -1);
if (script_dir[0] == '$') {
if (script_dir && script_dir[0] == '$') {
/* call path.getabsolute() to handle ".." if present */
lua_pushcfunction(L, path_getabsolute);
lua_pushstring(L, filename);
@ -75,7 +75,7 @@ LUALIB_API int luaL_loadfile (lua_State* L, const char* filename)
if (z == OKAY) {
lua_pushcclosure(L, chunk_wrapper, 2);
}
else {
else if (z == LUA_YIELD) {
lua_pushstring(L, "cannot open ");
lua_pushstring(L, filename);
lua_pushstring(L, ": No such file or directory");

View File

@ -332,11 +332,5 @@ int premake_load_embedded_script(lua_State* L, const char* filename)
lua_concat(L, 2);
/* Load the chunk */
i = luaL_loadbuffer(L, chunk, strlen(chunk), filename);
if (i != OKAY) {
lua_pop(L, 1);
printf("Failed to load embedded script '%s': %s\n", filename, lua_tostring(L, -1));
}
return i;
return luaL_loadbuffer(L, chunk, strlen(chunk), filename);
}

View File

@ -166,7 +166,6 @@
function clang.getldflags(cfg)
local flags = config.mapFlags(cfg, clang.ldflags)
flags = table.join(flags, cfg.linkoptions)
return flags
end

View File

@ -200,10 +200,12 @@
--
dotnet.flags = {
clr = {
Unsafe = "/unsafe",
},
flags = {
FatalWarning = "/warnaserror",
Symbols = "/debug",
Unsafe = "/unsafe"
},
optimize = {
On = "/optimize",

View File

@ -40,7 +40,9 @@
flags = {
FatalCompileWarnings = "-Werror",
NoFramePointer = "-fomit-frame-pointer",
Symbols = "-g"
ShadowedVariables = "-Wshadow",
Symbols = "-g",
UndefinedIdentifiers = "-Wundef",
},
floatingpoint = {
Fast = "-ffast-math",
@ -51,6 +53,12 @@
if cfg.system ~= premake.WINDOWS then return "-fPIC" end
end,
},
strictaliasing = {
Off = "-fno-strict-aliasing",
Level1 = { "-fstrict-aliasing", "-Wstrict-aliasing=1" },
Level2 = { "-fstrict-aliasing", "-Wstrict-aliasing=2" },
Level3 = { "-fstrict-aliasing", "-Wstrict-aliasing=3" },
},
optimize = {
Off = "-O0",
On = "-O2",
@ -177,7 +185,6 @@
function gcc.getldflags(cfg)
local flags = config.mapFlags(cfg, gcc.ldflags)
flags = table.join(flags, cfg.linkoptions)
return flags
end

View File

@ -25,6 +25,12 @@
--
msc.cflags = {
clr = {
On = "/clr",
Unsafe = "/clr",
Pure = "/clr:pure",
Safe = "/clr:safe",
},
flags = {
FatalCompileWarnings = "/WX",
MultiProcessorCompile = "/MP",
@ -168,7 +174,6 @@
function msc.getldflags(cfg)
local map = iif(cfg.kind ~= premake.STATICLIB, msc.linkerFlags, msc.librarianFlags)
local flags = config.mapFlags(cfg, map)
flags = table.join(flags, cfg.linkoptions)
table.insert(flags, 1, "/NOLOGO")
return flags
end

View File

@ -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",

View File

@ -43,7 +43,7 @@
--
function suite.onUnsafe()
flags { "Unsafe" }
clr "Unsafe"
prepare()
test.capture [[
FLAGS = /unsafe /noconfig

View File

@ -44,7 +44,7 @@
--
function suite.allowUnsafeBlocks_onUnsafeFlag()
flags { "Unsafe" }
clr "Unsafe"
prepare()
test.capture [[
<DefineConstants></DefineConstants>

View File

@ -184,7 +184,7 @@ EndProject
--
function suite.translatesEnvironmentVars()
external "MyProject"
externalProject "MyProject"
location "$(SDK_LOCATION)/MyProject"
uuid "30A1B994-C2C6-485F-911B-FB4674366DA8"
kind "SharedLib"

View File

@ -16,7 +16,7 @@
function suite.setup()
sln = test.createsolution()
flags { "Managed" }
clr "On"
end
local function prepare(platform)

View File

@ -364,7 +364,7 @@
-- Verify the correct Detect64BitPortabilityProblems settings are used when _ACTION < "VS2008".
--
function suite.runtimeLibraryIsDebug_onVS2005()
function suite._64BitPortabilityOn_onVS2005()
_ACTION = "vs2005"
prepare()
test.capture [[
@ -382,6 +382,23 @@
]]
end
function suite._64BitPortabilityOff_onVS2005_andCLR()
_ACTION = "vs2005"
clr "On"
prepare()
test.capture [[
<Tool
Name="VCCLCompilerTool"
Optimization="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="0"
/>
]]
end
--
-- Verify the correct warnings settings are used when no warnings are enabled.

View File

@ -76,7 +76,7 @@
--
function suite.keywordIsCorrect_onManagedC()
flags { "Managed" }
clr "On"
prepare()
test.capture [[
<VisualStudioProject

View File

@ -16,7 +16,7 @@
function suite.setup()
sln = test.createsolution()
flags { "Managed" }
clr "On"
end
local function prepare(platform)

View File

@ -569,11 +569,12 @@
--
-- Check the handling of the NoEditAndContinue flag.
-- Check the handling of the editAndContinue flag.
--
function suite.debugFormat_onNoEditAndContinue()
flags { "Symbols", "NoEditAndContinue" }
function suite.debugFormat_onEditAndContinueOff()
flags { "Symbols" }
editAndContinue "Off"
prepare()
test.capture [[
<ClCompile>
@ -606,7 +607,8 @@
--
function suite.debugFormat_onManagedCode()
flags { "Symbols", "Managed" }
flags "Symbols"
clr "On"
prepare()
test.capture [[
<ClCompile>

View File

@ -110,12 +110,13 @@
]]
end
--
-- Check the support for Managed C++.
--
function suite.clrSupport_onManaged()
flags "Managed"
function suite.clrSupport_onClrOn()
clr "On"
prepare()
test.capture [[
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -125,6 +126,50 @@
]]
end
function suite.clrSupport_onClrOff()
clr "Off"
prepare()
test.capture [[
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
]]
end
function suite.clrSupport_onClrUnsafe()
clr "Unsafe"
prepare()
test.capture [[
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
]]
end
function suite.clrSupport_onClrSafe()
clr "Safe"
prepare()
test.capture [[
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>Safe</CLRSupport>
]]
end
function suite.clrSupport_onClrPure()
clr "Pure"
prepare()
test.capture [[
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>Pure</CLRSupport>
]]
end
--
-- Check the support for building with MFC.
--

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -46,7 +46,7 @@
--
function suite.keywordIsCorrect_onManagedC()
flags { "Managed" }
clr "On"
prepare()
test.capture [[
<PropertyGroup Label="Globals">
@ -64,7 +64,7 @@
--
function suite.frameworkVersionIsCorrect_onManagedC()
flags { "Managed" }
clr "On"
framework "4.5"
prepare()
test.capture [[

View File

@ -82,7 +82,7 @@
function suite.referencesAreRelative_onDifferentProjectLocation()
links { "MyProject" }
flags { "Managed" }
clr "On"
prepare()
test.capture [[
<ItemGroup>

View 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

View 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

View File

@ -175,16 +175,16 @@
function suite.remove_onExactValueMatch()
local f = field.get("flags")
configset.store(cset, f, { "Symbols", "Unsafe", "NoRTTI" })
configset.remove(cset, f, { "Unsafe" })
configset.store(cset, f, { "Symbols", "WinMain", "NoRTTI" })
configset.remove(cset, f, { "WinMain" })
test.isequal({ "Symbols", "NoRTTI" }, configset.fetch(cset, f, {}))
end
function suite.remove_onMultipleValues()
local f = field.get("flags")
configset.store(cset, f, { "Symbols", "NoExceptions", "Unsafe", "NoRTTI" })
configset.store(cset, f, { "Symbols", "NoExceptions", "WinMain", "NoRTTI" })
configset.remove(cset, f, { "NoExceptions", "NoRTTI" })
test.isequal({ "Symbols", "Unsafe" }, configset.fetch(cset, f, {}))
test.isequal({ "Symbols", "WinMain" }, configset.fetch(cset, f, {}))
end

View File

@ -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

View File

@ -111,7 +111,7 @@
function suite.skipsAssemblies_onManagedCpp()
system "windows"
flags { "Managed" }
clr "On"
links { "user32", "System.dll" }
local r = prepare("all", "fullpath")
test.isequal({ "user32.lib" }, r)
@ -125,7 +125,7 @@
function suite.skipsUnmanagedLibs_onManagedLinkage()
system "windows"
flags { "Managed" }
clr "On"
links { "user32", "System.dll" }
local r = prepare("all", "fullpath", "managed")
test.isequal({ "System.dll" }, r)
@ -161,20 +161,20 @@
end
function suite.canLink_ManagedCppAndManagedCpp()
flags { "Managed" }
clr "On"
links { "MyProject2" }
project "MyProject2"
kind "StaticLib"
language "C++"
flags { "Managed" }
clr "On"
local r = prepare("all", "fullpath")
test.isequal({ "MyProject2.lib" }, r)
end
function suite.canLink_ManagedCppAndCs()
flags { "Managed" }
clr "On"
links { "MyProject2" }
project "MyProject2"

View File

@ -402,3 +402,32 @@
test.isequal({ '-I"$(IntDir)/includes"' }, gcc.getincludedirs(cfg, cfg.includedirs))
end
--
-- Check handling of strict aliasing flags.
--
function suite.cflags_onNoStrictAliasing()
strictaliasing "Off"
prepare()
test.contains("-fno-strict-aliasing", gcc.getcflags(cfg))
end
function suite.cflags_onLevel1Aliasing()
strictaliasing "Level1"
prepare()
test.contains({ "-fstrict-aliasing", "-Wstrict-aliasing=1" }, gcc.getcflags(cfg))
end
function suite.cflags_onLevel2Aliasing()
strictaliasing "Level2"
prepare()
test.contains({ "-fstrict-aliasing", "-Wstrict-aliasing=2" }, gcc.getcflags(cfg))
end
function suite.cflags_onLevel3Aliasing()
strictaliasing "Level3"
prepare()
test.contains({ "-fstrict-aliasing", "-Wstrict-aliasing=3" }, gcc.getcflags(cfg))
end

View File

@ -235,3 +235,33 @@
prepare()
test.contains("/DLL", msc.getldflags(cfg))
end
--
-- Check handling of CLR settings.
--
function suite.cflags_onClrOn()
clr "On"
prepare()
test.contains("/clr", msc.getcflags(cfg))
end
function suite.cflags_onClrUnsafe()
clr "Unsafe"
prepare()
test.contains("/clr", msc.getcflags(cfg))
end
function suite.cflags_onClrSafe()
clr "Safe"
prepare()
test.contains("/clr:safe", msc.getcflags(cfg))
end
function suite.cflags_onClrPure()
clr "Pure"
prepare()
test.contains("/clr:pure", msc.getcflags(cfg))
end