--
-- vs2005_csproj.lua
-- Generate a Visual Studio 2005-2010 C# project.
-- Copyright (c) 2009-2013 Jason Perkins and the Premake project
--
premake.vstudio.cs2005 = {}
local vstudio = premake.vstudio
local cs2005 = premake.vstudio.cs2005
local project = premake5.project
local config = premake5.config
local dotnet = premake.tools.dotnet
--
-- Generate a Visual Studio 200x C# project, with support for the new platforms API.
--
function cs2005.generate_ng(prj)
io.eol = "\r\n"
io.indent = " "
cs2005.projectelement(prj)
cs2005.projectsettings(prj)
for cfg in project.eachconfig(prj) do
cs2005.propertyGroup(cfg)
cs2005.debugProps(cfg)
cs2005.outputProps(cfg)
cs2005.compilerProps(cfg)
_p(1,'')
end
cs2005.applicationIcon(prj)
cs2005.assemblyReferences(prj)
_p(1,'')
cs2005.files(prj)
_p(1,'')
cs2005.projectReferences(prj)
_p(' ')
_p(' ')
cs2005.buildEvents(prj)
_p('')
end
--
-- Write the opening element.
--
function cs2005.projectelement(prj)
local toolversion = {
vs2005 = '',
vs2008 = ' ToolsVersion="3.5"',
vs2010 = ' ToolsVersion="4.0"',
vs2012 = ' ToolsVersion="4.0"',
}
if _ACTION > "vs2008" then
_p('')
end
_p('', toolversion[_ACTION])
end
--
-- Write the opening PropertyGroup, which contains the project-level settings.
--
function cs2005.projectsettings(prj)
local version = {
vs2005 = '8.0.50727',
vs2008 = '9.0.21022',
vs2010 = '8.0.30703',
vs2012 = '8.0.30703',
}
local frameworks = {
vs2010 = "4.0",
vs2012 = "4.5",
}
_p(1,'')
-- find the first configuration in the project, use as the default
local cfg = project.getfirstconfig(prj)
_p(2,'%s', premake.esc(cfg.buildcfg))
_p(2,'%s', cs2005.arch(prj))
_p(2,'%s', version[_ACTION])
_p(2,'2.0')
_p(2,'{%s}', prj.uuid)
_p(2,'%s', dotnet.getkind(cfg))
_p(2,'Properties')
local target = cfg.buildtarget
_p(2,'%s', prj.namespace or target.basename)
_p(2,'%s', target.basename)
local framework = prj.framework or frameworks[_ACTION]
if framework then
_p(2,'v%s', framework)
end
if _ACTION >= "vs2010" then
_p(2,'')
_p(2,'512')
end
_p(1,'')
end
--
-- Write out the source files item group.
--
function cs2005.files(prj)
local tr = project.getsourcetree(prj)
premake.tree.traverse(tr, {
onleaf = function(node, depth)
-- Some settings applied at project level; can't be changed in cfg
local cfg = project.getfirstconfig(prj)
local filecfg = config.getfileconfig(cfg, node.abspath)
local action = dotnet.getbuildaction(filecfg)
local fname = path.translate(node.relpath)
local elements, dependency = cs2005.getrelated(prj, filecfg, action)
if elements == "None" then
_p(2,'<%s Include="%s" />', action, fname)
else
_p(2,'<%s Include="%s">', action, fname)
if elements == "AutoGen" then
_p(3,'True')
elseif elements == "AutoGenerated" then
_p(3,'Designer')
_p(3,'ResXFileCodeGenerator')
_x(3,'%s.Designer.cs', path.getbasename(node.name))
elseif elements == "PreserveNewest" then
_p(3,'PreserveNewest')
elseif elements then
_p(3,'%s', elements)
end
if dependency then
dependency = project.getrelative(prj, dependency)
_x(3,'%s', path.translate(dependency))
end
_p(2,'%s>', action)
end
end
}, false)
end
--
-- Write out pre- and post-build events, if provided.
--
function cs2005.buildEvents(prj)
local function output(name, steps)
if #steps > 0 then
_x(2,'<%sBuildEvent>%s%sBuildEvent>', name, table.implode(steps, "", "", "\r\n"), name)
end
end
if #prj.prebuildcommands > 0 or #prj.postbuildcommands > 0 then
_p(1,'')
output("Pre", prj.prebuildcommands)
output("Post", prj.postbuildcommands)
_p(1,'')
end
end
--
-- Write the compiler flags for a particular configuration.
--
function cs2005.compilerProps(cfg)
_x(2,'%s', table.concat(cfg.defines, ";"))
_p(2,'prompt')
_p(2,'4')
if cfg.flags.Unsafe then
_p(2,'true')
end
if cfg.flags.FatalWarnings then
_p(2,'true')
end
end
--
-- Write out the debugging and optimization flags for a configuration.
--
function cs2005.debugProps(cfg)
if cfg.flags.Symbols then
_p(2,'true')
_p(2,'full')
else
_p(2,'pdbonly')
end
_p(2,'%s', iif(premake.config.isoptimizedbuild(cfg), "true", "false"))
end
--
-- Write out the target and intermediates settings for a configuration.
--
function cs2005.outputProps(cfg)
local outdir = project.getrelative(cfg.project, cfg.buildtarget.directory)
_x(2,'%s\\', path.translate(outdir))
-- Want to set BaseIntermediateOutputPath because otherwise VS will create obj/
-- anyway. But VS2008 throws up ominous warning if present.
local objdir = path.translate(project.getrelative(cfg.project, cfg.objdir))
if _ACTION > "vs2008" then
_x(2,'%s\\', objdir)
_p(2,'$(BaseIntermediateOutputPath)')
else
_x(2,'%s\\', objdir)
end
end
--
-- Given a source file name, look for related elements and files. Pairs up
-- designer and resource files with their corresponding source files, and
-- vice versa.
--
-- @param prj
-- The current project, which contains the source file lists.
-- @param filecfg
-- The configuration of the file being generated.
-- @param action
-- The build action for the file under consideration.
--
function cs2005.getrelated(prj, filecfg, action)
local fname = filecfg.abspath
if action == "Compile" and fname:endswith(".cs") then
if fname:endswith(".Designer.cs") then
local basename = fname:sub(1, -13)
-- is there a matching *.cs file?
local testname = basename .. ".cs"
if project.hasfile(prj, testname) then
return "Dependency", testname
end
-- is there a matching *.resx file
testname = basename .. ".resx"
if project.hasfile(prj, testname) then
return "AutoGen", testname
end
else
-- is there a matching *.Designer.cs?
local basename = fname:sub(1, -4)
testname = basename .. ".Designer.cs"
if project.hasfile(prj, testname) then
return "Form"
end
if filecfg.flags and filecfg.flags.Component then
return "Component"
end
end
end
if action == "EmbeddedResource" and fname:endswith(".resx") then
local basename = fname:sub(1, -6)
-- is there a matching *.cs file?
local testname = basename .. ".cs"
if project.hasfile(prj, testname) then
if project.hasfile(prj, basename .. ".Designer.cs") then
return "DesignerType", testname
else
return "Dependency", testname
end
else
-- is there a matching *.Designer.cs?
testname = basename .. ".Designer.cs"
if project.hasfile(prj, testname) then
return "AutoGenerated"
end
end
end
if action == "Content" then
return "PreserveNewest"
end
return "None"
end
--
-- Write the list of assembly (system, or non-sibling) references.
--
function cs2005.assemblyReferences(prj)
_p(1,'')
-- C# doesn't support per-configuration links (does it?) so just use
-- the settings from the first available config instead
local links = config.getlinks(project.getfirstconfig(prj), "system", "fullpath")
for _, link in ipairs(links) do
if link:find("/", nil, true) then
_x(2,'', path.getbasename(link))
_x(3,'%s', path.translate(link))
_p(2,'')
else
_x(2,'', path.getbasename(link))
end
end
_p(1,'')
end
--
-- Write the list of project dependencies.
--
function cs2005.projectReferences(prj)
_p(1,'')
local deps = project.getdependencies(prj)
if #deps > 0 then
local prjpath = project.getlocation(prj)
for _, dep in ipairs(deps) do
local relpath = path.getrelative(prjpath, vstudio.projectfile(dep))
_x(2,'', path.translate(relpath))
_p(3,'{%s}', dep.uuid)
_x(3,'%s', dep.name)
_p(2,'')
end
end
_p(1,'')
end
--
-- Return the Visual Studio architecture identification string. The logic
-- to select this is getting more complicated in VS2010, but I haven't
-- tackled all the permutations yet.
--
function cs2005.arch(cfg)
local arch = vstudio.archFromConfig(cfg)
if arch == "Any CPU" then
arch = "AnyCPU"
end
return arch
end
--
-- Write the PropertyGroup element for a specific configuration block.
--
function cs2005.propertyGroup(cfg)
local arch = cs2005.arch(cfg)
_x(1,'', cfg.buildcfg, arch)
if arch ~= "AnyCPU" or _ACTION > "vs2008" then
_x(2,'%s', arch)
end
end
--
-- Generators for individual project elements.
--
function cs2005.applicationIcon(prj)
if prj.icon then
local icon = path.translate(project.getrelative(prj, prj.icon))
_p(1,'')
_x(2,'%s', icon)
_p(1,'')
end
end