Improve rule support:
- move rule code from gmake2.lua to rule.lua - Add UTs - Fix enum case - uniformise code for list. - Add support of rules for Codelite.
This commit is contained in:
parent
6c9fda87b5
commit
29fa743f19
@ -379,38 +379,51 @@
|
|||||||
_p(4, '<CustomPostBuild/>')
|
_p(4, '<CustomPostBuild/>')
|
||||||
|
|
||||||
local dependencies = {}
|
local dependencies = {}
|
||||||
local rules = {}
|
local makefilerules = {}
|
||||||
local function addrule(dependencies, rules, config, filename)
|
local function addrule(dependencies, makefilerules, config, filename)
|
||||||
if #config.buildcommands == 0 or #config.buildOutputs == 0 then
|
if #config.buildcommands == 0 or #config.buildOutputs == 0 then
|
||||||
return
|
return false
|
||||||
end
|
end
|
||||||
local inputs = table.implode(config.buildInputs,"",""," ")
|
local inputs = table.implode(project.getrelative(cfg.project, config.buildInputs), "", "", " ")
|
||||||
if filename ~= "" and inputs ~= "" then
|
if filename ~= "" and inputs ~= "" then
|
||||||
filename = filename .. " "
|
filename = filename .. " "
|
||||||
end
|
end
|
||||||
local outputs = config.buildOutputs[1]
|
local outputs = project.getrelative(cfg.project, config.buildOutputs[1])
|
||||||
local buildmessage = ""
|
local buildmessage = ""
|
||||||
if config.buildmessage then
|
if config.buildmessage then
|
||||||
buildmessage = "\t@{ECHO} " .. config.buildmessage .. "\n"
|
buildmessage = "\t@{ECHO} " .. config.buildmessage .. "\n"
|
||||||
end
|
end
|
||||||
local commands = table.implode(config.buildCommands,"\t","\n","")
|
local commands = table.implode(config.buildCommands,"\t","\n","")
|
||||||
table.insert(rules, os.translateCommandsAndPaths(outputs .. ": " .. filename .. inputs .. "\n" .. buildmessage .. commands, cfg.project.basedir, cfg.project.location))
|
table.insert(makefilerules, os.translateCommandsAndPaths(outputs .. ": " .. filename .. inputs .. "\n" .. buildmessage .. commands, cfg.project.basedir, cfg.project.location))
|
||||||
table.insertflat(dependencies, config.buildOutputs[1])
|
table.insertflat(dependencies, outputs)
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
local tr = project.getsourcetree(cfg.project)
|
local tr = project.getsourcetree(cfg.project)
|
||||||
p.tree.traverse(tr, {
|
p.tree.traverse(tr, {
|
||||||
onleaf = function(node, depth)
|
onleaf = function(node, depth)
|
||||||
local filecfg = p.fileconfig.getconfig(node, cfg)
|
local filecfg = p.fileconfig.getconfig(node, cfg)
|
||||||
addrule(dependencies, rules, filecfg, node.relpath)
|
local prj = cfg.project
|
||||||
|
local rule = p.global.getRuleForFile(node.name, prj.rules)
|
||||||
|
|
||||||
|
if not addrule(dependencies, makefilerules, filecfg, node.relpath) and rule then
|
||||||
|
local environ = table.shallowcopy(filecfg.environ)
|
||||||
|
|
||||||
|
if rule.propertydefinition then
|
||||||
|
p.rule.prepareEnvironment(rule, environ, cfg)
|
||||||
|
p.rule.prepareEnvironment(rule, environ, filecfg)
|
||||||
|
end
|
||||||
|
local rulecfg = p.context.extent(rule, environ)
|
||||||
|
addrule(dependencies, makefilerules, rulecfg, node.relpath)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
addrule(dependencies, rules, cfg, "")
|
addrule(dependencies, makefilerules, cfg, "")
|
||||||
|
|
||||||
if #rules == 0 and #dependencies == 0 then
|
if #makefilerules == 0 and #dependencies == 0 then
|
||||||
_p(4, '<CustomPreBuild/>')
|
_p(4, '<CustomPreBuild/>')
|
||||||
else
|
else
|
||||||
_p(4, '<CustomPreBuild>' .. table.implode(dependencies,"",""," "))
|
_p(4, '<CustomPreBuild>' .. table.implode(dependencies,"",""," "))
|
||||||
_p(0, table.implode(rules,"","","\n") .. '</CustomPreBuild>')
|
_p(0, table.implode(makefilerules,"","","\n") .. '</CustomPreBuild>')
|
||||||
end
|
end
|
||||||
_p(3, '</AdditionalRules>')
|
_p(3, '</AdditionalRules>')
|
||||||
end
|
end
|
||||||
|
@ -4,4 +4,5 @@ return {
|
|||||||
"test_codelite_workspace.lua",
|
"test_codelite_workspace.lua",
|
||||||
"test_codelite_project.lua",
|
"test_codelite_project.lua",
|
||||||
"test_codelite_config.lua",
|
"test_codelite_config.lua",
|
||||||
|
"test_codelite_additional_rules.lua",
|
||||||
}
|
}
|
||||||
|
256
modules/codelite/tests/test_codelite_additional_rules.lua
Normal file
256
modules/codelite/tests/test_codelite_additional_rules.lua
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
---
|
||||||
|
-- codelite/tests/test_codelite_config.lua
|
||||||
|
-- Automated test suite for CodeLite project generation.
|
||||||
|
-- Copyright (c) 2021 Joris Dauphin and the Premake project
|
||||||
|
---
|
||||||
|
|
||||||
|
local suite = test.declare("codelite_cproj_additional_rules")
|
||||||
|
local p = premake
|
||||||
|
local codelite = p.modules.codelite
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- Setup/Teardown
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local wks, prj, cfg
|
||||||
|
|
||||||
|
local function prepare_rule()
|
||||||
|
rule "TestRule"
|
||||||
|
display "Test Rule"
|
||||||
|
fileextension ".rule"
|
||||||
|
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestProperty",
|
||||||
|
kind = "boolean",
|
||||||
|
value = false,
|
||||||
|
switch = "-p"
|
||||||
|
}
|
||||||
|
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestProperty2",
|
||||||
|
kind = "boolean",
|
||||||
|
value = false,
|
||||||
|
switch = "-p2"
|
||||||
|
}
|
||||||
|
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestListProperty",
|
||||||
|
kind = "list"
|
||||||
|
}
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestListPropertyWithSwitch",
|
||||||
|
kind = "list",
|
||||||
|
switch = "-S"
|
||||||
|
}
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestListPropertySeparator",
|
||||||
|
kind = "list",
|
||||||
|
separator = ","
|
||||||
|
}
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestListPropertySeparatorWithSwitch",
|
||||||
|
kind = "list",
|
||||||
|
separator = ",",
|
||||||
|
switch = "-O"
|
||||||
|
}
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestEnumProperty",
|
||||||
|
values = { [0] = "V0", [1] = "V1"},
|
||||||
|
switch = { [0] = "S0", [1] = "S1"},
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
buildmessage 'Rule-ing %{file.name}'
|
||||||
|
buildcommands 'dorule %{TestProperty} %{TestProperty2} %{TestListProperty} %{TestListPropertyWithSwitch} %{TestListPropertySeparator} %{TestListPropertySeparatorWithSwitch} %{TestEnumProperty} "%{file.path}"'
|
||||||
|
buildoutputs { "%{file.basename}.obj" }
|
||||||
|
end
|
||||||
|
|
||||||
|
function suite.setup()
|
||||||
|
p.action.set("codelite")
|
||||||
|
p.escaper(codelite.esc)
|
||||||
|
p.indent(" ")
|
||||||
|
prepare_rule()
|
||||||
|
wks = test.createWorkspace()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function prepare()
|
||||||
|
prj = test.getproject(wks, 1)
|
||||||
|
cfg = test.getconfig(prj, "Debug")
|
||||||
|
end
|
||||||
|
|
||||||
|
function suite.customRuleEmpty()
|
||||||
|
prepare()
|
||||||
|
codelite.project.additionalRules(prj)
|
||||||
|
test.capture [[
|
||||||
|
<AdditionalRules>
|
||||||
|
<CustomPostBuild/>
|
||||||
|
<CustomPreBuild/>
|
||||||
|
</AdditionalRules>
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
function suite.customRuleWithPropertyDefinition()
|
||||||
|
rules { "TestRule" }
|
||||||
|
|
||||||
|
files { "test.rule", "test2.rule" }
|
||||||
|
|
||||||
|
testRuleVars {
|
||||||
|
TestProperty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
filter "files:test2.rule"
|
||||||
|
testRuleVars {
|
||||||
|
TestProperty2 = true
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare()
|
||||||
|
codelite.project.additionalRules(cfg)
|
||||||
|
|
||||||
|
test.capture [[
|
||||||
|
<AdditionalRules>
|
||||||
|
<CustomPostBuild/>
|
||||||
|
<CustomPreBuild>test.obj test2.obj
|
||||||
|
test.obj: test.rule
|
||||||
|
@echo Rule-ing test.rule
|
||||||
|
dorule -p "test.rule"
|
||||||
|
|
||||||
|
test2.obj: test2.rule
|
||||||
|
@echo Rule-ing test2.rule
|
||||||
|
dorule -p -p2 "test2.rule"
|
||||||
|
</CustomPreBuild>
|
||||||
|
</AdditionalRules>
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
function suite.customRuleWithPropertyDefinitionSeparator()
|
||||||
|
|
||||||
|
rules { "TestRule" }
|
||||||
|
|
||||||
|
files { "test.rule", "test2.rule", "test3.rule", "test4.rule" }
|
||||||
|
|
||||||
|
filter "files:test.rule"
|
||||||
|
testRuleVars {
|
||||||
|
TestListProperty = { "testValue1", "testValue2" }
|
||||||
|
}
|
||||||
|
|
||||||
|
filter "files:test2.rule"
|
||||||
|
testRuleVars {
|
||||||
|
TestListPropertyWithSwitch = { "testValue1", "testValue2" }
|
||||||
|
}
|
||||||
|
|
||||||
|
filter "files:test3.rule"
|
||||||
|
testRuleVars {
|
||||||
|
TestListPropertySeparator = { "testValue1", "testValue2" }
|
||||||
|
}
|
||||||
|
|
||||||
|
filter "files:test4.rule"
|
||||||
|
testRuleVars {
|
||||||
|
TestListPropertySeparatorWithSwitch = { "testValue1", "testValue2" }
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare()
|
||||||
|
codelite.project.additionalRules(cfg)
|
||||||
|
|
||||||
|
test.capture [[
|
||||||
|
<AdditionalRules>
|
||||||
|
<CustomPostBuild/>
|
||||||
|
<CustomPreBuild>test.obj test2.obj test3.obj test4.obj
|
||||||
|
test.obj: test.rule
|
||||||
|
@echo Rule-ing test.rule
|
||||||
|
dorule testValue1 testValue2 "test.rule"
|
||||||
|
|
||||||
|
test2.obj: test2.rule
|
||||||
|
@echo Rule-ing test2.rule
|
||||||
|
dorule -StestValue1 -StestValue2 "test2.rule"
|
||||||
|
|
||||||
|
test3.obj: test3.rule
|
||||||
|
@echo Rule-ing test3.rule
|
||||||
|
dorule testValue1,testValue2 "test3.rule"
|
||||||
|
|
||||||
|
test4.obj: test4.rule
|
||||||
|
@echo Rule-ing test4.rule
|
||||||
|
dorule -OtestValue1,testValue2 "test4.rule"
|
||||||
|
</CustomPreBuild>
|
||||||
|
</AdditionalRules>
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
function suite.customRuleWithPropertyDefinitionEnum()
|
||||||
|
rules { "TestRule" }
|
||||||
|
|
||||||
|
files { "test.rule", "test2.rule" }
|
||||||
|
|
||||||
|
testRuleVars {
|
||||||
|
TestEnumProperty = "V0"
|
||||||
|
}
|
||||||
|
|
||||||
|
filter "files:test2.rule"
|
||||||
|
testRuleVars {
|
||||||
|
TestEnumProperty = "V1"
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare()
|
||||||
|
codelite.project.additionalRules(cfg)
|
||||||
|
|
||||||
|
test.capture [[
|
||||||
|
<AdditionalRules>
|
||||||
|
<CustomPostBuild/>
|
||||||
|
<CustomPreBuild>test.obj test2.obj
|
||||||
|
test.obj: test.rule
|
||||||
|
@echo Rule-ing test.rule
|
||||||
|
dorule S0 "test.rule"
|
||||||
|
|
||||||
|
test2.obj: test2.rule
|
||||||
|
@echo Rule-ing test2.rule
|
||||||
|
dorule S1 "test2.rule"
|
||||||
|
</CustomPreBuild>
|
||||||
|
</AdditionalRules>
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
function suite.buildCommand()
|
||||||
|
files {"foo.txt", "bar.txt"}
|
||||||
|
buildinputs { "toto.txt", "extra_dependency" }
|
||||||
|
buildoutputs { "toto.c" }
|
||||||
|
buildcommands { "test", "test toto.c" }
|
||||||
|
buildmessage "Some message"
|
||||||
|
prepare()
|
||||||
|
codelite.project.additionalRules(cfg)
|
||||||
|
test.capture [[
|
||||||
|
<AdditionalRules>
|
||||||
|
<CustomPostBuild/>
|
||||||
|
<CustomPreBuild>toto.c
|
||||||
|
toto.c: toto.txt extra_dependency
|
||||||
|
@echo Some message
|
||||||
|
test
|
||||||
|
test toto.c
|
||||||
|
</CustomPreBuild>
|
||||||
|
</AdditionalRules>]]
|
||||||
|
end
|
||||||
|
|
||||||
|
function suite.buildCommandPerFile()
|
||||||
|
files {"foo.txt", "bar.txt"}
|
||||||
|
filter "files:**.txt"
|
||||||
|
buildinputs { "%{file.basename}.h", "extra_dependency" }
|
||||||
|
buildoutputs { "%{file.basename}.c" }
|
||||||
|
buildcommands { "test", "test %{file.basename}" }
|
||||||
|
buildmessage "Some message"
|
||||||
|
prepare()
|
||||||
|
codelite.project.additionalRules(cfg)
|
||||||
|
test.capture [[
|
||||||
|
<AdditionalRules>
|
||||||
|
<CustomPostBuild/>
|
||||||
|
<CustomPreBuild>bar.c foo.c
|
||||||
|
bar.c: bar.txt bar.h extra_dependency
|
||||||
|
@echo Some message
|
||||||
|
test
|
||||||
|
test bar
|
||||||
|
|
||||||
|
foo.c: foo.txt foo.h extra_dependency
|
||||||
|
@echo Some message
|
||||||
|
test
|
||||||
|
test foo
|
||||||
|
</CustomPreBuild>
|
||||||
|
</AdditionalRules>]]
|
||||||
|
end
|
||||||
|
|
@ -203,52 +203,6 @@
|
|||||||
]]
|
]]
|
||||||
end
|
end
|
||||||
|
|
||||||
function suite.OnProjectCfg_BuildCommand()
|
|
||||||
files {"/c/foo.txt", "/c/bar.txt"}
|
|
||||||
buildinputs { "/c/toto.txt", "/c/extra_dependency" }
|
|
||||||
buildoutputs { "/c/toto.c" }
|
|
||||||
buildcommands { "test", "test /c/toto.c" }
|
|
||||||
buildmessage "Some message"
|
|
||||||
prepare()
|
|
||||||
codelite.project.additionalRules(cfg)
|
|
||||||
test.capture [[
|
|
||||||
<AdditionalRules>
|
|
||||||
<CustomPostBuild/>
|
|
||||||
<CustomPreBuild>/c/toto.c
|
|
||||||
/c/toto.c: /c/toto.txt /c/extra_dependency
|
|
||||||
@echo Some message
|
|
||||||
test
|
|
||||||
test /c/toto.c
|
|
||||||
</CustomPreBuild>
|
|
||||||
</AdditionalRules>]]
|
|
||||||
end
|
|
||||||
|
|
||||||
function suite.OnProjectCfg_BuildCommandPerFile()
|
|
||||||
files {"/c/foo.txt", "/c/bar.txt"}
|
|
||||||
filter "files:**.txt"
|
|
||||||
buildinputs { "/c/%{file.basename}.h", "/c/extra_dependency" }
|
|
||||||
buildoutputs { "/c/%{file.basename}.c" }
|
|
||||||
buildcommands { "test", "test /c/%{file.basename}" }
|
|
||||||
buildmessage "Some message"
|
|
||||||
prepare()
|
|
||||||
codelite.project.additionalRules(cfg)
|
|
||||||
test.capture [[
|
|
||||||
<AdditionalRules>
|
|
||||||
<CustomPostBuild/>
|
|
||||||
<CustomPreBuild>/c/bar.c /c/foo.c
|
|
||||||
/c/bar.c: /c/bar.txt /c/bar.h /c/extra_dependency
|
|
||||||
@echo Some message
|
|
||||||
test
|
|
||||||
test /c/bar
|
|
||||||
|
|
||||||
/c/foo.c: /c/foo.txt /c/foo.h /c/extra_dependency
|
|
||||||
@echo Some message
|
|
||||||
test
|
|
||||||
test /c/foo
|
|
||||||
</CustomPreBuild>
|
|
||||||
</AdditionalRules>]]
|
|
||||||
end
|
|
||||||
|
|
||||||
function suite.OnProjectCfg_General()
|
function suite.OnProjectCfg_General()
|
||||||
system "Windows"
|
system "Windows"
|
||||||
prepare()
|
prepare()
|
||||||
@ -386,20 +340,6 @@ cmd2</StartupCommands>
|
|||||||
]]
|
]]
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: test custom build
|
|
||||||
|
|
||||||
|
|
||||||
function suite.OnProjectCfg_AdditionalRules()
|
|
||||||
prepare()
|
|
||||||
codelite.project.additionalRules(prj)
|
|
||||||
test.capture [[
|
|
||||||
<AdditionalRules>
|
|
||||||
<CustomPostBuild/>
|
|
||||||
<CustomPreBuild/>
|
|
||||||
</AdditionalRules>
|
|
||||||
]]
|
|
||||||
end
|
|
||||||
|
|
||||||
function suite.OnProjectCfg_Completion()
|
function suite.OnProjectCfg_Completion()
|
||||||
language "C++"
|
language "C++"
|
||||||
cppdialect "C++11"
|
cppdialect "C++11"
|
||||||
|
@ -171,20 +171,6 @@
|
|||||||
return value
|
return value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function gmake2.path(cfg, value)
|
|
||||||
cfg = cfg.project or cfg
|
|
||||||
local dirs = path.translate(project.getrelative(cfg, value))
|
|
||||||
|
|
||||||
if type(dirs) == 'table' then
|
|
||||||
dirs = table.filterempty(dirs)
|
|
||||||
end
|
|
||||||
|
|
||||||
return dirs
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function gmake2.getToolSet(cfg)
|
function gmake2.getToolSet(cfg)
|
||||||
local default = iif(cfg.system == p.MACOSX, "clang", "gcc")
|
local default = iif(cfg.system == p.MACOSX, "clang", "gcc")
|
||||||
local toolset = p.tools[_OPTIONS.cc or cfg.toolset or default]
|
local toolset = p.tools[_OPTIONS.cc or cfg.toolset or default]
|
||||||
@ -259,71 +245,6 @@
|
|||||||
|
|
||||||
-- convert a rule property into a string
|
-- convert a rule property into a string
|
||||||
|
|
||||||
function gmake2.expandRuleString(rule, prop, value)
|
|
||||||
-- list?
|
|
||||||
if type(value) == "table" then
|
|
||||||
if #value > 0 then
|
|
||||||
if prop.switch then
|
|
||||||
return prop.switch .. table.concat(value, " " .. prop.switch)
|
|
||||||
else
|
|
||||||
prop.separator = prop.separator or " "
|
|
||||||
return table.concat(value, prop.separator)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- bool just emits the switch
|
|
||||||
if prop.switch and type(value) == "boolean" then
|
|
||||||
if value then
|
|
||||||
return prop.switch
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local switch = prop.switch or ""
|
|
||||||
|
|
||||||
-- enum?
|
|
||||||
if prop.values then
|
|
||||||
value = table.findKeyByValue(prop.values, value)
|
|
||||||
if value == nil then
|
|
||||||
value = ""
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- primitive
|
|
||||||
value = tostring(value)
|
|
||||||
if #value > 0 then
|
|
||||||
return switch .. value
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function gmake2.prepareEnvironment(rule, environ, cfg)
|
|
||||||
for _, prop in ipairs(rule.propertydefinition) do
|
|
||||||
local fld = p.rule.getPropertyField(rule, prop)
|
|
||||||
local value = cfg[fld.name]
|
|
||||||
if value ~= nil then
|
|
||||||
|
|
||||||
if fld.kind == "path" then
|
|
||||||
value = gmake2.path(cfg, value)
|
|
||||||
elseif fld.kind == "list:path" then
|
|
||||||
value = gmake2.path(cfg, value)
|
|
||||||
end
|
|
||||||
|
|
||||||
value = gmake2.expandRuleString(rule, prop, value)
|
|
||||||
if value ~= nil and #value > 0 then
|
|
||||||
environ[prop.name] = p.esc(value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
-- Handlers for the individual makefile elements that can be shared
|
-- Handlers for the individual makefile elements that can be shared
|
||||||
|
@ -269,8 +269,8 @@
|
|||||||
local environ = table.shallowcopy(filecfg.environ)
|
local environ = table.shallowcopy(filecfg.environ)
|
||||||
|
|
||||||
if rule.propertydefinition then
|
if rule.propertydefinition then
|
||||||
gmake2.prepareEnvironment(rule, environ, cfg)
|
p.rule.prepareEnvironment(rule, environ, cfg)
|
||||||
gmake2.prepareEnvironment(rule, environ, filecfg)
|
p.rule.prepareEnvironment(rule, environ, filecfg)
|
||||||
end
|
end
|
||||||
|
|
||||||
local shadowContext = p.context.extent(rule, environ)
|
local shadowContext = p.context.extent(rule, environ)
|
||||||
|
@ -175,8 +175,8 @@
|
|||||||
local environ = table.shallowcopy(filecfg.environ)
|
local environ = table.shallowcopy(filecfg.environ)
|
||||||
|
|
||||||
if rule.propertydefinition then
|
if rule.propertydefinition then
|
||||||
gmake2.prepareEnvironment(rule, environ, cfg)
|
p.rule.prepareEnvironment(rule, environ, cfg)
|
||||||
gmake2.prepareEnvironment(rule, environ, filecfg)
|
p.rule.prepareEnvironment(rule, environ, filecfg)
|
||||||
end
|
end
|
||||||
|
|
||||||
local shadowContext = p.context.extent(rule, environ)
|
local shadowContext = p.context.extent(rule, environ)
|
||||||
|
@ -41,15 +41,31 @@
|
|||||||
name = "TestListProperty",
|
name = "TestListProperty",
|
||||||
kind = "list"
|
kind = "list"
|
||||||
}
|
}
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestListPropertyWithSwitch",
|
||||||
|
kind = "list",
|
||||||
|
switch = "-S"
|
||||||
|
}
|
||||||
propertydefinition {
|
propertydefinition {
|
||||||
name = "TestListPropertySeparator",
|
name = "TestListPropertySeparator",
|
||||||
kind = "list",
|
kind = "list",
|
||||||
separator = ","
|
separator = ","
|
||||||
}
|
}
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestListPropertySeparatorWithSwitch",
|
||||||
|
kind = "list",
|
||||||
|
separator = ",",
|
||||||
|
switch = "-O"
|
||||||
|
}
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestEnumProperty",
|
||||||
|
values = { [0] = "V0", [1] = "V1"},
|
||||||
|
switch = { [0] = "S0", [1] = "S1"},
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
|
||||||
buildmessage 'Rule-ing %{file.name}'
|
buildmessage 'Rule-ing %{file.name}'
|
||||||
buildcommands 'dorule %{TestProperty} %{TestProperty2} %{TestListProperty} %{TestListPropertySeparator} "%{file.path}"'
|
buildcommands 'dorule %{TestProperty} %{TestProperty2} %{TestListProperty} %{TestListPropertyWithSwitch} %{TestListPropertySeparator} %{TestListPropertySeparatorWithSwitch} %{TestEnumProperty} "%{file.path}"'
|
||||||
buildoutputs { "%{file.basename}.obj" }
|
buildoutputs { "%{file.basename}.obj" }
|
||||||
|
|
||||||
wks = test.createWorkspace()
|
wks = test.createWorkspace()
|
||||||
@ -292,7 +308,7 @@ test2.obj: test2.rule
|
|||||||
|
|
||||||
rules { "TestRule" }
|
rules { "TestRule" }
|
||||||
|
|
||||||
files { "test.rule", "test2.rule" }
|
files { "test.rule", "test2.rule", "test3.rule", "test4.rule" }
|
||||||
|
|
||||||
filter "files:test.rule"
|
filter "files:test.rule"
|
||||||
testRuleVars {
|
testRuleVars {
|
||||||
@ -300,9 +316,18 @@ test2.obj: test2.rule
|
|||||||
}
|
}
|
||||||
|
|
||||||
filter "files:test2.rule"
|
filter "files:test2.rule"
|
||||||
|
testRuleVars {
|
||||||
|
TestListPropertyWithSwitch = { "testValue1", "testValue2" }
|
||||||
|
}
|
||||||
|
|
||||||
|
filter "files:test3.rule"
|
||||||
testRuleVars {
|
testRuleVars {
|
||||||
TestListPropertySeparator = { "testValue1", "testValue2" }
|
TestListPropertySeparator = { "testValue1", "testValue2" }
|
||||||
}
|
}
|
||||||
|
filter "files:test4.rule"
|
||||||
|
testRuleVars {
|
||||||
|
TestListPropertySeparatorWithSwitch = { "testValue1", "testValue2" }
|
||||||
|
}
|
||||||
|
|
||||||
prepare()
|
prepare()
|
||||||
test.capture [[
|
test.capture [[
|
||||||
@ -314,7 +339,41 @@ test.obj: test.rule
|
|||||||
$(SILENT) dorule testValue1\ testValue2 "test.rule"
|
$(SILENT) dorule testValue1\ testValue2 "test.rule"
|
||||||
test2.obj: test2.rule
|
test2.obj: test2.rule
|
||||||
@echo Rule-ing test2.rule
|
@echo Rule-ing test2.rule
|
||||||
$(SILENT) dorule testValue1,testValue2 "test2.rule"
|
$(SILENT) dorule -StestValue1\ -StestValue2 "test2.rule"
|
||||||
|
test3.obj: test3.rule
|
||||||
|
@echo Rule-ing test3.rule
|
||||||
|
$(SILENT) dorule testValue1,testValue2 "test3.rule"
|
||||||
|
test4.obj: test4.rule
|
||||||
|
@echo Rule-ing test4.rule
|
||||||
|
$(SILENT) dorule -OtestValue1,testValue2 "test4.rule"
|
||||||
]]
|
]]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function suite.customRuleWithPropertyDefinitionEnum()
|
||||||
|
|
||||||
|
rules { "TestRule" }
|
||||||
|
|
||||||
|
files { "test.rule", "test2.rule" }
|
||||||
|
|
||||||
|
testRuleVars {
|
||||||
|
TestEnumProperty = "V0"
|
||||||
|
}
|
||||||
|
|
||||||
|
filter "files:test2.rule"
|
||||||
|
testRuleVars {
|
||||||
|
TestEnumProperty = "V1"
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare()
|
||||||
|
test.capture [[
|
||||||
|
# File Rules
|
||||||
|
# #############################################
|
||||||
|
|
||||||
|
test.obj: test.rule
|
||||||
|
@echo Rule-ing test.rule
|
||||||
|
$(SILENT) dorule S0 "test.rule"
|
||||||
|
test2.obj: test2.rule
|
||||||
|
@echo Rule-ing test2.rule
|
||||||
|
$(SILENT) dorule S1 "test2.rule"
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
@ -136,21 +136,14 @@
|
|||||||
-- @param format
|
-- @param format
|
||||||
-- The formatting to be used, ie "[%s]".
|
-- The formatting to be used, ie "[%s]".
|
||||||
---
|
---
|
||||||
|
function rule.createEnvironment(self, format)
|
||||||
function rule.prepareEnvironment(self, environ, format)
|
local environ = {}
|
||||||
for _, def in ipairs(self.propertydefinition) do
|
for _, def in ipairs(self.propertydefinition) do
|
||||||
environ[def.name] = string.format(format, def.name)
|
environ[def.name] = string.format(format, def.name)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function rule.createEnvironment(self, format)
|
|
||||||
local environ = {}
|
|
||||||
rule.prepareEnvironment(self, environ, format)
|
|
||||||
return environ
|
return environ
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- prepare an table of pathVars with the rule properties as global tokens,
|
-- prepare an table of pathVars with the rule properties as global tokens,
|
||||||
-- according to the format specified.
|
-- according to the format specified.
|
||||||
@ -172,3 +165,78 @@
|
|||||||
rule.preparePathVars(self, pathVars, format)
|
rule.preparePathVars(self, pathVars, format)
|
||||||
return pathVars
|
return pathVars
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function rule.prepareEnvironment(self, environ, cfg)
|
||||||
|
local function path(cfg, value)
|
||||||
|
cfg = cfg.project or cfg
|
||||||
|
local dirs = path.translate(project.getrelative(cfg, value))
|
||||||
|
|
||||||
|
if type(dirs) == 'table' then
|
||||||
|
dirs = table.filterempty(dirs)
|
||||||
|
end
|
||||||
|
|
||||||
|
return dirs
|
||||||
|
end
|
||||||
|
|
||||||
|
local function expandRuleString(prop, value)
|
||||||
|
-- list
|
||||||
|
if type(value) == "table" then
|
||||||
|
if #value > 0 then
|
||||||
|
local switch = prop.switch or ""
|
||||||
|
if prop.separator then
|
||||||
|
return switch .. table.concat(value, prop.separator)
|
||||||
|
else
|
||||||
|
return switch .. table.concat(value, " " .. switch)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- bool just emits the switch
|
||||||
|
if prop.switch and type(value) == "boolean" then
|
||||||
|
if value then
|
||||||
|
return prop.switch
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- enum
|
||||||
|
if prop.values then
|
||||||
|
local switch = prop.switch or {}
|
||||||
|
value = table.findKeyByValue(prop.values, value)
|
||||||
|
if value == nil then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return switch[value]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- primitive
|
||||||
|
local switch = prop.switch or ""
|
||||||
|
value = tostring(value)
|
||||||
|
if #value > 0 then
|
||||||
|
return switch .. value
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, prop in ipairs(self.propertydefinition) do
|
||||||
|
local fld = p.rule.getPropertyField(self, prop)
|
||||||
|
local value = cfg[fld.name]
|
||||||
|
if value ~= nil then
|
||||||
|
|
||||||
|
if fld.kind == "path" then
|
||||||
|
value = path(cfg, value)
|
||||||
|
elseif fld.kind == "list:path" then
|
||||||
|
value = path(cfg, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
value = expandRuleString(prop, value)
|
||||||
|
if value ~= nil and #value > 0 then
|
||||||
|
environ[prop.name] = p.esc(value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@ -16,6 +16,7 @@ return {
|
|||||||
"base/test_premake_command.lua",
|
"base/test_premake_command.lua",
|
||||||
"base/test_table.lua",
|
"base/test_table.lua",
|
||||||
"base/test_tree.lua",
|
"base/test_tree.lua",
|
||||||
|
"base/test_rule.lua",
|
||||||
"base/test_uuid.lua",
|
"base/test_uuid.lua",
|
||||||
"base/test_versions.lua",
|
"base/test_versions.lua",
|
||||||
"base/test_http.lua",
|
"base/test_http.lua",
|
||||||
|
85
tests/base/test_rule.lua
Normal file
85
tests/base/test_rule.lua
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
--
|
||||||
|
-- tests/base/test_rule.lua
|
||||||
|
-- Automated test suite for custom rule.
|
||||||
|
-- Copyright (c) 2008-2021 Jason Perkins and the Premake project
|
||||||
|
--
|
||||||
|
|
||||||
|
local suite = test.declare("rule")
|
||||||
|
|
||||||
|
local p = premake
|
||||||
|
|
||||||
|
function suite.setup()
|
||||||
|
rule "TestRule"
|
||||||
|
display "Test Rule"
|
||||||
|
fileextension ".rule"
|
||||||
|
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestPropertyFalse",
|
||||||
|
kind = "boolean",
|
||||||
|
value = false,
|
||||||
|
switch = "-dummy"
|
||||||
|
}
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestPropertyTrue",
|
||||||
|
kind = "boolean",
|
||||||
|
value = false,
|
||||||
|
switch = "-p"
|
||||||
|
}
|
||||||
|
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestListProperty",
|
||||||
|
kind = "list"
|
||||||
|
}
|
||||||
|
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestListPropertyWithSwitch",
|
||||||
|
kind = "list",
|
||||||
|
switch = "-S"
|
||||||
|
}
|
||||||
|
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestListPropertySeparator",
|
||||||
|
kind = "list",
|
||||||
|
separator = ","
|
||||||
|
}
|
||||||
|
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestListPropertySeparatorWithSwitch",
|
||||||
|
kind = "list",
|
||||||
|
separator = ",",
|
||||||
|
switch = "-O"
|
||||||
|
}
|
||||||
|
|
||||||
|
propertydefinition {
|
||||||
|
name = "TestEnumProperty",
|
||||||
|
values = { [0] = "V0", [1] = "V1"},
|
||||||
|
switch = { [0] = "S0", [1] = "S1"},
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- rule tests
|
||||||
|
--
|
||||||
|
function suite.prepareEnvironment()
|
||||||
|
local rule = premake.global.getRule("TestRule")
|
||||||
|
local environ = {}
|
||||||
|
local cfg = {
|
||||||
|
["_rule_TestRule_TestPropertyFalse"] = false,
|
||||||
|
["_rule_TestRule_TestPropertyTrue"] = true,
|
||||||
|
["_rule_TestRule_TestListProperty"] = {"a", "b"},
|
||||||
|
["_rule_TestRule_TestListPropertyWithSwitch"] = {"c", "d"},
|
||||||
|
["_rule_TestRule_TestListPropertySeparator"] = {"e", "f"},
|
||||||
|
["_rule_TestRule_TestListPropertySeparatorWithSwitch"] = {"1", "2"},
|
||||||
|
["_rule_TestRule_TestEnumProperty"] = 'V1'
|
||||||
|
}
|
||||||
|
p.rule.prepareEnvironment(rule, environ, cfg)
|
||||||
|
|
||||||
|
test.isequal(nil, environ["TestPropertyFalse"])
|
||||||
|
test.isequal("-p", environ["TestPropertyTrue"])
|
||||||
|
test.isequal("a b", environ["TestListProperty"])
|
||||||
|
test.isequal("-Sc -Sd", environ["TestListPropertyWithSwitch"])
|
||||||
|
test.isequal("e,f", environ["TestListPropertySeparator"])
|
||||||
|
test.isequal("-O1,2", environ["TestListPropertySeparatorWithSwitch"])
|
||||||
|
test.isequal("S1", environ["TestEnumProperty"])
|
||||||
|
end
|
@ -47,9 +47,8 @@ For enum properties, a key-value table of the possible values of the property, a
|
|||||||
The value to be placed into the command line for this property. See the examples below for more information.
|
The value to be placed into the command line for this property. See the examples below for more information.
|
||||||
|
|
||||||
#### separator ####
|
#### separator ####
|
||||||
For list properties, this sets the value of the list item separator in the command line.\
|
For list properties, this sets the value of the list item separator in the command line.
|
||||||
gmake2: Default value is ' '. If a switch is set, the separator is ignored and instead the switch is duplicated.\
|
If set, the list is concatenated by the separator and placed behind a single switch. If not set, the switch is duplicated.
|
||||||
VS201x: If set, the list is concatenated by the separator and placed behind a single switch. If not set, the switch is duplicated.
|
|
||||||
|
|
||||||
#### category ####
|
#### category ####
|
||||||
Visual Studio only.
|
Visual Studio only.
|
||||||
|
Loading…
Reference in New Issue
Block a user