Add custom rules to VC 2010 filters

This commit is contained in:
Jason Perkins 2014-06-12 16:14:42 -04:00
parent d7c7c9373d
commit 07a4ad897d
4 changed files with 209 additions and 178 deletions

View File

@ -703,7 +703,13 @@
function m.categorizeSources(prj)
local groups = {}
local groups = prj._vc2010_sources
if groups then
return groups
end
groups = {}
prj._vc2010_sources = groups
local tr = project.getsourcetree(prj)
tree.traverse(tr, {
@ -726,72 +732,6 @@
function m.getfilegroup(prj, group)
-- Have I already created the groups?
local groups = prj._vc2010_file_groups
if groups then
return groups[group]
end
groups = {
ClCompile = {},
ClInclude = {},
None = {},
ResourceCompile = {},
CustomBuild = {},
CustomRule = {},
}
local tr = project.getsourcetree(prj)
tree.traverse(tr, {
onleaf = function(node)
-- if any configuration of this file uses a custom build rule,
-- then they all must be marked as custom build
local customBuild, customRule
for cfg in project.eachconfig(prj) do
local fcfg = fileconfig.getconfig(node, cfg)
if fileconfig.hasCustomBuildRule(fcfg) then
customBuild = true
break
elseif fcfg and fcfg.customRule then
customRule = fcfg.customRule
break
end
end
if customBuild then
table.insert(groups.CustomBuild, node)
elseif customRule then
groups.CustomRule[customRule] = groups.CustomRule[customRule] or {}
table.insert(groups.CustomRule[customRule], node)
elseif path.iscppfile(node.name) then
table.insert(groups.ClCompile, node)
elseif path.iscppheader(node.name) then
table.insert(groups.ClInclude, node)
elseif path.isresourcefile(node.name) then
table.insert(groups.ResourceCompile, node)
else
table.insert(groups.None, node)
end
end
})
-- sort by relative to path; otherwise VS will reorder the files
for group, files in pairs(groups) do
table.sort(files, function (a, b)
return a.relpath < b.relpath
end)
end
prj._vc2010_file_groups = groups
return groups[group]
end
--
-- Generate the list of project dependencies.
--

View File

@ -5,55 +5,76 @@
--
local p = premake
local vc2010 = p.vstudio.vc2010
local project = p.project
local tree = p.tree
local m = p.vstudio.vc2010
--
-- Generate a Visual Studio 201x C++ project, with support for the new platforms API.
--
function vc2010.generateFilters(prj)
vc2010.xmlDeclaration()
vc2010.project()
vc2010.filters_uniqueidentifiers(prj)
vc2010.filters_filegroup(prj, "None")
vc2010.filters_filegroup(prj, "ClInclude")
vc2010.filters_filegroup(prj, "ClCompile")
vc2010.filters_filegroup(prj, "ResourceCompile")
vc2010.filters_filegroup(prj, "CustomBuild")
function m.generateFilters(prj)
m.xmlDeclaration()
m.project()
m.uniqueIdentifiers(prj)
m.filterGroups(prj)
p.out('</Project>')
end
m.elements.filterGroups = {
"None",
"ClInclude",
"ClCompile",
"ResourceCompile",
"CustomBuild",
"CustomRule"
}
m.elements.filters = function(prj, groups)
local calls = {}
for i, group in ipairs(m.elements.filterGroups) do
calls[i] = m[group .. "Filters"]
end
return calls
end
function m.filterGroups(prj)
-- Categorize the source files in groups by build rule; each will
-- be written to a separate item group by one of the handlers
local groups = m.categorizeSources(prj)
p.callArray(m.elements.filters, prj, groups)
end
--
-- The first portion of the filters file assigns unique IDs to each
-- directory or virtual group. Would be cool if we could automatically
-- map vpaths like "**.h" to an <Extensions>h</Extensions> element.
--
function vc2010.filters_uniqueidentifiers(prj)
local opened = false
function m.uniqueIdentifiers(prj)
local tr = project.getsourcetree(prj)
tree.traverse(tr, {
onbranch = function(node, depth)
if not opened then
_p(1,'<ItemGroup>')
opened = true
local contents = p.capture(function()
p.push()
tree.traverse(tr, {
onbranch = function(node, depth)
p.push('<Filter Include="%s">', path.translate(node.path))
p.w('<UniqueIdentifier>{%s}</UniqueIdentifier>', os.uuid(node.path))
p.pop('</Filter>')
end
}, false)
p.pop()
end)
_x(2, '<Filter Include="%s">', path.translate(node.path))
_p(3, '<UniqueIdentifier>{%s}</UniqueIdentifier>', os.uuid(node.path))
_p(2, '</Filter>')
end
}, false)
if opened then
_p(1,'</ItemGroup>')
if #contents > 0 then
p.push('<ItemGroup>')
p.out(contents)
p.pop('</ItemGroup>')
end
end
@ -64,20 +85,48 @@
-- "ResourceCompile", or "None".
--
function vc2010.filters_filegroup(prj, group)
local files = vc2010.getfilegroup(prj, group)
if #files > 0 then
_p(1,'<ItemGroup>')
for _, file in ipairs(files) do
if file.parent.path then
_p(2,'<%s Include=\"%s\">', group, path.translate(file.relpath))
_p(3,'<Filter>%s</Filter>', path.translate(file.parent.path))
_p(2,'</%s>', group)
else
_p(2,'<%s Include=\"%s\" />', group, path.translate(file.relpath))
end
function m.ClCompileFilters(prj, groups)
m.filterGroup(prj, groups, "ClCompile")
end
function m.ClIncludeFilters(prj, groups)
m.filterGroup(prj, groups, "ClInclude")
end
function m.CustomBuildFilters(prj, groups)
m.filterGroup(prj, groups, "CustomBuild")
end
function m.CustomRuleFilters(prj, groups)
for group, files in pairs(groups) do
if not table.contains(m.elements.filterGroups, group) then
m.filterGroup(prj, groups, group)
end
_p(1,'</ItemGroup>')
end
end
function m.NoneFilters(prj, groups)
m.filterGroup(prj, groups, "None")
end
function m.ResourceCompileFilters(prj, groups)
m.filterGroup(prj, groups, "ResourceCompile")
end
function m.filterGroup(prj, groups, group)
local files = groups[group] or {}
if #files > 0 then
p.push('<ItemGroup>')
for _, file in ipairs(files) do
if file.parent.path then
p.push('<%s Include=\"%s\">', group, path.translate(file.relpath))
p.w('<Filter>%s</Filter>', path.translate(file.parent.path))
p.pop('</%s>', group)
else
p.w('<%s Include=\"%s\" />', group, path.translate(file.relpath))
end
end
p.pop('</ItemGroup>')
end
end

View File

@ -20,8 +20,8 @@
end
local function prepare()
prj = premake.solution.getproject(sln, 1)
vc2010.filters_uniqueidentifiers(prj)
prj = test.getproject(sln)
vc2010.uniqueIdentifiers(prj)
end
@ -44,11 +44,11 @@
files { "src/hello.c", "src/goodbye.c", "so_long.h" }
prepare()
test.capture [[
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{2DAB880B-99B4-887C-2230-9F7C8E38947C}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{2DAB880B-99B4-887C-2230-9F7C8E38947C}</UniqueIdentifier>
</Filter>
</ItemGroup>
]]
end
@ -61,14 +61,14 @@
files { "src/hello.c", "src/departures/goodbye.c", "so_long.h" }
prepare()
test.capture [[
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{2DAB880B-99B4-887C-2230-9F7C8E38947C}</UniqueIdentifier>
</Filter>
<Filter Include="src\departures">
<UniqueIdentifier>{BB36ED8F-A704-E195-9098-51BC7C05BDFA}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{2DAB880B-99B4-887C-2230-9F7C8E38947C}</UniqueIdentifier>
</Filter>
<Filter Include="src\departures">
<UniqueIdentifier>{BB36ED8F-A704-E195-9098-51BC7C05BDFA}</UniqueIdentifier>
</Filter>
</ItemGroup>
]]
end
@ -82,11 +82,11 @@
vpaths { ["Source Files"] = "**.c" }
prepare()
test.capture [[
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{E9C7FDCE-D52A-8D73-7EB0-C5296AF258F6}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{E9C7FDCE-D52A-8D73-7EB0-C5296AF258F6}</UniqueIdentifier>
</Filter>
</ItemGroup>
]]
end
@ -95,13 +95,13 @@
vpaths { ["Source Files"] = "*.c", ["Header Files"] = "*.h" }
prepare()
test.capture [[
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{21EB8090-0D4E-1035-B6D3-48EBA215DCB7}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{E9C7FDCE-D52A-8D73-7EB0-C5296AF258F6}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{21EB8090-0D4E-1035-B6D3-48EBA215DCB7}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{E9C7FDCE-D52A-8D73-7EB0-C5296AF258F6}</UniqueIdentifier>
</Filter>
</ItemGroup>
]]
end

View File

@ -20,8 +20,8 @@
end
local function prepare(group)
prj = premake.solution.getproject(sln, 1)
vc2010.filters_filegroup(prj, group)
prj = test.getproject(sln)
vc2010.filterGroups(prj)
end
@ -30,32 +30,51 @@
--
function suite.itemGroup_onClInclude()
files { "hello.c", "hello.h", "hello.rc", "hello.txt" }
prepare("ClInclude")
files { "hello.h" }
prepare()
test.capture [[
<ItemGroup>
<ClInclude Include="hello.h" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="hello.h" />
</ItemGroup>
]]
end
function suite.itemGroup_onResourceSection()
files { "hello.c", "hello.h", "hello.rc", "hello.txt" }
prepare("ResourceCompile")
files { "hello.rc" }
prepare()
test.capture [[
<ItemGroup>
<ResourceCompile Include="hello.rc" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="hello.rc" />
</ItemGroup>
]]
end
function suite.itemGroup_onNoneSection()
files { "hello.c", "hello.h", "hello.rc", "hello.txt" }
prepare("None")
files { "hello.txt" }
prepare()
test.capture [[
<ItemGroup>
<None Include="hello.txt" />
</ItemGroup>
<ItemGroup>
<None Include="hello.txt" />
</ItemGroup>
]]
end
function suite.itemGroup_onMixed()
files { "hello.c", "hello.h", "hello.rc", "hello.txt" }
prepare()
test.capture [[
<ItemGroup>
<None Include="hello.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="hello.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="hello.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="hello.rc" />
</ItemGroup>
]]
end
@ -65,28 +84,28 @@
--
function suite.itemGroup_onBuildRule()
files { "hello.c", "hello.h", "hello.rc", "hello.cg" }
files { "hello.cg" }
filter "files:**.cg"
buildcommands { "cgc $(InputFile)" }
buildoutputs { "$(InputName).obj" }
prepare("CustomBuild")
test.capture [[
<ItemGroup>
<CustomBuild Include="hello.cg" />
</ItemGroup>
<ItemGroup>
<CustomBuild Include="hello.cg" />
</ItemGroup>
]]
end
function suite.itemGroup_onSingleConfigBuildRule()
files { "hello.c", "hello.h", "hello.rc", "hello.cg" }
files { "hello.cg" }
filter { "Release", "files:**.cg" }
buildcommands { "cgc $(InputFile)" }
buildoutputs { "$(InputName).obj" }
prepare("CustomBuild")
test.capture [[
<ItemGroup>
<CustomBuild Include="hello.cg" />
</ItemGroup>
<ItemGroup>
<CustomBuild Include="hello.cg" />
</ItemGroup>
]]
end
@ -98,12 +117,12 @@
function suite.noFilter_onRootFiles()
files { "hello.c", "goodbye.c" }
prepare("ClCompile")
prepare()
test.capture [[
<ItemGroup>
<ClCompile Include="goodbye.c" />
<ClCompile Include="hello.c" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="goodbye.c" />
<ClCompile Include="hello.c" />
</ItemGroup>
]]
end
@ -113,13 +132,16 @@
function suite.filter_onRealPath()
files { "src/hello.c", "hello.h" }
prepare("ClCompile")
prepare()
test.capture [[
<ItemGroup>
<ClCompile Include="src\hello.c">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="hello.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\hello.c">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
]]
end
@ -130,12 +152,32 @@
function suite.filter_onVpath()
files { "src/hello.c", "hello.h" }
vpaths { ["Source Files"] = "**.c" }
prepare("ClCompile")
prepare()
test.capture [[
<ItemGroup>
<ClCompile Include="src\hello.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="hello.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\hello.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
]]
end
--
-- Check handling of files using custom rules.
--
function suite.filter_onCustomRule()
files { "hello.dae" }
filter "files:**.dae"
customRule "Animation"
prepare()
test.capture [[
<ItemGroup>
<Animation Include="hello.dae" />
</ItemGroup>
]]
end