premake/src/actions/vstudio/vs200x_vcproj.lua

1611 lines
42 KiB
Lua

--
-- vs200x_vcproj.lua
-- Generate a Visual Studio 2002-2008 C/C++ project.
-- Copyright (c) 2009-2012 Jason Perkins and the Premake project
--
premake.vstudio.vc200x = { }
local vstudio = premake.vstudio
local vc200x = premake.vstudio.vc200x
local config = premake5.config
local project = premake5.project
local tree = premake.tree
--
-- Generate a Visual Studio 200x C++ project, with support for the new platforms API.
--
function vc200x.generate_ng(prj)
io.eol = "\r\n"
vc200x.xmldeclaration()
vc200x.visualStudioProject(prj)
vc200x.platforms(prj)
if _ACTION > "vs2003" then
_p(1,'<ToolFiles>')
_p(1,'</ToolFiles>')
end
_p(1,'<Configurations>')
for cfg in project.eachconfig(prj) do
vc200x.configuration(cfg)
vc200x.tools(cfg)
_p(2,'</Configuration>')
end
_p(1,'</Configurations>')
_p(1,'<References>')
_p(1,'</References>')
_p(1,'<Files>')
vc200x.files_ng(prj)
_p(1,'</Files>')
_p(1,'<Globals>')
_p(1,'</Globals>')
_p('</VisualStudioProject>')
end
--
-- Return the version-specific text for a boolean value.
--
local function bool(value)
if (_ACTION < "vs2005") then
return iif(value, "TRUE", "FALSE")
else
return iif(value, "true", "false")
end
end
--
-- Writes the opening XML declaration for both the project file
-- and the project user file.
--
function vc200x.xmldeclaration(element)
_p('<?xml version="1.0" encoding="Windows-1252"?>')
end
--
-- Write the opening <VisualStudioProject> element of the project file.
--
function vc200x.visualStudioProject(prj)
_p('<VisualStudioProject')
_p(1,'ProjectType="Visual C++"')
vc200x.projectversion()
_x(1,'Name="%s"', prj.name)
_p(1,'ProjectGUID="{%s}"', prj.uuid)
if _ACTION > "vs2003" then
_x(1,'RootNamespace="%s"', prj.name)
end
_p(1,'Keyword="%s"', iif(prj.flags.Managed, "ManagedCProj", "Win32Proj"))
_p(1,'>')
end
--
-- Write out the <Platforms> element, listing each architecture used
-- by the project's configurations.
--
function vc200x.platforms(prj)
_p(1,'<Platforms>')
architectures = { }
for cfg in project.eachconfig(prj) do
local arch = vstudio.architecture(cfg)
if not architectures[arch] then
_p(2,'<Platform')
_p(3,'Name="%s"', arch)
_p(2,'/>')
architectures[arch] = true
end
end
_p(1,'</Platforms>')
end
--
-- Write out the <Configuration> element, describing a specific Premake
-- build configuration/platform pairing.
--
function vc200x.configuration(cfg)
_p(2,'<Configuration')
_x(3,'Name="%s"', vstudio.configname(cfg))
local outdir = path.translate(config.gettargetinfo(cfg).directory)
_x(3,'OutputDirectory="%s"', outdir)
local objdir = path.translate(config.getuniqueobjdir(cfg))
_x(3,'IntermediateDirectory="%s"', objdir)
local cfgtype
if (cfg.kind == "SharedLib") then
cfgtype = 2
elseif (cfg.kind == "StaticLib") then
cfgtype = 4
else
cfgtype = 1
end
_p(3,'ConfigurationType="%s"', cfgtype)
if (cfg.flags.MFC) then
_p(3, 'UseOfMFC="%d"', iif(cfg.flags.StaticRuntime, 1, 2))
end
_p(3,'CharacterSet="%s"', iif(cfg.flags.Unicode, 1, 2))
if cfg.flags.Managed then
_p(3,'ManagedExtensions="1"')
end
_p(3,'>')
end
--
-- Write out the tool elements for a specific configuration.
--
function vc200x.tools(cfg)
for _, tool in ipairs(vc200x.gettools(cfg)) do
if vc200x.toolmap[tool] then
vc200x.toolmap[tool](cfg)
else
vc200x.tool(tool)
end
end
end
--
-- Write out an empty tool element.
--
function vc200x.tool(name)
_p(3,'<Tool')
_p(4,'Name="%s"', name)
_p(3,'/>')
end
--
-- Write out the VCCLCompilerTool element.
--
function vc200x.VCCLCompilerTool_ng(cfg)
_p(3,'<Tool')
_p(4,'Name="%s"', vc200x.compilertool(cfg))
if cfg.system == premake.PS3 then
vc200x.VCCLCompilerTool_ps3_ng(cfg)
else
vc200x.VCCLCompilerTool_windows(cfg)
end
_p(3,'/>')
end
function vc200x.VCCLCompilerTool_windows(cfg)
if #cfg.buildoptions > 0 then
_x(4,'AdditionalOptions="%s"', table.concat(cfg.buildoptions, " "))
end
_p(4,'Optimization="%s"', vc200x.optimization(cfg))
if cfg.flags.NoFramePointer then
_p(4,'OmitFramePointers="%s"', bool(true))
end
if #cfg.includedirs > 0 then
local dirs = table.concat(project.getrelative(cfg.project, cfg.includedirs), ";")
_x(4,'AdditionalIncludeDirectories="%s"', path.translate(dirs))
end
if #cfg.defines > 0 then
_x(4,'PreprocessorDefinitions="%s"', table.concat(cfg.defines, ";"))
end
if premake.config.isdebugbuild(cfg) and
cfg.debugformat ~= "c7" and
not cfg.flags.NoMinimalRebuild and
not cfg.flags.Managed
then
_p(4,'MinimalRebuild="%s"', bool(true))
end
if cfg.flags.NoExceptions then
_p(4,'ExceptionHandling="%s"', iif(_ACTION < "vs2005", "FALSE", 0))
elseif cfg.flags.SEH and _ACTION > "vs2003" then
_p(4,'ExceptionHandling="2"')
end
if vc200x.optimization(cfg) == 0 and not cfg.flags.Managed then
_p(4,'BasicRuntimeChecks="3"')
end
if vc200x.optimization(cfg) ~= 0 then
_p(4,'StringPooling="%s"', bool(true))
end
local runtime
if premake.config.isdebugbuild(cfg) then
runtime = iif(cfg.flags.StaticRuntime, 1, 3)
else
runtime = iif(cfg.flags.StaticRuntime, 0, 2)
end
_p(4,'RuntimeLibrary="%s"', runtime)
_p(4,'EnableFunctionLevelLinking="%s"', bool(true))
if _ACTION > "vs2003" and cfg.system ~= "Xbox360" and cfg.architecture ~= "x64" then
if cfg.flags.EnableSSE then
_p(4,'EnableEnhancedInstructionSet="1"')
elseif cfg.flags.EnableSSE2 then
_p(4,'EnableEnhancedInstructionSet="2"')
end
end
if _ACTION < "vs2005" then
if cfg.flags.FloatFast then
_p(4,'ImproveFloatingPointConsistency="%s"', bool(false))
elseif cfg.flags.FloatStrict then
_p(4,'ImproveFloatingPointConsistency="%s"', bool(true))
end
else
if cfg.flags.FloatFast then
_p(4,'FloatingPointModel="2"')
elseif cfg.flags.FloatStrict then
_p(4,'FloatingPointModel="1"')
end
end
if _ACTION < "vs2005" and not cfg.flags.NoRTTI then
_p(4,'RuntimeTypeInfo="%s"', bool(true))
elseif _ACTION > "vs2003" and cfg.flags.NoRTTI and not cfg.flags.Managed then
_p(4,'RuntimeTypeInfo="%s"', bool(false))
end
if cfg.flags.NativeWChar then
_p(4,'TreatWChar_tAsBuiltInType="%s"', bool(true))
elseif cfg.flags.NoNativeWChar then
_p(4,'TreatWChar_tAsBuiltInType="%s"', bool(false))
end
if not cfg.flags.NoPCH and cfg.pchheader then
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION < "vs2005", 3, 2))
_x(4,'PrecompiledHeaderThrough="%s"', path.getname(cfg.pchheader))
else
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION > "vs2003" or cfg.flags.NoPCH, 0, 2))
end
_p(4,'WarningLevel="%s"', iif(cfg.flags.ExtraWarnings, 4, 3))
if cfg.flags.FatalWarnings then
_p(4,'WarnAsError="%s"', bool(true))
end
if _ACTION < "vs2008" and not cfg.flags.Managed then
_p(4,'Detect64BitPortabilityProblems="%s"', bool(not cfg.flags.No64BitChecks))
end
_x(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', config.gettargetinfo(cfg).basename)
_p(4,'DebugInformationFormat="%s"', vc200x.symbols(cfg))
if cfg.project.language == "C" then
_p(4, 'CompileAs="1"')
end
end
function vc200x.VCCLCompilerTool_ps3_ng(cfg)
local buildoptions = table.join(premake.snc.getcflags(cfg), premake.snc.getcxxflags(cfg), cfg.buildoptions)
if not cfg.flags.NoPCH and cfg.pchheader then
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION < "vs2005", 3, 2))
_x(4,'PrecompiledHeaderThrough="%s"', path.getname(cfg.pchheader))
table.insert(buildoptions, '--use_pch="$(IntDir)/$(TargetName).pch"')
else
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION > "vs2003" or cfg.flags.NoPCH, 0, 2))
end
if #buildoptions > 0 then
_x(4,'AdditionalOptions="%s"', table.concat(buildoptions, " "))
end
if #cfg.includedirs > 0 then
_x(4,'AdditionalIncludeDirectories="%s"', path.translate(table.concat(cfg.includedirs, ";")))
end
if #cfg.defines > 0 then
_x(4,'PreprocessorDefinitions="%s"', table.concat(cfg.defines, ";"))
end
_x(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', config.gettargetinfo(cfg).basename)
_p(4,'DebugInformationFormat="0"')
_p(4,'CompileAs="0"')
end
--
-- Write out the VCLinkerTool element.
--
function vc200x.VCLinkerTool_ng(cfg)
_p(3,'<Tool')
if cfg.kind == premake.STATICLIB then
_p(4,'Name="VCLibrarianTool"')
if cfg.system == premake.PS3 then
vc200x.VCLinkerTool_ps3_ng(cfg)
else
vc200x.VCLinkerTool_windows_static(cfg)
end
else
_p(4,'Name="%s"', iif(cfg.platform ~= "Xbox360", "VCLinkerTool", "VCX360LinkerTool"))
if cfg.system == premake.PS3 then
vc200x.VCLinkerTool_ps3_ng(cfg)
else
vc200x.VCLinkerTool_windows(cfg)
end
end
_p(3,'/>')
end
function vc200x.VCLinkerTool_windows(cfg)
if cfg.flags.NoImportLib then
_p(4,'IgnoreImportLibrary="%s"', bool(true))
end
if #cfg.linkoptions > 0 then
_x(4,'AdditionalOptions="%s"', table.concat(cfg.linkoptions, " "))
end
if #cfg.links > 0 then
_x(4,'AdditionalDependencies="%s"', vc200x.links(cfg))
end
_x(4,'OutputFile="$(OutDir)\\%s"', config.gettargetinfo(cfg).name)
_p(4,'LinkIncremental="%s"', iif(premake.config.canincrementallink(cfg) , 2, 1))
vc200x.additionalLibraryDirectories(cfg)
local deffile = config.findfile(cfg, ".def")
if deffile then
_p(4,'ModuleDefinitionFile="%s"', deffile)
end
if cfg.flags.NoManifest then
_p(4,'GenerateManifest="%s"', bool(false))
end
_p(4,'GenerateDebugInformation="%s"', bool(vc200x.symbols(cfg) ~= 0))
if vc200x.symbols(cfg) >= 3 then
_x(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', config.gettargetinfo(cfg).basename)
end
_p(4,'SubSystem="%s"', iif(cfg.kind == "ConsoleApp", 1, 2))
if vc200x.optimization(cfg) ~= 0 then
_p(4,'OptimizeReferences="2"')
_p(4,'EnableCOMDATFolding="2"')
end
if (cfg.kind == "ConsoleApp" or cfg.kind == "WindowedApp") and not cfg.flags.WinMain then
_p(4,'EntryPointSymbol="mainCRTStartup"')
end
if cfg.kind == "SharedLib" then
local implibname = config.getlinkinfo(cfg).fullpath
-- I can't actually stop the import lib, but I can hide it in the objects directory
if cfg.flags.NoImportLib then
local objdir = config.getuniqueobjdir(cfg)
implibname = path.join(objdir, path.getname(implibname))
end
_x(4,'ImportLibrary="%s"', path.translate(implibname))
end
_p(4,'TargetMachine="%d"', iif(cfg.architecture == "x64", 17, 1))
end
function vc200x.VCLinkerTool_windows_static(cfg)
if #cfg.links > 0 then
_x(4,'AdditionalDependencies="%s"', vc200x.links(cfg))
end
_x(4,'OutputFile="$(OutDir)\\%s"', config.gettargetinfo(cfg).name)
vc200x.additionalLibraryDirectories(cfg)
local opts = {}
if cfg.architecture == premake.X32 then
table.insert(opts, "/MACHINE:X86")
elseif cfg.architecture == premake.X64 then
table.insert(opts, "/MACHINE:X64")
end
opts = table.join(opts, cfg.linkoptions)
if #opts > 0 then
_x(4,'AdditionalOptions="%s"', table.concat(opts, " "))
end
end
function vc200x.VCLinkerTool_ps3_ng(cfg)
local buildoptions = table.join(premake.snc.getldflags_ng(cfg), cfg.linkoptions)
if #buildoptions > 0 then
_x(4,'AdditionalOptions="%s"', table.concat(buildoptions, " "))
end
if #cfg.links > 0 then
_x(4,'AdditionalDependencies="%s"', table.concat(config.getlinks(cfg, "all", "fullpath"), " "))
end
_x(4,'OutputFile="$(OutDir)\\%s"', config.gettargetinfo(cfg).name)
if cfg.kind ~= premake.STATICLIB then
_p(4,'LinkIncremental="0"')
end
vc200x.additionalLibraryDirectories(cfg)
if cfg.kind ~= premake.STATICLIB then
_p(4,'GenerateManifest="%s"', bool(false))
_p(4,'ProgramDatabaseFile=""')
_p(4,'RandomizedBaseAddress="1"')
_p(4,'DataExecutionPrevention="0"')
end
end
--
-- Write out the <VCManifestTool> element.
--
function vc200x.VCManifestTool_ng(cfg)
local manifests = {}
for _, fname in ipairs(cfg.files) do
if path.getextension(fname) == ".manifest" then
table.insert(manifests, project.getrelative(cfg.project, fname))
end
end
_p(3,'<Tool')
_p(4,'Name="VCManifestTool"')
if #manifests > 0 then
_x(4,'AdditionalManifestFiles="%s"', table.concat(manifests, ";"))
end
_p(3,'/>')
end
--
-- Write out the <VCMIDLTool> block
--
function vc200x.VCMIDLTool_ng(cfg)
_p(3,'<Tool')
_p(4,'Name="VCMIDLTool"')
if cfg.architecture == "x64" then
_p(4,'TargetEnvironment="3"')
end
_p(3,'/>')
end
--
-- Write out the resource compiler block.
--
function vc200x.VCResourceCompilerTool_ng(cfg)
_p(3,'<Tool')
_p(4,'Name="VCResourceCompilerTool"')
if #cfg.resoptions > 0 then
_x(4,'AdditionalOptions="%s"', table.concat(cfg.resoptions, " "))
end
if #cfg.defines > 0 or #cfg.resdefines > 0 then
local defines = table.join(cfg.defines, cfg.resdefines)
_x(4,'PreprocessorDefinitions="%s"', table.concat(defines, ";"))
end
if #cfg.includedirs > 0 or #cfg.resincludedirs > 0 then
local dirs = table.join(cfg.includedirs, cfg.resincludedirs)
_x(4,'AdditionalIncludeDirectories="%s"', path.translate(table.concat(dirs, ";")))
end
_p(3,'/>')
end
--
-- Write out the custom build step blocks.
--
local function buildstepsblock(name, steps)
_p(3,'<Tool')
_p(4,'Name="%s"', name)
if #steps > 0 then
_x(4,'CommandLine="%s"', table.implode(steps, "", "", "\r\n"))
end
_p(3,'/>')
end
function vc200x.VCPreBuildEventTool(cfg)
buildstepsblock("VCPreBuildEventTool", cfg.prebuildcommands)
end
function vc200x.VCPreLinkEventTool(cfg)
buildstepsblock("VCPreLinkEventTool", cfg.prelinkcommands)
end
function vc200x.VCPostBuildEventTool(cfg)
buildstepsblock("VCPostBuildEventTool", cfg.postbuildcommands)
end
--
-- Write out the Xbox 360 deployment tool block.
--
function vc200x.VCX360DeploymentTool(cfg)
_p(3,'<Tool')
_p(4,'Name="VCX360DeploymentTool"')
_p(4,'DeploymentType="0"')
if #cfg.deploymentoptions > 0 then
_x(4,'AdditionalOptions="%s"', table.concat(cfg.deploymentoptions, " "))
end
_p(3,'/>')
end
--
-- Write out the Xbox 360 image tool block.
--
function vc200x.VCX360ImageTool(cfg)
_p(3,'<Tool')
_p(4,'Name="VCX360ImageTool"')
if #cfg.imageoptions > 0 then
_x(4,'AdditionalOptions="%s"', table.concat(cfg.imageoptions, " "))
end
if cfg.imagepath ~= nil then
_x(4,'OutputFileName="%s"', path.translate(cfg.imagepath))
end
_p(3,'/>')
end
--
-- Write out the Xbox 360 debugger tool block.
--
function vc200x.DebuggerTool(cfg)
_p(3,'<DebuggerTool')
_p(3,'/>')
end
--
-- Return the list of tools required to build a specific configuration.
-- Each tool gets represented by an XML element in the project file.
--
function vc200x.gettools(cfg)
if _ACTION == "vs2002" then
return {
"VCCLCompilerTool",
"VCCustomBuildTool",
"VCLinkerTool",
"VCMIDLTool",
"VCPostBuildEventTool",
"VCPreBuildEventTool",
"VCPreLinkEventTool",
"VCResourceCompilerTool",
"VCWebServiceProxyGeneratorTool",
"VCWebDeploymentTool"
}
end
if _ACTION == "vs2003" then
return {
"VCCLCompilerTool",
"VCCustomBuildTool",
"VCLinkerTool",
"VCMIDLTool",
"VCPostBuildEventTool",
"VCPreBuildEventTool",
"VCPreLinkEventTool",
"VCResourceCompilerTool",
"VCWebServiceProxyGeneratorTool",
"VCXMLDataGeneratorTool",
"VCWebDeploymentTool",
"VCManagedWrapperGeneratorTool",
"VCAuxiliaryManagedWrapperGeneratorTool"
}
end
if cfg.system == premake.XBOX360 then
return {
"VCPreBuildEventTool",
"VCCustomBuildTool",
"VCXMLDataGeneratorTool",
"VCWebServiceProxyGeneratorTool",
"VCMIDLTool",
"VCCLCompilerTool",
"VCManagedResourceCompilerTool",
"VCResourceCompilerTool",
"VCPreLinkEventTool",
"VCLinkerTool",
"VCALinkTool",
"VCX360ImageTool",
"VCBscMakeTool",
"VCX360DeploymentTool",
"VCPostBuildEventTool",
"DebuggerTool",
}
end
return {
"VCPreBuildEventTool",
"VCCustomBuildTool",
"VCXMLDataGeneratorTool",
"VCWebServiceProxyGeneratorTool",
"VCMIDLTool",
"VCCLCompilerTool",
"VCManagedResourceCompilerTool",
"VCResourceCompilerTool",
"VCPreLinkEventTool",
"VCLinkerTool",
"VCALinkTool",
"VCManifestTool",
"VCXDCMakeTool",
"VCBscMakeTool",
"VCFxCopTool",
"VCAppVerifierTool",
"VCWebDeploymentTool",
"VCPostBuildEventTool"
}
end
--
-- Map tool names to output functions. Tools that aren't listed will
-- output a standard empty tool element.
--
vc200x.toolmap = {
DebuggerTool = vc200x.DebuggerTool,
VCCLCompilerTool = vc200x.VCCLCompilerTool_ng,
VCLinkerTool = vc200x.VCLinkerTool_ng,
VCManifestTool = vc200x.VCManifestTool_ng,
VCMIDLTool = vc200x.VCMIDLTool_ng,
VCPostBuildEventTool = vc200x.VCPostBuildEventTool,
VCPreBuildEventTool = vc200x.VCPreBuildEventTool,
VCPreLinkEventTool = vc200x.VCPreLinkEventTool,
VCResourceCompilerTool = vc200x.VCResourceCompilerTool_ng,
VCX360DeploymentTool = vc200x.VCX360DeploymentTool,
VCX360ImageTool = vc200x.VCX360ImageTool
}
--
-- Write out the source file tree.
--
function vc200x.files_ng(prj)
local tr = project.getsourcetree(prj)
local pchsource = project.getrelative(prj, prj.pchsource)
tree.traverse(tr, {
-- folders, virtual or otherwise, are handled at the internal nodes
onbranchenter = function(node, depth)
_p(depth, '<Filter')
_p(depth, '\tName="%s"', node.name)
_p(depth, '\tFilter=""')
_p(depth, '\t>')
end,
onbranchexit = function(node, depth)
_p(depth, '</Filter>')
end,
-- source files are handled at the leaves
onleaf = function(node, depth)
_p(depth, '<File')
_p(depth, '\tRelativePath="%s"', path.translate(node.cfg.fullpath))
_p(depth, '\t>')
-- C files in C++ projects should still be compiled as C code
local compileAs
if path.iscfile(node.name) ~= premake.project.iscproject(prj) then
if path.iscppfile(node.name) then
compileAs = iif(prj.language == premake.CPP, 1, 2)
end
end
depth = depth + 1
for cfg in project.eachconfig(prj) do
local hasconfig
local out = function(depth, msg, ...)
if not hasconfig then
hasconfig = true
_p(depth, '<FileConfiguration')
_p(depth, '\tName="%s"', vstudio.configname(cfg))
_p(depth, '\t>')
_p(depth, '\t<Tool')
_p(depth, '\t\tName="%s"', vc200x.compilertool(cfg))
end
_x(depth, msg, unpack(arg))
end
if compileAs then
out(depth, '\t\tCompileAs="%s"', compileAs)
end
if pchsource == node.cfg.fullpath and not cfg.flags.NoPCH then
if cfg.system == premake.PS3 then
local options = table.join(premake.snc.getcflags(cfg),
premake.snc.getcxxflags(cfg),
cfg.buildoptions,
' --create_pch="$(IntDir)/$(TargetName).pch"')
out(depth, '\t\tAdditionalOptions="%s"', table.concat(options, " "))
else
out(depth, '\t\tUsePrecompiledHeader="1"')
end
end
if hasconfig then
_p(depth, '\t/>')
_p(depth, '</FileConfiguration>')
end
end
depth = depth - 1
_p(depth, '</File>')
end
}, false, 2)
end
--
-- Write out the <AdditionalLibraryDirectories> block, used by the
-- various linker tool variations.
--
function vc200x.additionalLibraryDirectories(cfg)
if #cfg.libdirs > 0 then
local dirs = table.concat(project.getrelative(cfg.project, cfg.libdirs), ";")
_x(4,'AdditionalLibraryDirectories="%s"', path.translate(dirs))
end
end
--
-- Returns the correct name for the compiler tool element, based on
-- the configuration target system.
--
function vc200x.compilertool(cfg)
if cfg.system == premake.XBOX360 then
return "VCCLX360CompilerTool"
else
return "VCCLCompilerTool"
end
end
--
-- Returns the list of libraries required to link a specific configuration,
-- formatted for Visual Studio's XML.
--
function vc200x.links(cfg)
local links = config.getlinks(cfg, "system", "fullpath")
links = table.concat(links, " ")
links = path.translate(links)
return links
end
--
-- Translate Premake flags into a Visual Studio optimization value.
--
function vc200x.optimization(cfg)
local result = 0
-- step through the flags in the order they were specified, so
-- later flags can override an earlier value
for _, value in ipairs(cfg.flags) do
if (value == "Optimize") then
result = 3
elseif (value == "OptimizeSize") then
result = 1
elseif (value == "OptimizeSpeed") then
result = 2
end
end
return result
end
--
-- Return the debugging symbols level for a configuration.
--
function vc200x.symbols(cfg)
if not cfg.flags.Symbols then
return 0
elseif cfg.debugformat == "c7" then
return 1
else
-- Edit-and-continue doesn't work for some configurations
if cfg.flags.NoEditAndContinue or
vc200x.optimization(cfg) ~= 0 or
cfg.flags.Managed or
cfg.system == "x64" or
cfg.platform == "x64" -- TODO: remove this when the _ng stuff goes live
then
return 3
else
return 4
end
end
end
--
-- Output the correct project version attribute for the current action.
--
function vc200x.projectversion()
local map = {
vs2002 = '7.0',
vs2003 = '7.1',
vs2005 = '8.0',
vs2008 = '9.0'
}
_p(1,'Version="%s0"', map[_ACTION])
end
-----------------------------------------------------------------------------
-- Everything below this point is a candidate for deprecation
-----------------------------------------------------------------------------
--
-- Write the project file header
--
function vc200x.header(element)
io.eol = "\r\n"
_p('<?xml version="1.0" encoding="Windows-1252"?>')
_p('<%s', element)
_p(1,'ProjectType="Visual C++"')
if _ACTION == "vs2002" then
_p(1,'Version="7.00"')
elseif _ACTION == "vs2003" then
_p(1,'Version="7.10"')
elseif _ACTION == "vs2005" then
_p(1,'Version="8.00"')
elseif _ACTION == "vs2008" then
_p(1,'Version="9.00"')
end
end
--
-- Write out the <Configuration> element.
--
function vc200x.Configuration(name, cfg)
_p(2,'<Configuration')
_p(3,'Name="%s"', premake.esc(name))
_p(3,'OutputDirectory="%s"', premake.esc(cfg.buildtarget.directory))
_p(3,'IntermediateDirectory="%s"', premake.esc(cfg.objectsdir))
local cfgtype
if (cfg.kind == "SharedLib") then
cfgtype = 2
elseif (cfg.kind == "StaticLib") then
cfgtype = 4
else
cfgtype = 1
end
_p(3,'ConfigurationType="%s"', cfgtype)
if (cfg.flags.MFC) then
_p(3, 'UseOfMFC="%d"', iif(cfg.flags.StaticRuntime, 1, 2))
end
_p(3,'CharacterSet="%s"', iif(cfg.flags.Unicode, 1, 2))
if cfg.flags.Managed then
_p(3,'ManagedExtensions="1"')
end
_p(3,'>')
end
--
-- Write out the <Files> element.
--
function vc200x.Files(prj)
local tr = premake.project.buildsourcetree(prj)
tree.traverse(tr, {
-- folders are handled at the internal nodes
onbranchenter = function(node, depth)
_p(depth, '<Filter')
_p(depth, '\tName="%s"', node.name)
_p(depth, '\tFilter=""')
_p(depth, '\t>')
end,
onbranchexit = function(node, depth)
_p(depth, '</Filter>')
end,
-- source files are handled at the leaves
onleaf = function(node, depth)
local fname = node.cfg.name
_p(depth, '<File')
_p(depth, '\tRelativePath="%s"', path.translate(fname, "\\"))
_p(depth, '\t>')
depth = depth + 1
-- handle file configuration stuff. This needs to be cleaned up and simplified.
-- configurations are cached, so this isn't as bad as it looks
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
if cfginfo.isreal then
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
local usePCH = (not prj.flags.NoPCH and prj.pchsource == node.cfg.name)
local isSourceCode = path.iscppfile(fname)
local needsCompileAs = (path.iscfile(fname) ~= premake.project.iscproject(prj))
if usePCH or (isSourceCode and needsCompileAs) then
_p(depth, '<FileConfiguration')
_p(depth, '\tName="%s"', cfginfo.name)
_p(depth, '\t>')
_p(depth, '\t<Tool')
_p(depth, '\t\tName="%s"', iif(cfg.system == "Xbox360",
"VCCLX360CompilerTool",
"VCCLCompilerTool"))
if needsCompileAs then
_p(depth, '\t\tCompileAs="%s"', iif(path.iscfile(fname), 1, 2))
end
if usePCH then
if cfg.system == "PS3" then
local options = table.join(premake.snc.getcflags(cfg),
premake.snc.getcxxflags(cfg),
cfg.buildoptions)
options = table.concat(options, " ");
options = options .. ' --create_pch="$(IntDir)/$(TargetName).pch"'
_p(depth, '\t\tAdditionalOptions="%s"', premake.esc(options))
else
_p(depth, '\t\tUsePrecompiledHeader="1"')
end
end
_p(depth, '\t/>')
_p(depth, '</FileConfiguration>')
end
end
end
depth = depth - 1
_p(depth, '</File>')
end,
}, false, 2)
end
--
-- Write out the <Platforms> element, listing each architecture used
-- by the project's configurations.
--
function vc200x.Platforms(prj)
local used = { }
_p(1,'<Platforms>')
for _, cfg in ipairs(prj.solution.vstudio_configs) do
if cfg.isreal and not table.contains(used, cfg.platform) then
table.insert(used, cfg.platform)
_p(2,'<Platform')
_p(3,'Name="%s"', cfg.platform)
_p(2,'/>')
end
end
_p(1,'</Platforms>')
end
--
-- Compiler block for Windows and XBox360 platforms.
--
function vc200x.VCCLCompilerTool(cfg)
_p(3,'<Tool')
_p(4,'Name="%s"', iif(cfg.platform ~= "Xbox360", "VCCLCompilerTool", "VCCLX360CompilerTool"))
if #cfg.buildoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.buildoptions), " "))
end
_p(4,'Optimization="%s"', vc200x.optimization(cfg))
if cfg.flags.NoFramePointer then
_p(4,'OmitFramePointers="%s"', bool(true))
end
if #cfg.includedirs > 0 then
_p(4,'AdditionalIncludeDirectories="%s"', premake.esc(path.translate(table.concat(cfg.includedirs, ";"), '\\')))
end
if #cfg.defines > 0 then
_p(4,'PreprocessorDefinitions="%s"', premake.esc(table.concat(cfg.defines, ";")))
end
if premake.config.isdebugbuild(cfg) and
cfg.debugformat ~= "c7" and
not cfg.flags.NoMinimalRebuild and
not cfg.flags.Managed
then
_p(4,'MinimalRebuild="%s"', bool(true))
end
if cfg.flags.NoExceptions then
_p(4,'ExceptionHandling="%s"', iif(_ACTION < "vs2005", "FALSE", 0))
elseif cfg.flags.SEH and _ACTION > "vs2003" then
_p(4,'ExceptionHandling="2"')
end
if vc200x.optimization(cfg) == 0 and not cfg.flags.Managed then
_p(4,'BasicRuntimeChecks="3"')
end
if vc200x.optimization(cfg) ~= 0 then
_p(4,'StringPooling="%s"', bool(true))
end
local runtime
if premake.config.isdebugbuild(cfg) then
runtime = iif(cfg.flags.StaticRuntime, 1, 3)
else
runtime = iif(cfg.flags.StaticRuntime, 0, 2)
end
_p(4,'RuntimeLibrary="%s"', runtime)
_p(4,'EnableFunctionLevelLinking="%s"', bool(true))
if _ACTION > "vs2003" and cfg.platform ~= "Xbox360" and cfg.platform ~= "x64" then
if cfg.flags.EnableSSE then
_p(4,'EnableEnhancedInstructionSet="1"')
elseif cfg.flags.EnableSSE2 then
_p(4,'EnableEnhancedInstructionSet="2"')
end
end
if _ACTION < "vs2005" then
if cfg.flags.FloatFast then
_p(4,'ImproveFloatingPointConsistency="%s"', bool(false))
elseif cfg.flags.FloatStrict then
_p(4,'ImproveFloatingPointConsistency="%s"', bool(true))
end
else
if cfg.flags.FloatFast then
_p(4,'FloatingPointModel="2"')
elseif cfg.flags.FloatStrict then
_p(4,'FloatingPointModel="1"')
end
end
if _ACTION < "vs2005" and not cfg.flags.NoRTTI then
_p(4,'RuntimeTypeInfo="%s"', bool(true))
elseif _ACTION > "vs2003" and cfg.flags.NoRTTI and not cfg.flags.Managed then
_p(4,'RuntimeTypeInfo="%s"', bool(false))
end
if cfg.flags.NativeWChar then
_p(4,'TreatWChar_tAsBuiltInType="%s"', bool(true))
elseif cfg.flags.NoNativeWChar then
_p(4,'TreatWChar_tAsBuiltInType="%s"', bool(false))
end
if not cfg.flags.NoPCH and cfg.pchheader then
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION < "vs2005", 3, 2))
_p(4,'PrecompiledHeaderThrough="%s"', path.getname(cfg.pchheader))
else
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION > "vs2003" or cfg.flags.NoPCH, 0, 2))
end
_p(4,'WarningLevel="%s"', iif(cfg.flags.ExtraWarnings, 4, 3))
if cfg.flags.FatalWarnings then
_p(4,'WarnAsError="%s"', bool(true))
end
if _ACTION < "vs2008" and not cfg.flags.Managed then
_p(4,'Detect64BitPortabilityProblems="%s"', bool(not cfg.flags.No64BitChecks))
end
_p(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', path.getbasename(cfg.buildtarget.name))
_p(4,'DebugInformationFormat="%s"', vc200x.symbols(cfg))
if cfg.language == "C" then
_p(4, 'CompileAs="1"')
end
_p(3,'/>')
end
--
-- Linker block for Windows and Xbox 360 platforms.
--
function vc200x.VCLinkerTool(cfg)
_p(3,'<Tool')
if cfg.kind ~= "StaticLib" then
_p(4,'Name="%s"', iif(cfg.platform ~= "Xbox360", "VCLinkerTool", "VCX360LinkerTool"))
if cfg.flags.NoImportLib then
_p(4,'IgnoreImportLibrary="%s"', bool(true))
end
if #cfg.linkoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.linkoptions), " "))
end
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
_p(4,'LinkIncremental="%s"',
iif(premake.config.canincrementallink(cfg) , 2, 1))
_p(4,'AdditionalLibraryDirectories="%s"', table.concat(premake.esc(path.translate(cfg.libdirs, '\\')) , ";"))
local deffile = premake.findfile(cfg, ".def")
if deffile then
_p(4,'ModuleDefinitionFile="%s"', deffile)
end
if cfg.flags.NoManifest then
_p(4,'GenerateManifest="%s"', bool(false))
end
_p(4,'GenerateDebugInformation="%s"', bool(vc200x.symbols(cfg) ~= 0))
if vc200x.symbols(cfg) >= 3 then
_p(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', path.getbasename(cfg.buildtarget.name))
end
_p(4,'SubSystem="%s"', iif(cfg.kind == "ConsoleApp", 1, 2))
if vc200x.optimization(cfg) ~= 0 then
_p(4,'OptimizeReferences="2"')
_p(4,'EnableCOMDATFolding="2"')
end
if (cfg.kind == "ConsoleApp" or cfg.kind == "WindowedApp") and not cfg.flags.WinMain then
_p(4,'EntryPointSymbol="mainCRTStartup"')
end
if cfg.kind == "SharedLib" then
local implibname = config.getlinkinfo(cfg).fullpath
_p(4,'ImportLibrary="%s"', iif(cfg.flags.NoImportLib, cfg.objectsdir .. "\\" .. path.getname(implibname), implibname))
end
_p(4,'TargetMachine="%d"', iif(cfg.platform == "x64", 17, 1))
else
_p(4,'Name="VCLibrarianTool"')
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
if #cfg.libdirs > 0 then
_p(4,'AdditionalLibraryDirectories="%s"', premake.esc(path.translate(table.concat(cfg.libdirs , ";"))))
end
local addlOptions = {}
if cfg.platform == "x32" then
table.insert(addlOptions, "/MACHINE:X86")
elseif cfg.platform == "x64" then
table.insert(addlOptions, "/MACHINE:X64")
end
addlOptions = table.join(addlOptions, cfg.linkoptions)
if #addlOptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(addlOptions), " "))
end
end
_p(3,'/>')
end
--
-- Compiler and linker blocks for the PS3 platform, which uses Sony's SNC.
--
function vc200x.VCCLCompilerTool_PS3(cfg)
_p(3,'<Tool')
_p(4,'Name="VCCLCompilerTool"')
local buildoptions = table.join(premake.snc.getcflags(cfg), premake.snc.getcxxflags(cfg), cfg.buildoptions)
if not cfg.flags.NoPCH and cfg.pchheader then
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION < "vs2005", 3, 2))
_p(4,'PrecompiledHeaderThrough="%s"', path.getname(cfg.pchheader))
table.insert(buildoptions, '--use_pch="$(IntDir)/$(TargetName).pch"')
else
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION > "vs2003" or cfg.flags.NoPCH, 0, 2))
end
_p(4,'AdditionalOptions="%s"', premake.esc(table.concat(buildoptions, " ")))
if #cfg.includedirs > 0 then
_p(4,'AdditionalIncludeDirectories="%s"', premake.esc(path.translate(table.concat(cfg.includedirs, ";"), '\\')))
end
if #cfg.defines > 0 then
_p(4,'PreprocessorDefinitions="%s"', table.concat(premake.esc(cfg.defines), ";"))
end
_p(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', path.getbasename(cfg.buildtarget.name))
_p(4,'DebugInformationFormat="0"')
_p(4,'CompileAs="0"')
_p(3,'/>')
end
function vc200x.VCLinkerTool_PS3(cfg)
_p(3,'<Tool')
if cfg.kind ~= "StaticLib" then
_p(4,'Name="VCLinkerTool"')
local buildoptions = table.join(premake.snc.getldflags(cfg), cfg.linkoptions)
if #buildoptions > 0 then
_p(4,'AdditionalOptions="%s"', premake.esc(table.concat(buildoptions, " ")))
end
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
_p(4,'LinkIncremental="0"')
_p(4,'AdditionalLibraryDirectories="%s"', table.concat(premake.esc(path.translate(cfg.libdirs, '\\')) , ";"))
_p(4,'GenerateManifest="%s"', bool(false))
_p(4,'ProgramDatabaseFile=""')
_p(4,'RandomizedBaseAddress="1"')
_p(4,'DataExecutionPrevention="0"')
else
_p(4,'Name="VCLibrarianTool"')
local buildoptions = table.join(premake.snc.getldflags(cfg), cfg.linkoptions)
if #buildoptions > 0 then
_p(4,'AdditionalOptions="%s"', premake.esc(table.concat(buildoptions, " ")))
end
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
if #cfg.libdirs > 0 then
_p(4,'AdditionalLibraryDirectories="%s"', premake.esc(path.translate(table.concat(cfg.libdirs , ";"))))
end
end
_p(3,'/>')
end
--
-- Write out the <VCManifest> element.
--
function vc200x.VCManifestTool(cfg)
local manifests = {}
for _, fname in ipairs(cfg.files) do
if path.getextension(fname) == ".manifest" then
table.insert(manifests, fname)
end
end
_p(3,'<Tool')
_p(4,'Name="VCManifestTool"')
if #manifests > 0 then
_x(4,'AdditionalManifestFiles="%s"', table.concat(manifests, ";"))
end
_p(3,'/>')
end
--
-- Resource compiler block.
--
function vc200x.VCResourceCompilerTool(cfg)
_p(3,'<Tool')
_p(4,'Name="VCResourceCompilerTool"')
if #cfg.resoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.resoptions), " "))
end
if #cfg.defines > 0 or #cfg.resdefines > 0 then
_p(4,'PreprocessorDefinitions="%s"', table.concat(premake.esc(table.join(cfg.defines, cfg.resdefines)), ";"))
end
if #cfg.includedirs > 0 or #cfg.resincludedirs > 0 then
local dirs = table.join(cfg.includedirs, cfg.resincludedirs)
_p(4,'AdditionalIncludeDirectories="%s"', premake.esc(path.translate(table.concat(dirs, ";"), '\\')))
end
_p(3,'/>')
end
--
-- VCMIDLTool block
--
function vc200x.VCMIDLTool(cfg)
_p(3,'<Tool')
_p(4,'Name="VCMIDLTool"')
if cfg.platform == "x64" then
_p(4,'TargetEnvironment="3"')
end
_p(3,'/>')
end
--
-- Map project tool blocks to handler functions. Unmapped blocks will output
-- an empty <Tool> element.
--
local blockmap =
{
VCCLCompilerTool = vc200x.VCCLCompilerTool,
VCCLCompilerTool_PS3 = vc200x.VCCLCompilerTool_PS3,
VCLinkerTool = vc200x.VCLinkerTool,
VCLinkerTool_PS3 = vc200x.VCLinkerTool_PS3,
VCManifestTool = vc200x.VCManifestTool,
VCMIDLTool = vc200x.VCMIDLTool,
VCResourceCompilerTool = vc200x.VCResourceCompilerTool,
}
--
-- Return a list of sections for a particular Visual Studio version and target platform.
--
local function getsections(version, platform)
if version == "vs2002" then
return {
"VCCLCompilerTool",
"VCCustomBuildTool",
"VCLinkerTool",
"VCMIDLTool",
"VCPostBuildEventTool",
"VCPreBuildEventTool",
"VCPreLinkEventTool",
"VCResourceCompilerTool",
"VCWebServiceProxyGeneratorTool",
"VCWebDeploymentTool"
}
end
if version == "vs2003" then
return {
"VCCLCompilerTool",
"VCCustomBuildTool",
"VCLinkerTool",
"VCMIDLTool",
"VCPostBuildEventTool",
"VCPreBuildEventTool",
"VCPreLinkEventTool",
"VCResourceCompilerTool",
"VCWebServiceProxyGeneratorTool",
"VCXMLDataGeneratorTool",
"VCWebDeploymentTool",
"VCManagedWrapperGeneratorTool",
"VCAuxiliaryManagedWrapperGeneratorTool"
}
end
if platform == "Xbox360" then
return {
"VCPreBuildEventTool",
"VCCustomBuildTool",
"VCXMLDataGeneratorTool",
"VCWebServiceProxyGeneratorTool",
"VCMIDLTool",
"VCCLCompilerTool",
"VCManagedResourceCompilerTool",
"VCResourceCompilerTool",
"VCPreLinkEventTool",
"VCLinkerTool",
"VCALinkTool",
"VCX360ImageTool",
"VCBscMakeTool",
"VCX360DeploymentTool",
"VCPostBuildEventTool",
"DebuggerTool",
}
end
if platform == "PS3" then
return {
"VCPreBuildEventTool",
"VCCustomBuildTool",
"VCXMLDataGeneratorTool",
"VCWebServiceProxyGeneratorTool",
"VCMIDLTool",
"VCCLCompilerTool_PS3",
"VCManagedResourceCompilerTool",
"VCResourceCompilerTool",
"VCPreLinkEventTool",
"VCLinkerTool_PS3",
"VCALinkTool",
"VCManifestTool",
"VCXDCMakeTool",
"VCBscMakeTool",
"VCFxCopTool",
"VCAppVerifierTool",
"VCWebDeploymentTool",
"VCPostBuildEventTool"
}
else
return {
"VCPreBuildEventTool",
"VCCustomBuildTool",
"VCXMLDataGeneratorTool",
"VCWebServiceProxyGeneratorTool",
"VCMIDLTool",
"VCCLCompilerTool",
"VCManagedResourceCompilerTool",
"VCResourceCompilerTool",
"VCPreLinkEventTool",
"VCLinkerTool",
"VCALinkTool",
"VCManifestTool",
"VCXDCMakeTool",
"VCBscMakeTool",
"VCFxCopTool",
"VCAppVerifierTool",
"VCWebDeploymentTool",
"VCPostBuildEventTool"
}
end
end
--
-- The main function: write the project file.
--
function vc200x.generate(prj)
vc200x.header('VisualStudioProject')
_p(1,'Name="%s"', premake.esc(prj.name))
_p(1,'ProjectGUID="{%s}"', prj.uuid)
if _ACTION > "vs2003" then
_p(1,'RootNamespace="%s"', prj.name)
end
_p(1,'Keyword="%s"', iif(prj.flags.Managed, "ManagedCProj", "Win32Proj"))
_p(1,'>')
-- list the target platforms
vc200x.Platforms(prj)
if _ACTION > "vs2003" then
_p(1,'<ToolFiles>')
_p(1,'</ToolFiles>')
end
_p(1,'<Configurations>')
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
if cfginfo.isreal then
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
-- Start a configuration
vc200x.Configuration(cfginfo.name, cfg)
for _, block in ipairs(getsections(_ACTION, cfginfo.src_platform)) do
if blockmap[block] then
blockmap[block](cfg)
-- Build event blocks --
elseif block == "VCPreBuildEventTool" then
vc200x.buildstepsblock("VCPreBuildEventTool", cfg.prebuildcommands)
elseif block == "VCPreLinkEventTool" then
vc200x.buildstepsblock("VCPreLinkEventTool", cfg.prelinkcommands)
elseif block == "VCPostBuildEventTool" then
vc200x.buildstepsblock("VCPostBuildEventTool", cfg.postbuildcommands)
-- End build event blocks --
-- Xbox 360 custom sections --
elseif block == "VCX360DeploymentTool" then
_p(3,'<Tool')
_p(4,'Name="VCX360DeploymentTool"')
_p(4,'DeploymentType="0"')
if #cfg.deploymentoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.deploymentoptions), " "))
end
_p(3,'/>')
elseif block == "VCX360ImageTool" then
_p(3,'<Tool')
_p(4,'Name="VCX360ImageTool"')
if #cfg.imageoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.imageoptions), " "))
end
if cfg.imagepath ~= nil then
_p(4,'OutputFileName="%s"', premake.esc(path.translate(cfg.imagepath)))
end
_p(3,'/>')
elseif block == "DebuggerTool" then
_p(3,'<DebuggerTool')
_p(3,'/>')
-- End Xbox 360 custom sections --
else
_p(3,'<Tool')
_p(4,'Name="%s"', block)
_p(3,'/>')
end
end
_p(2,'</Configuration>')
end
end
_p(1,'</Configurations>')
_p(1,'<References>')
_p(1,'</References>')
_p(1,'<Files>')
vc200x.Files(prj)
_p(1,'</Files>')
_p(1,'<Globals>')
_p(1,'</Globals>')
_p('</VisualStudioProject>')
end