427 lines
11 KiB
Lua
427 lines
11 KiB
Lua
--
|
|
-- 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 = premake.project
|
|
local config = premake.config
|
|
local fileconfig = premake.fileconfig
|
|
local dotnet = premake.tools.dotnet
|
|
|
|
|
|
cs2005.elements = {}
|
|
|
|
|
|
--
|
|
-- Generate a Visual Studio 200x C# project, with support for the new platforms API.
|
|
--
|
|
|
|
cs2005.elements.project = {
|
|
"projectElement",
|
|
"projectProperties",
|
|
}
|
|
|
|
function cs2005.generate(prj)
|
|
io.indent = " "
|
|
io.utf8()
|
|
|
|
premake.callarray(cs2005, cs2005.elements.project, prj)
|
|
|
|
for cfg in project.eachconfig(prj) do
|
|
cs2005.configurationProperties(cfg)
|
|
end
|
|
|
|
cs2005.applicationIcon(prj)
|
|
cs2005.assemblyReferences(prj)
|
|
|
|
_p(1,'<ItemGroup>')
|
|
cs2005.files(prj)
|
|
_p(1,'</ItemGroup>')
|
|
|
|
cs2005.projectReferences(prj)
|
|
cs2005.targets(prj)
|
|
cs2005.buildEvents(prj)
|
|
|
|
io.printf('</Project>')
|
|
end
|
|
|
|
|
|
--
|
|
-- Write the opening <Project> element.
|
|
--
|
|
|
|
function cs2005.projectElement(prj)
|
|
if _ACTION > "vs2008" then
|
|
_p('<?xml version="1.0" encoding="utf-8"?>')
|
|
end
|
|
|
|
local ver = ''
|
|
local action = premake.action.current()
|
|
if action.vstudio.toolsVersion then
|
|
ver = string.format(' ToolsVersion="%s"', action.vstudio.toolsVersion)
|
|
end
|
|
_p('<Project%s DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">', ver)
|
|
end
|
|
|
|
|
|
--
|
|
-- Write the opening PropertyGroup, which contains the project-level settings.
|
|
--
|
|
|
|
function cs2005.projectProperties(prj)
|
|
|
|
_p(1,'<PropertyGroup>')
|
|
|
|
-- find the first configuration in the project, use as the default
|
|
local cfg = project.getfirstconfig(prj)
|
|
|
|
_p(2,'<Configuration Condition=" \'$(Configuration)\' == \'\' ">%s</Configuration>', premake.esc(cfg.buildcfg))
|
|
_p(2,'<Platform Condition=" \'$(Platform)\' == \'\' ">%s</Platform>', cs2005.arch(prj))
|
|
|
|
cs2005.productVersion(prj)
|
|
cs2005.schemaVersion(prj)
|
|
|
|
_p(2,'<ProjectGuid>{%s}</ProjectGuid>', prj.uuid)
|
|
|
|
_p(2,'<OutputType>%s</OutputType>', dotnet.getkind(cfg))
|
|
_p(2,'<AppDesignerFolder>Properties</AppDesignerFolder>')
|
|
|
|
local target = cfg.buildtarget
|
|
_p(2,'<RootNamespace>%s</RootNamespace>', prj.namespace or target.basename)
|
|
_p(2,'<AssemblyName>%s</AssemblyName>', target.basename)
|
|
|
|
cs2005.targetFrameworkVersion(prj)
|
|
cs2005.targetFrameworkProfile(prj)
|
|
cs2005.fileAlignment(prj)
|
|
|
|
_p(1,'</PropertyGroup>')
|
|
end
|
|
|
|
|
|
--
|
|
-- Write out the settings for an individual configuration.
|
|
--
|
|
|
|
function cs2005.configurationProperties(cfg)
|
|
cs2005.propertyGroup(cfg)
|
|
cs2005.debugProps(cfg)
|
|
cs2005.outputProps(cfg)
|
|
cs2005.compilerProps(cfg)
|
|
_p(1,'</PropertyGroup>')
|
|
end
|
|
|
|
|
|
--
|
|
-- Write out the source files item group.
|
|
--
|
|
|
|
function cs2005.files(prj)
|
|
-- Some settings applied at project level; can't be changed in cfg
|
|
local cfg = project.getfirstconfig(prj)
|
|
|
|
local tr = project.getsourcetree(prj)
|
|
premake.tree.traverse(tr, {
|
|
onleaf = function(node, depth)
|
|
local filecfg = fileconfig.getconfig(node, cfg)
|
|
local fname = path.translate(node.relpath)
|
|
|
|
-- Files that live outside of the project tree need to be "linked"
|
|
-- and provided with a project relative pseudo-path. Check for any
|
|
-- leading "../" sequences and, if found, remove them and mark this
|
|
-- path as external.
|
|
|
|
local link, count = node.relpath:gsub("%.%.%/", "")
|
|
local external = (count > 0)
|
|
|
|
-- Try to provide a little bit of flexibility by allowing virtual
|
|
-- paths for external files. Would be great to support them for all
|
|
-- files but Visual Studio chokes if file is already in project area.
|
|
|
|
if external and node.vpath ~= node.relpath then
|
|
link = node.vpath
|
|
end
|
|
|
|
-- Deduce what, if any, special attributes are required for this file.
|
|
-- For example, forms may have related source, designer, and resource
|
|
-- files which need to be associated.
|
|
|
|
local info = dotnet.fileinfo(filecfg)
|
|
|
|
-- If no additional attributes are required, write a simple element
|
|
|
|
if not info.subtype and not info.dependency and not external then
|
|
_p(2,'<%s Include="%s" />', info.action, fname)
|
|
|
|
else
|
|
_p(2,'<%s Include="%s">', info.action, fname)
|
|
|
|
if external then
|
|
_p(3,'<Link>%s</Link>', path.translate(link))
|
|
end
|
|
|
|
if info.subtype == "AutoGenerated" then
|
|
_p(3,"<AutoGen>True</AutoGen>")
|
|
|
|
elseif info.subtype == "Designer" then
|
|
_p(3,'<SubType>Designer</SubType>')
|
|
_p(3,'<Generator>ResXFileCodeGenerator</Generator>')
|
|
_x(3,'<LastGenOutput>%s.Designer.cs</LastGenOutput>', path.getbasename(node.name))
|
|
|
|
elseif info.subtype == "PreserveNewest" then
|
|
_p(3,'<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>')
|
|
|
|
elseif info.subtype then
|
|
_p(3,'<SubType>%s</SubType>', info.subtype)
|
|
|
|
end
|
|
|
|
if info.dependency then
|
|
local dependency = path.translate(project.getrelative(prj, info.dependency))
|
|
_x(3,'<DependentUpon>%s</DependentUpon>', dependency)
|
|
end
|
|
|
|
_p(2,'</%s>', info.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,'<PropertyGroup>')
|
|
output("Pre", prj.prebuildcommands)
|
|
output("Post", prj.postbuildcommands)
|
|
_p(1,'</PropertyGroup>')
|
|
end
|
|
end
|
|
|
|
|
|
--
|
|
-- Write the compiler flags for a particular configuration.
|
|
--
|
|
|
|
function cs2005.compilerProps(cfg)
|
|
_x(2,'<DefineConstants>%s</DefineConstants>', table.concat(cfg.defines, ";"))
|
|
|
|
_p(2,'<ErrorReport>prompt</ErrorReport>')
|
|
_p(2,'<WarningLevel>4</WarningLevel>')
|
|
|
|
if cfg.flags.Unsafe then
|
|
_p(2,'<AllowUnsafeBlocks>true</AllowUnsafeBlocks>')
|
|
end
|
|
|
|
if cfg.flags.FatalWarnings then
|
|
_p(2,'<TreatWarningsAsErrors>true</TreatWarningsAsErrors>')
|
|
end
|
|
end
|
|
|
|
|
|
--
|
|
-- Write out the debugging and optimization flags for a configuration.
|
|
--
|
|
|
|
function cs2005.debugProps(cfg)
|
|
if cfg.flags.Symbols then
|
|
_p(2,'<DebugSymbols>true</DebugSymbols>')
|
|
_p(2,'<DebugType>full</DebugType>')
|
|
else
|
|
_p(2,'<DebugType>pdbonly</DebugType>')
|
|
end
|
|
_p(2,'<Optimize>%s</Optimize>', iif(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,'<OutputPath>%s\\</OutputPath>', 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,'<BaseIntermediateOutputPath>%s\\</BaseIntermediateOutputPath>', objdir)
|
|
_p(2,'<IntermediateOutputPath>$(BaseIntermediateOutputPath)</IntermediateOutputPath>')
|
|
else
|
|
_x(2,'<IntermediateOutputPath>%s\\</IntermediateOutputPath>', objdir)
|
|
end
|
|
end
|
|
|
|
|
|
--
|
|
-- Write the list of assembly (system, or non-sibling) references.
|
|
--
|
|
|
|
function cs2005.assemblyReferences(prj)
|
|
_p(1,'<ItemGroup>')
|
|
|
|
-- C# doesn't support per-configuration links (does it?) so just use
|
|
-- the settings from the first available config instead
|
|
local cfg = project.getfirstconfig(prj)
|
|
|
|
config.getlinks(cfg, "system", function(original, decorated)
|
|
if decorated:find("/", nil, true) then
|
|
_x(2,'<Reference Include="%s">', path.getbasename(decorated))
|
|
_x(3,'<HintPath>%s</HintPath>', path.translate(decorated))
|
|
|
|
if not config.isCopyLocal(prj, original, true) then
|
|
_p(3,"<Private>False</Private>")
|
|
end
|
|
|
|
_p(2,'</Reference>')
|
|
else
|
|
_x(2,'<Reference Include="%s" />', path.getbasename(decorated))
|
|
end
|
|
end)
|
|
|
|
_p(1,'</ItemGroup>')
|
|
end
|
|
|
|
|
|
--
|
|
-- Write the list of project dependencies.
|
|
--
|
|
function cs2005.projectReferences(prj)
|
|
_p(1,'<ItemGroup>')
|
|
|
|
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,'<ProjectReference Include="%s">', path.translate(relpath))
|
|
_p(3,'<Project>{%s}</Project>', dep.uuid)
|
|
_x(3,'<Name>%s</Name>', dep.name)
|
|
|
|
if not config.isCopyLocal(prj, dep.name, true) then
|
|
_p(3,"<Private>False</Private>")
|
|
end
|
|
|
|
_p(2,'</ProjectReference>')
|
|
end
|
|
end
|
|
|
|
_p(1,'</ItemGroup>')
|
|
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,'<PropertyGroup Condition=" \'$(Configuration)|$(Platform)\' == \'%s|%s\' ">', cfg.buildcfg, arch)
|
|
if arch ~= "AnyCPU" or _ACTION > "vs2008" then
|
|
_x(2,'<PlatformTarget>%s</PlatformTarget>', 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,'<PropertyGroup>')
|
|
_x(2,'<ApplicationIcon>%s</ApplicationIcon>', icon)
|
|
_p(1,'</PropertyGroup>')
|
|
end
|
|
end
|
|
|
|
|
|
---------------------------------------------------------------------------
|
|
--
|
|
-- Handlers for individual project elements
|
|
--
|
|
---------------------------------------------------------------------------
|
|
|
|
function cs2005.fileAlignment(prj)
|
|
if _ACTION >= "vs2010" then
|
|
_p(2,'<FileAlignment>512</FileAlignment>')
|
|
end
|
|
end
|
|
|
|
|
|
function cs2005.productVersion(prj)
|
|
local action = premake.action.current()
|
|
if action.vstudio.productVersion then
|
|
_p(2,'<ProductVersion>%s</ProductVersion>', action.vstudio.productVersion)
|
|
end
|
|
end
|
|
|
|
|
|
function cs2005.schemaVersion(prj)
|
|
local action = premake.action.current()
|
|
if action.vstudio.csprojSchemaVersion then
|
|
_p(2,'<SchemaVersion>%s</SchemaVersion>', action.vstudio.csprojSchemaVersion)
|
|
end
|
|
end
|
|
|
|
|
|
function cs2005.targetFrameworkVersion(prj)
|
|
local action = premake.action.current()
|
|
local framework = prj.framework or action.vstudio.targetFramework
|
|
if framework then
|
|
_p(2,'<TargetFrameworkVersion>v%s</TargetFrameworkVersion>', framework)
|
|
end
|
|
end
|
|
|
|
|
|
function cs2005.targetFrameworkProfile(prj)
|
|
if _ACTION == "vs2010" then
|
|
_p(2,'<TargetFrameworkProfile>')
|
|
_p(2,'</TargetFrameworkProfile>')
|
|
end
|
|
end
|
|
|
|
|
|
function cs2005.targets(prj)
|
|
local bin = iif(_ACTION <= "vs2010", "MSBuildBinPath", "MSBuildToolsPath")
|
|
_p(1,'<Import Project="$(%s)\\Microsoft.CSharp.targets" />', bin)
|
|
_p(1,'<!-- To modify your build process, add your task inside one of the targets below and uncomment it.')
|
|
_p(1,' Other similar extension points exist, see Microsoft.Common.targets.')
|
|
_p(1,'<Target Name="BeforeBuild">')
|
|
_p(1,'</Target>')
|
|
_p(1,'<Target Name="AfterBuild">')
|
|
_p(1,'</Target>')
|
|
_p(1,'-->')
|
|
end
|