-- -- 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,'', 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', 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