-- -- 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) local architectures = vc200x.platforms(prj) if _ACTION > "vs2003" then _p(1,'') _p(1,'') end _p(1,'') for cfg in project.eachconfig(prj) do -- Visual Studio requires each project configuration to have an -- entry for every project architecture. Those that are not -- actually part of the solution, use a skeleton configuration. local cfgarch = vstudio.architecture(cfg) for _, prjarch in ipairs(architectures) do if cfgarch == prjarch then vc200x.configuration(cfg) vc200x.tools(cfg) _p(2,'') else vc200x.emptyconfiguration(cfg, prjarch) end end end _p(1,'') _p(1,'') vc200x.projectReferences(prj) _p(1,'') _p(1,'') vc200x.files_ng(prj) _p(1,'') _p(1,'') _p(1,'') _p('') 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('') end -- -- Write the opening element of the project file. -- function vc200x.visualStudioProject(prj) _p(' "vs2003" then _x(1,'RootNamespace="%s"', prj.name) end -- flags are located on the configurations; grab one local cfg = project.getconfig(prj, prj.configurations[1], prj.platforms[1]) _p(1,'Keyword="%s"', iif(cfg.flags.Managed, "ManagedCProj", "Win32Proj")) _p(1,'TargetFrameworkVersion=\"0\"') _p(1,'>') end -- -- Write out the element, listing each architecture used -- by the project's configurations. -- function vc200x.platforms(prj) _p(1,'') architectures = {} for cfg in project.eachconfig(prj) do local arch = vstudio.architecture(cfg) if not table.contains(architectures, arch) then table.insert(architectures, arch) _p(2,'') end end _p(1,'') return architectures end -- -- Write out the element, describing a specific Premake -- build configuration/platform pairing. -- function vc200x.configuration(cfg) _p(2,'') end -- -- Write out an empty configuration element for a build configuration/ -- platform that is not actually part of the solution. -- function vc200x.emptyconfiguration(cfg, arch) _p(2,'') local tools = vc200x.gettools(cfg) for _, tool in ipairs(tools) do vc200x.tool(tool) end _p(2,'') 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,'') end -- -- Write out the VCCLCompilerTool element. -- function vc200x.VCCLCompilerTool_ng(cfg) _p(3,'') end function vc200x.VCCLBuiltInCompilerTool(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 vc200x.additionalIncludeDirectories(cfg, cfg.includedirs) vc200x.preprocessorDefinitions(cfg, cfg.defines) 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 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 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 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 vc200x.programDatabase(cfg) vc200x.warnings(cfg) _p(4,'DebugInformationFormat="%s"', vc200x.symbols(cfg)) if cfg.project.language == "C" then _p(4, 'CompileAs="1"') end vc200x.forcedIncludeFiles(cfg) end function vc200x.VCCLExternalCompilerTool(cfg, toolset) local buildoptions = table.join(toolset.getcflags(cfg), toolset.getcxxflags(cfg), cfg.buildoptions) if not cfg.flags.NoPCH and cfg.pchheader then table.insert(buildoptions, '--use_pch="$(IntDir)/$(TargetName).pch"') end if #buildoptions > 0 then _x(4,'AdditionalOptions="%s"', table.concat(buildoptions, " ")) end vc200x.additionalIncludeDirectories(cfg, cfg.includedirs) vc200x.preprocessorDefinitions(cfg, cfg.defines) 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 vc200x.programDatabase(cfg) _p(4,'DebugInformationFormat="0"') _p(4,'CompileAs="0"') vc200x.forcedIncludeFiles(cfg) end -- -- Write out the VCLinkerTool element. -- function vc200x.VCLinkerTool_ng(cfg) _p(3,'') end function vc200x.VCBuiltInLinkerTool(cfg) if cfg.kind ~= premake.STATICLIB then -- Complex builds can fail intermittently, as VS fails to link the -- dependencies. Workaround by explicitly linking siblings. _p(4,'LinkLibraryDependencies="false"') if cfg.flags.NoImportLib then _p(4,'IgnoreImportLibrary="%s"', bool(true)) end 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"', cfg.buildtarget.name) if cfg.kind ~= premake.STATICLIB then _p(4,'LinkIncremental="%s"', iif(premake.config.canincrementallink(cfg) , 2, 1)) end vc200x.additionalLibraryDirectories(cfg) if cfg.kind ~= premake.STATICLIB then 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"', cfg.buildtarget.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 implibdir = cfg.linktarget.abspath -- I can't actually stop the import lib, but I can hide it in the objects directory if cfg.flags.NoImportLib then implibdir = path.join(cfg.objdir, path.getname(implibdir)) end implibdir = project.getrelative(cfg.project, implibdir) _x(4,'ImportLibrary="%s"', path.translate(implibdir)) end _p(4,'TargetMachine="%d"', iif(cfg.architecture == "x64", 17, 1)) end end function vc200x.VCExternalLinkerTool(cfg, toolset) local buildoptions = table.join(toolset.getldflags(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(toolset.getlinks(cfg), " ")) end _x(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.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 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,' 0 then _x(4,'AdditionalManifestFiles="%s"', table.concat(manifests, ";")) end _p(3,'/>') end -- -- Write out the block -- function vc200x.VCMIDLTool_ng(cfg) _p(3,'') end -- -- Write out the resource compiler block. -- function vc200x.VCResourceCompilerTool_ng(cfg) _p(3,' 0 then _x(4,'AdditionalOptions="%s"', table.concat(cfg.resoptions, " ")) end vc200x.preprocessorDefinitions(cfg, table.join(cfg.defines, cfg.resdefines)) vc200x.additionalIncludeDirectories(cfg, table.join(cfg.includedirs, cfg.resincludedirs)) _p(3,'/>') end -- -- Write out the custom build step blocks. -- local function buildstepsblock(name, steps) _p(3,' 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,' 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,' 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,'') end -- -- Write out the list of project references. -- function vc200x.projectReferences(prj) 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)) _p(2,'') end end 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", } else return { "VCPreBuildEventTool", "VCCustomBuildTool", "VCXMLDataGeneratorTool", "VCWebServiceProxyGeneratorTool", "VCMIDLTool", "VCCLCompilerTool", "VCManagedResourceCompilerTool", "VCResourceCompilerTool", "VCPreLinkEventTool", "VCLinkerTool", "VCALinkTool", "VCManifestTool", "VCXDCMakeTool", "VCBscMakeTool", "VCFxCopTool", "VCAppVerifierTool", "VCPostBuildEventTool" } end 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 } -- -- Map target systems to their default toolset. If no mapping is -- listed, the built-in Visual Studio tools will be used -- vc200x.toolsets = { ps3 = premake.tools.snc } -- -- Write out the source file tree. -- function vc200x.files_ng(prj) local tr = project.getsourcetree(prj) tree.traverse(tr, { -- folders, virtual or otherwise, are handled at the internal nodes onbranchenter = function(node, depth) _p(depth, '') end, onbranchexit = function(node, depth) _p(depth, '') end, -- source files are handled at the leaves onleaf = function(node, depth) _p(depth, '') vc200x.fileConfiguration(prj, node, depth + 1) _p(depth, '') end }, false, 2) end -- -- Write out the element for a specific file. -- function vc200x.fileConfiguration(prj, node, depth) -- check to see if this is a C file in a C++ project, or vice versa, -- that needs to be built with a different compiler local compileAs if path.iscfile(node.name) ~= premake.project.iscproject(prj) then if path.iscppfile(node.name) then compileAs = iif(prj.language == premake.CPP, "C++", "C") end end -- see if this file needs a modified object file name local objectname if path.iscppfile(node.name) then objectname = project.getfileobject(prj, node.abspath) if objectname == path.getbasename(node.abspath) then objectname = nil end end for cfg in project.eachconfig(prj) do -- get any settings specific to this file for this configuration; -- if nil this file is excluded from the configuration entirely local filecfg = config.getfileconfig(cfg, node.abspath) -- if there is a file configuration, see if it contains any values -- (will be empty if it matches the project config) local hasSettings = (filecfg ~= nil and filecfg.terms ~= nil) -- check to see if this is the PCH source file local isPchSource = (cfg.pchsource == node.abspath and not cfg.flags.NoPCH) -- only write the element if we have something to say if compileAs or isPchSource or not filecfg or hasSettings or objectname then _p(depth,'') _p(depth, '') _p(depth, '') end end end -- -- Write out the element, used by the -- various compiler tool variations. -- function vc200x.additionalIncludeDirectories(cfg, includedirs) if #includedirs > 0 then local dirs = project.getrelative(cfg.project, includedirs) _x(4,'AdditionalIncludeDirectories="%s"', path.translate(table.concat(dirs, ";"))) end end -- -- Write out the element, 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 -- -- Write out the ForcedIncludeFiles element, used by both compiler variations. -- function vc200x.forcedIncludeFiles(cfg) if #cfg.forceincludes > 0 then local includes = project.getrelative(cfg.project, cfg.forceincludes) _x(4,'ForcedIncludeFiles="%s"', table.concat(includes, ';')) end end -- -- Returns the correct name for the linker tool element, based on -- the configuration target system. -- function vc200x.linkertool(cfg) if cfg.kind == premake.STATICLIB then return "VCLibrarianTool" elseif cfg.system == premake.XBOX360 then return "VCX360LinkerTool" else return "VCLinkerTool" 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, "all", "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 -- -- Output the list of preprocessor symbols. -- function vc200x.preprocessorDefinitions(cfg, defines) if #defines > 0 then _x(4,'PreprocessorDefinitions="%s"', table.concat(defines, ";")) end end -- -- Output the program database filename. -- function vc200x.programDatabase(cfg) local target = cfg.buildtarget _x(4,'ProgramDataBaseFileName="$(OutDir)\\%s%s.pdb"', target.prefix, target.basename) 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 -- -- 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 -- -- Identify the toolset to use for a given configuration. Returns nil to -- use the built-in Visual Studio compiler, or a toolset interface to -- use the alternate external compiler setup. -- function vc200x.toolset(cfg) return premake.tools[cfg.toolset] or vc200x.toolsets[cfg.system] end -- -- Convert Premake warning flags to Visual Studio equivalents. -- function vc200x.warnings(cfg) -- if NoWarnings flags specified just disable warnings, and return. if cfg.flags.NoWarnings then _p(4,'WarningLevel="0"') return end -- else setup all warning blocks as needed. _p(4,'WarningLevel="%d"', 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 end ----------------------------------------------------------------------------- -- Everything below this point is a candidate for deprecation ----------------------------------------------------------------------------- -- -- Write the project file header -- function vc200x.header(element) io.eol = "\r\n" _p('') _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 element. -- function vc200x.Configuration(name, cfg) _p(2,'') end -- -- Write out the 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, '') end, onbranchexit = function(node, depth) _p(depth, '') end, -- source files are handled at the leaves onleaf = function(node, depth) local fname = node.cfg.name _p(depth, '') 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, '') _p(depth, '\t') _p(depth, '') end end end depth = depth - 1 _p(depth, '') end, }, false, 2) end -- -- Write out the element, listing each architecture used -- by the project's configurations. -- function vc200x.Platforms(prj) local used = { } _p(1,'') 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,'') end end _p(1,'') end -- -- Compiler block for Windows and XBox360 platforms. -- function vc200x.VCCLCompilerTool(cfg) _p(3,' 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 vc200x.warnings(cfg) _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,' 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 = cfg.linktarget.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,' "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,' 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 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,' 0 then _x(4,'AdditionalManifestFiles="%s"', table.concat(manifests, ";")) end _p(3,'/>') end -- -- Resource compiler block. -- function vc200x.VCResourceCompilerTool(cfg) _p(3,' 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,'') end -- -- Map project tool blocks to handler functions. Unmapped blocks will output -- an empty 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,'') _p(1,'') end _p(1,'') 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,' 0 then _p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.deploymentoptions), " ")) end _p(3,'/>') elseif block == "VCX360ImageTool" then _p(3,' 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,'') -- End Xbox 360 custom sections -- else _p(3,'') end end _p(2,'') end end _p(1,'') _p(1,'') _p(1,'') _p(1,'') vc200x.Files(prj) _p(1,'') _p(1,'') _p(1,'') _p('') end