123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- --
- -- vs2005_solution.lua
- -- Generate a Visual Studio 2005+ solution.
- -- Copyright (c) Jason Perkins and the Premake project
- --
- local p = premake
- p.vstudio.sln2005 = {}
- local vstudio = p.vstudio
- local sln2005 = p.vstudio.sln2005
- local project = p.project
- local tree = p.tree
- ---
- -- Add namespace for element definition lists for p.callArray()
- ---
- sln2005.elements = {}
- --
- -- Return the list of sections contained in the solution.
- -- TODO: Get rid of this when the MonoDevelop module no longer needs it
- --
- function sln2005.solutionSections(wks)
- return {
- "ConfigurationPlatforms",
- "SolutionProperties",
- "NestedProjects",
- "ExtensibilityGlobals"
- }
- end
- --
- -- Generate a Visual Studio 200x solution, with support for the new platforms API.
- --
- function sln2005.generate(wks)
- -- Mark the file as Unicode
- p.utf8()
- p.outln('')
- sln2005.reorderProjects(wks)
- sln2005.header()
- sln2005.projects(wks)
- p.push('Global')
- sln2005.sections(wks)
- p.pop('EndGlobal')
- p.w()
- end
- --
- -- Generate the solution header. Each Visual Studio action definition
- -- should include its own version.
- --
- function sln2005.header()
- local action = p.action.current()
- p.w('Microsoft Visual Studio Solution File, Format Version %d.00', action.vstudio.solutionVersion)
- p.w('# Visual Studio %s', action.vstudio.versionName)
- end
- --
- -- If a startup project is specified, move it (and any enclosing groups)
- -- to the front of the project list. This will make Visual Studio treat
- -- it like a startup project.
- --
- -- I force the new ordering into the tree so that it will get applied to
- -- all sections of the solution; otherwise the first change to the solution
- -- in the IDE will cause the orderings to get rewritten.
- --
- function sln2005.reorderProjects(wks)
- if wks.startproject then
- local np
- local tr = p.workspace.grouptree(wks)
- tree.traverse(tr, {
- onleaf = function(n)
- if n.project.name == wks.startproject then
- np = n
- end
- end
- })
- while np and np.parent do
- local p = np.parent
- local i = table.indexof(p.children, np)
- table.remove(p.children, i)
- table.insert(p.children, 1, np)
- np = p
- end
- end
- end
- --
- -- Build a relative path from the solution file to the project file
- --
- function sln2005.buildRelativePath(prj)
- local prjpath = vstudio.projectfile(prj)
- prjpath = vstudio.path(prj.workspace, prjpath)
- -- Unlike projects, solutions must use old-school %...% DOS style
- -- for environment variables.
- return prjpath:gsub("$%((.-)%)", "%%%1%%")
- end
- --
- -- Write out the list of projects and groups contained by the solution.
- --
- function sln2005.projects(wks)
- local tr = p.workspace.grouptree(wks)
- tree.traverse(tr, {
- onleaf = function(n)
- local prj = n.project
- p.x('Project("{%s}") = "%s", "%s", "{%s}"', vstudio.tool(prj), prj.name, sln2005.buildRelativePath(prj), prj.uuid)
- p.push()
- sln2005.projectdependencies(prj)
- p.pop('EndProject')
- end,
- onbranch = function(n)
- p.push('Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "%s", "%s", "{%s}"', n.name, n.name, n.uuid)
- p.pop('EndProject')
- end,
- })
- end
- --
- -- Write out the list of project dependencies for a particular project.
- --
- function sln2005.projectdependencies(prj)
- local deps = project.getdependencies(prj, 'dependOnly')
- if #deps > 0 then
- p.push('ProjectSection(ProjectDependencies) = postProject')
- for _, dep in ipairs(deps) do
- p.w('{%s} = {%s}', dep.uuid, dep.uuid)
- end
- p.pop('EndProjectSection')
- end
- end
- --
- -- Write out the list of shared project files and their links
- --
- function sln2005.sharedProjects(wks)
- local contents = p.capture(function ()
- local tr = p.workspace.grouptree(wks)
- p.tree.traverse(tr, {
- onleaf = function(n)
- local prj = n.project
- -- SharedItems projects reference their own UUID with a "9"
- -- SharedItems projects reference the UUID of projects that link them with a "4"
- if prj.kind == p.SHAREDITEMS then
- p.w('%s*{%s}*SharedItemsImports = %s', sln2005.buildRelativePath(prj), prj.uuid:lower(), "9")
- else
- local deps = p.project.getdependencies(prj, 'linkOnly')
- for _, dep in ipairs(deps) do
- if dep.kind == p.SHAREDITEMS then
- p.w('%s*{%s}*SharedItemsImports = %s', sln2005.buildRelativePath(dep), prj.uuid:lower(), "4")
- end
- end
- end
- end,
- })
- end)
- if #contents > 0 then
- p.push('GlobalSection(SharedMSBuildProjectFiles) = preSolution')
- p.outln(contents)
- p.pop('EndGlobalSection')
- end
- end
- --
- -- Write out the list of project configuration platforms.
- --
- sln2005.elements.projectConfigurationPlatforms = function(cfg, context)
- return {
- sln2005.activeCfg,
- sln2005.build0,
- }
- end
- function sln2005.projectConfigurationPlatforms(wks, sorted, descriptors)
- p.w("GlobalSection(ProjectConfigurationPlatforms) = postSolution")
- local tr = p.workspace.grouptree(wks)
- tree.traverse(tr, {
- onleaf = function(n)
- local prj = n.project
- -- SharedItems projects don't have any configuration platform entries
- if prj.kind == p.SHAREDITEMS then
- return
- end
- table.foreachi(sorted, function(cfg)
- local context = {}
- -- Look up the matching project configuration. If none exist, this
- -- configuration has been excluded from the project, and should map
- -- to closest available project configuration instead.
- context.prj = prj
- context.prjCfg = project.getconfig(prj, cfg.buildcfg, cfg.platform)
- context.excluded = (context.prjCfg == nil or context.prjCfg.flags.ExcludeFromBuild)
- if context.prjCfg == nil then
- context.prjCfg = project.findClosestMatch(prj, cfg.buildcfg, cfg.platform)
- end
- context.descriptor = descriptors[cfg]
- context.platform = vstudio.projectPlatform(context.prjCfg)
- context.architecture = vstudio.archFromConfig(context.prjCfg, true)
- p.push()
- p.callArray(sln2005.elements.projectConfigurationPlatforms, cfg, context)
- p.pop()
- end)
- end
- })
- p.w("EndGlobalSection")
- end
- function sln2005.activeCfg(cfg, context)
- p.w('{%s}.%s.ActiveCfg = %s|%s', context.prj.uuid, context.descriptor, context.platform, context.architecture)
- end
- function sln2005.build0(cfg, context)
- if not context.excluded and context.prjCfg.kind ~= p.NONE then
- p.w('{%s}.%s.Build.0 = %s|%s', context.prj.uuid, context.descriptor, context.platform, context.architecture)
- end
- end
- --
- -- Write out the tables that map solution configurations to project configurations.
- --
- function sln2005.configurationPlatforms(wks)
- local descriptors = {}
- local sorted = {}
- for cfg in p.workspace.eachconfig(wks) do
- -- Create a Visual Studio solution descriptor (i.e. Debug|Win32) for
- -- this solution configuration. I need to use it in a few different places
- -- below so it makes sense to precompute it up front.
- local platform = vstudio.solutionPlatform(cfg)
- descriptors[cfg] = string.format("%s|%s", cfg.buildcfg, platform)
- -- Also add the configuration to an indexed table which I can sort below
- table.insert(sorted, cfg)
- end
- -- Sort the solution configurations to match Visual Studio's preferred
- -- order, which appears to be a simple alpha sort on the descriptors.
- table.sort(sorted, function(cfg0, cfg1)
- return descriptors[cfg0]:lower() < descriptors[cfg1]:lower()
- end)
- -- Now I can output the sorted list of solution configuration descriptors
- -- Visual Studio assumes the first configurations as the defaults.
- if wks.defaultplatform then
- p.push('GlobalSection(SolutionConfigurationPlatforms) = preSolution')
- table.foreachi(sorted, function (cfg)
- if cfg.platform == wks.defaultplatform then
- p.w('%s = %s', descriptors[cfg], descriptors[cfg])
- end
- end)
- p.pop("EndGlobalSection")
- end
- p.push('GlobalSection(SolutionConfigurationPlatforms) = preSolution')
- table.foreachi(sorted, function (cfg)
- if not wks.defaultplatform or cfg.platform ~= wks.defaultplatform then
- p.w('%s = %s', descriptors[cfg], descriptors[cfg])
- end
- end)
- p.pop("EndGlobalSection")
- -- For each project in the solution...
- sln2005.projectConfigurationPlatforms(wks, sorted, descriptors)
- end
- --
- -- Write out contents of the SolutionProperties section; currently unused.
- --
- function sln2005.properties(wks)
- p.push('GlobalSection(SolutionProperties) = preSolution')
- p.w('HideSolutionNode = FALSE')
- p.pop('EndGlobalSection')
- end
- --
- -- Write out the NestedProjects block, which describes the structure of
- -- any solution groups.
- --
- function sln2005.nestedProjects(wks)
- local tr = p.workspace.grouptree(wks)
- if tree.hasbranches(tr) then
- p.push('GlobalSection(NestedProjects) = preSolution')
- tree.traverse(tr, {
- onnode = function(n)
- if n.parent.uuid then
- p.w('{%s} = {%s}', (n.project or n).uuid, n.parent.uuid)
- end
- end
- })
- p.pop('EndGlobalSection')
- end
- end
- --
- -- Write out the ExtensibilityGlobals block, which embeds some data for the
- -- Visual Studio PremakeExtension.
- --
- function sln2005.premakeExtensibilityGlobals(wks)
- if wks.editorintegration then
- -- we need to filter out the 'file' argument, since we already output
- -- the script separately.
- local args = {}
- for _, arg in ipairs(_ARGV) do
- if not (arg:startswith("--file") or arg:startswith("/file")) then
- table.insert(args, arg);
- end
- end
- p.w('PremakeBinary = %s', _PREMAKE_COMMAND)
- p.w('PremakeScript = %s', p.workspace.getrelative(wks, _MAIN_SCRIPT))
- p.w('PremakeArguments = %s', table.concat(args, ' '))
- end
- end
- --
- -- Map ExtensibilityGlobals to output functions.
- --
- sln2005.elements.extensibilityGlobals = function(wks)
- return {
- sln2005.premakeExtensibilityGlobals,
- }
- end
- --
- -- Output the ExtensibilityGlobals section.
- --
- function sln2005.extensibilityGlobals(wks)
- local contents = p.capture(function ()
- p.push()
- p.callArray(sln2005.elements.extensibilityGlobals, wks)
- p.pop()
- end)
- if #contents > 0 then
- p.push('GlobalSection(ExtensibilityGlobals) = postSolution')
- p.outln(contents)
- p.pop('EndGlobalSection')
- end
- end
- --
- -- Map solution sections to output functions. Tools that aren't listed will
- -- be ignored.
- --
- sln2005.elements.sections = function(wks)
- return {
- sln2005.sharedProjects,
- sln2005.configurationPlatforms,
- sln2005.properties,
- sln2005.nestedProjects,
- sln2005.extensibilityGlobals,
- }
- end
- --
- -- Write out all of the workspace sections.
- --
- function sln2005.sections(wks)
- p.callArray(sln2005.elements.sections, wks)
- end
|