-- -- 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('') end function m.visuald.header(prj) -- for some reason Visual D projects don't seem to have an xml header --_p('') _p('') end function m.visuald.globals(prj) _p(1,'{%s}', 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,'', prjPlatform, slnPlatform) _p(2,'0') _p(2,'0') local isWindows = false local isDebug = string.find(cfg.buildcfg, 'Debug') ~= nil local isOptimised = config.isOptimizedBuild(cfg) if cfg.kind == p.CONSOLEAPP then _p(2,'0') _p(2,'1') elseif cfg.kind == p.STATICLIB then _p(2,'1') _p(2,'0') elseif cfg.kind == p.SHAREDLIB then _p(2,'2') _p(2,'0') -- SHOULD THIS BE '2' (windows)?? else _p(2,'0') _p(2,'2') isWindows = true end _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'%s', iif(cfg.flags.Profile, '1', '0')) _p(2,'%s', iif(cfg.flags.Quiet, '1', '0')) _p(2,'%s', iif(cfg.flags.Verbose, '1', '0')) _p(2,'0') _p(2,'%s', iif(cfg.symbols == p.ON or cfg.symbols == "FastLink" or cfg.symbols == "Full", iif(cfg.flags.SymbolsLikeC, '2', '1'), '0')) _p(2,'%s', iif(isOptimised, '1', '0')) _p(2,'0') _p(2,'%s', iif(is64bit, '1', '0')) _p(2,'0') _p(2,'0') _p(2,'%s', iif(isWindows, '1', '0')) _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'%s', iif(cfg.deprecatedfeatures == "Allow", '1', '0')) _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'%s', iif(cfg.boundscheck == "Off", '1', '0')) _p(2,'0') _p(2,'%s', iif(cfg.flags.UnitTest, '1', '0')) _p(2,'%s', iif(cfg.flags.Inline or isOptimised, '1', '0')) _p(2,'%s', iif(cfg.flags.Release or not isDebug, '1', '0')) _p(2,'0') _p(2,'%s', iif(cfg.flags.FatalCompileWarnings, '1', '0')) _p(2,'%s', iif(cfg.warnings and cfg.warnings ~= "Off", '1', '0')) _p(2,'0') _p(2,'0') _p(2,'%s', iif(cfg.pic == "On", '1', '0')) _p(2,'%s', iif(cfg.flags.CodeCoverage, '1', '0')) _p(2,'%s', iif(cfg.floatingpoint and cfg.floatingpoint == "None", '1', '0')) _p(2,'2') _p(2,'0') 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,'0') _p(2,'0') _p(2,'%s', iif(cfg.kind ~= p.SHAREDLIB or cfg.flags.NoImportLib, '0', '1')) _p(2,'') _p(2,'') _p(2,'') _p(2,'0') _p(2,'') -- _p(2,'%s', iif(cfg.symbols == p.ON, '1', '0')) _p(2,'1') -- we will just leave this always enabled, since it's ignored if no debuginfo is written _p(2,'$(VisualDInstallDir)cv2pdb\\cv2pdb.exe') _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'') _p(2,'') _p(2,'') 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,'') _p(2,'') local target = config.gettargetinfo(cfg) _p(2,'$(OutDir)\\%s', target.name) _p(2,'1') 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,'%s',p.esc(table.implode(cfg.prebuildcommands, "", "", "\r\n"))) else _p(2,'') end if #cfg.postbuildcommands > 0 then _p(2,'%s',p.esc(table.implode(cfg.postbuildcommands, "", "", "\r\n"))) else _p(2,'') end _p(2,'*.obj;*.cmd;*.build;*.json;*.dep;*.o') _p(1,'') end end -- -- Write out the source file tree. -- function m.visuald.files(prj) _p(1,'', 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, '', node.name) end, onbranchexit = function(node, depth) _p(depth, '') end, -- source files are handled at the leaves onleaf = function(node, depth) _p(depth, '', path.translate(node.relpath)) -- _p(depth, '', path.translate(node.relpath)) -- m.visuald.fileConfiguration(prj, node, depth + 1) -- _p(depth, '') end }, false, 2) _p(1,'') 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', name, value, name) else if select('#',...) == 0 then value = p.esc(value) end _x(depth, string.format('<%s>%s', name, value, name), ...) end end end