123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- --
- -- d/actions/visuald.lua
- -- Generate a VisualD .visualdproj project.
- -- Copyright (c) 2012-2015 Manu Evans and the Premake project
- --
- local p = premake
- local m = p.modules.d
- m.visuald = {}
- require ("vstudio")
- local vstudio = p.vstudio
- local workspace = p.workspace
- local project = p.project
- local config = p.config
- local tree = p.tree
- --
- -- Patch the vstudio actions with D support...
- --
- for k,v in pairs({ "vs2005", "vs2008", "vs2010", "vs2012", "vs2013", "vs2015", "vs2017", "vs2019" }) do
- local vs = p.action.get(v)
- if vs ~= nil then
- table.insert( vs.valid_languages, p.D )
- vs.valid_tools.dc = { "dmd", "gdc", "ldc" }
- p.override(vs, "onProject", function(oldfn, prj)
- oldfn(prj)
- if project.isd(prj) then
- p.generate(prj, ".visualdproj", m.visuald.generate)
- end
- end)
- end
- end
- --
- -- Patch a bunch of other functions
- --
- p.override(project, "isnative", function(oldfn, prj)
- return project.isd(prj) or oldfn(prj)
- end)
- p.override(vstudio, "projectfile", function(oldfn, prj)
- if project.isd(prj) then
- return p.filename(prj, ".visualdproj")
- end
- return oldfn(prj)
- end)
- p.override(vstudio, "tool", function(oldfn, prj)
- if project.isd(prj) then
- return "002A2DE9-8BB6-484D-9802-7E4AD4084715"
- end
- return oldfn(prj)
- end)
- --
- -- Generate a Visual D project.
- --
- m.elements.project = function(prj)
- return {
- m.visuald.header,
- m.visuald.globals,
- m.visuald.projectConfigurations,
- m.visuald.files,
- }
- end
- function m.visuald.generate(prj)
- p.eol("\r\n")
- p.indent(" ")
- p.callArray(m.elements.project, prj)
- _p('</DProject>')
- end
- function m.visuald.header(prj)
- -- for some reason Visual D projects don't seem to have an xml header
- --_p('<?xml version="1.0" encoding="utf-8"?>')
- _p('<DProject>')
- end
- function m.visuald.globals(prj)
- _p(1,'<ProjectGuid>{%s}</ProjectGuid>', prj.uuid)
- end
- --
- -- Write out the list of project configurations, which pairs build
- -- configurations with architectures.
- --
- function m.visuald.projectConfigurations(prj)
- -- build a list of all architectures used in this project
- for cfg in project.eachconfig(prj) do
- local prjPlatform = p.esc(vstudio.projectPlatform(cfg))
- local slnPlatform = vstudio.solutionPlatform(cfg)
- local is64bit = slnPlatform == "x64" -- TODO: this seems like a hack
- _p(1,'<Config name="%s" platform="%s">', prjPlatform, slnPlatform)
- _p(2,'<obj>0</obj>')
- _p(2,'<link>0</link>')
- local isWindows = false
- local isDebug = string.find(cfg.buildcfg, 'Debug') ~= nil
- local isOptimised = config.isOptimizedBuild(cfg)
- if cfg.kind == p.CONSOLEAPP then
- _p(2,'<lib>0</lib>')
- _p(2,'<subsystem>1</subsystem>')
- elseif cfg.kind == p.STATICLIB then
- _p(2,'<lib>1</lib>')
- _p(2,'<subsystem>0</subsystem>')
- elseif cfg.kind == p.SHAREDLIB then
- _p(2,'<lib>2</lib>')
- _p(2,'<subsystem>0</subsystem>') -- SHOULD THIS BE '2' (windows)??
- else
- _p(2,'<lib>0</lib>')
- _p(2,'<subsystem>2</subsystem>')
- isWindows = true
- end
- _p(2,'<multiobj>0</multiobj>')
- _p(2,'<singleFileCompilation>0</singleFileCompilation>')
- _p(2,'<oneobj>0</oneobj>')
- _p(2,'<trace>%s</trace>', iif(cfg.flags.Profile, '1', '0'))
- _p(2,'<quiet>%s</quiet>', iif(cfg.flags.Quiet, '1', '0'))
- _p(2,'<verbose>%s</verbose>', iif(cfg.flags.Verbose, '1', '0'))
- _p(2,'<vtls>0</vtls>')
- _p(2,'<symdebug>%s</symdebug>', iif(cfg.symbols == p.ON or cfg.symbols == "FastLink" or cfg.symbols == "Full", iif(cfg.flags.SymbolsLikeC, '2', '1'), '0'))
- _p(2,'<optimize>%s</optimize>', iif(isOptimised, '1', '0'))
- _p(2,'<cpu>0</cpu>')
- _p(2,'<isX86_64>%s</isX86_64>', iif(is64bit, '1', '0'))
- _p(2,'<isLinux>0</isLinux>')
- _p(2,'<isOSX>0</isOSX>')
- _p(2,'<isWindows>%s</isWindows>', iif(isWindows, '1', '0'))
- _p(2,'<isFreeBSD>0</isFreeBSD>')
- _p(2,'<isSolaris>0</isSolaris>')
- _p(2,'<scheduler>0</scheduler>')
- _p(2,'<useDeprecated>%s</useDeprecated>', iif(cfg.deprecatedfeatures == "Allow", '1', '0'))
- _p(2,'<errDeprecated>0</errDeprecated>')
- _p(2,'<useAssert>0</useAssert>')
- _p(2,'<useInvariants>0</useInvariants>')
- _p(2,'<useIn>0</useIn>')
- _p(2,'<useOut>0</useOut>')
- _p(2,'<useArrayBounds>0</useArrayBounds>')
- _p(2,'<noboundscheck>%s</noboundscheck>', iif(cfg.boundscheck == "Off", '1', '0'))
- _p(2,'<useSwitchError>0</useSwitchError>')
- _p(2,'<useUnitTests>%s</useUnitTests>', iif(cfg.flags.UnitTest, '1', '0'))
- _p(2,'<useInline>%s</useInline>', iif(cfg.flags.Inline or isOptimised, '1', '0'))
- _p(2,'<release>%s</release>', iif(cfg.flags.Release or not isDebug, '1', '0'))
- _p(2,'<preservePaths>0</preservePaths>')
- _p(2,'<warnings>%s</warnings>', iif(cfg.flags.FatalCompileWarnings, '1', '0'))
- _p(2,'<infowarnings>%s</infowarnings>', iif(cfg.warnings and cfg.warnings ~= "Off", '1', '0'))
- _p(2,'<checkProperty>0</checkProperty>')
- _p(2,'<genStackFrame>0</genStackFrame>')
- _p(2,'<pic>%s</pic>', iif(cfg.pic == "On", '1', '0'))
- _p(2,'<cov>%s</cov>', iif(cfg.flags.CodeCoverage, '1', '0'))
- _p(2,'<nofloat>%s</nofloat>', iif(cfg.floatingpoint and cfg.floatingpoint == "None", '1', '0'))
- _p(2,'<Dversion>2</Dversion>')
- _p(2,'<ignoreUnsupportedPragmas>0</ignoreUnsupportedPragmas>')
- local compiler = { dmd="0", gdc="1", ldc="2" }
- local compilerName, err = p.api.checkValue(p.fields.toolset, _OPTIONS.dc or cfg.toolset or "dmd")
- if err then
- error { msg=err }
- end
- m.visuald.element(2, "compiler", compiler[compilerName])
- m.visuald.element(2, "otherDMD", '0')
- m.visuald.element(2, "program", '$(DMDInstallDir)windows\\bin\\dmd.exe')
- local impdirs
- if #cfg.importdirs > 0 then
- impdirs = vstudio.path(cfg, cfg.importdirs)
- end
- m.visuald.element(2, "imppath", impdirs)
- m.visuald.element(2, "fileImppath")
- m.visuald.element(2, "outdir", path.translate(project.getrelative(cfg.project, cfg.buildtarget.directory)))
- m.visuald.element(2, "objdir", path.translate(project.getrelative(cfg.project, cfg.objdir)))
- m.visuald.element(2, "objname")
- m.visuald.element(2, "libname")
- m.visuald.element(2, "doDocComments", iif(cfg.flags.Documentation, '1', '0'))
- m.visuald.element(2, "docdir", cfg.docdir)
- m.visuald.element(2, "docname", cfg.docname)
- m.visuald.element(2, "modules_ddoc")
- m.visuald.element(2, "ddocfiles")
- m.visuald.element(2, "doHdrGeneration", iif(cfg.flags.GenerateHeader, '1', '0'))
- m.visuald.element(2, "hdrdir", cfg.headerdir)
- m.visuald.element(2, "hdrname", cfg.headername)
- m.visuald.element(2, "doXGeneration", iif(cfg.flags.GenerateJSON, '1', '0'))
- m.visuald.element(2, "xfilename", '$(IntDir)\\$(TargetName).json')
- m.visuald.element(2, "debuglevel", iif(cfg.debuglevel, tostring(cfg.debuglevel), '0'))
- m.visuald.element(2, "debugids", cfg.debugconstants)
- m.visuald.element(2, "versionlevel", iif(cfg.versionlevel, tostring(cfg.versionlevel), '0'))
- m.visuald.element(2, "versionids", cfg.versionconstants)
- _p(2,'<dump_source>0</dump_source>')
- _p(2,'<mapverbosity>0</mapverbosity>')
- _p(2,'<createImplib>%s</createImplib>', iif(cfg.kind ~= p.SHAREDLIB or cfg.flags.NoImportLib, '0', '1'))
- _p(2,'<defaultlibname />')
- _p(2,'<debuglibname />')
- _p(2,'<moduleDepsFile />')
- _p(2,'<run>0</run>')
- _p(2,'<runargs />')
- -- _p(2,'<runCv2pdb>%s</runCv2pdb>', iif(cfg.symbols == p.ON, '1', '0'))
- _p(2,'<runCv2pdb>1</runCv2pdb>') -- we will just leave this always enabled, since it's ignored if no debuginfo is written
- _p(2,'<pathCv2pdb>$(VisualDInstallDir)cv2pdb\\cv2pdb.exe</pathCv2pdb>')
- _p(2,'<cv2pdbPre2043>0</cv2pdbPre2043>')
- _p(2,'<cv2pdbNoDemangle>0</cv2pdbNoDemangle>')
- _p(2,'<cv2pdbEnumType>0</cv2pdbEnumType>')
- _p(2,'<cv2pdbOptions />')
- _p(2,'<objfiles />')
- _p(2,'<linkswitches />')
- local links
- local explicit = vstudio.needsExplicitLink(cfg)
- -- check to see if this project uses an external toolset. If so, let the
- -- toolset define the format of the links
- local toolset = config.toolset(cfg)
- if toolset then
- links = toolset.getlinks(cfg, not explicit)
- else
- local scope = iif(explicit, "all", "system")
- links = config.getlinks(cfg, scope, "fullpath")
- end
- m.visuald.element(2, "libfiles", table.concat(links, " "))
- m.visuald.element(2, "libpaths", cfg.libdirs)
- _p(2,'<deffile />')
- _p(2,'<resfile />')
- local target = config.gettargetinfo(cfg)
- _p(2,'<exefile>$(OutDir)\\%s</exefile>', target.name)
- _p(2,'<useStdLibPath>1</useStdLibPath>')
- local runtime = 0
- if not cfg.flags.OmitDefaultLibrary then
- if config.isDebugBuild(cfg) then
- runtime = iif(cfg.flags.StaticRuntime, "2", "4")
- else
- runtime = iif(cfg.flags.StaticRuntime, "1", "3")
- end
- end
- m.visuald.element(2, "cRuntime", runtime)
- local additionalOptions
- if #cfg.buildoptions > 0 then
- additionalOptions = table.concat(cfg.buildoptions, " ")
- end
- if #cfg.linkoptions > 0 then
- local linkOpts = table.implode(cfg.linkoptions, "-L", "", " ")
- if additionalOptions then
- additionalOptions = additionalOptions .. " " .. linkOpts
- else
- additionalOptions = linkOpts
- end
- end
- m.visuald.element(2, "additionalOptions", additionalOptions)
- if #cfg.prebuildcommands > 0 then
- _p(2,'<preBuildCommand>%s</preBuildCommand>',p.esc(table.implode(cfg.prebuildcommands, "", "", "\r\n")))
- else
- _p(2,'<preBuildCommand />')
- end
- if #cfg.postbuildcommands > 0 then
- _p(2,'<postBuildCommand>%s</postBuildCommand>',p.esc(table.implode(cfg.postbuildcommands, "", "", "\r\n")))
- else
- _p(2,'<postBuildCommand />')
- end
- _p(2,'<filesToClean>*.obj;*.cmd;*.build;*.json;*.dep;*.o</filesToClean>')
- _p(1,'</Config>')
- end
- end
- --
- -- Write out the source file tree.
- --
- function m.visuald.files(prj)
- _p(1,'<Folder name="%s">', prj.name)
- local tr = project.getsourcetree(prj)
- tree.traverse(tr, {
- -- folders, virtual or otherwise, are handled at the internal nodes
- onbranchenter = function(node, depth)
- _p(depth, '<Folder name="%s">', node.name)
- end,
- onbranchexit = function(node, depth)
- _p(depth, '</Folder>')
- end,
- -- source files are handled at the leaves
- onleaf = function(node, depth)
- _p(depth, '<File path="%s" />', path.translate(node.relpath))
- -- _p(depth, '<File path="%s">', path.translate(node.relpath))
- -- m.visuald.fileConfiguration(prj, node, depth + 1)
- -- _p(depth, '</File>')
- end
- }, false, 2)
- _p(1,'</Folder>')
- end
- function m.visuald.fileConfiguration(prj, node, depth)
- -- maybe we'll need this in the future...
- end
- --
- -- Output an individual project XML element.
- --
- function m.visuald.element(depth, name, value, ...)
- local isTable = type(value) == "table"
- if not value or (isTable and #value == 0) then
- _p(depth, '<%s />', name)
- else
- if isTable then
- value = p.esc(table.implode(value, "", "", ";"))
- _p(depth, '<%s>%s</%s>', name, value, name)
- else
- if select('#',...) == 0 then
- value = p.esc(value)
- end
- _x(depth, string.format('<%s>%s</%s>', name, value, name), ...)
- end
- end
- end
|