vcxproj.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. --
  2. -- d/actions/vcxproj.lua
  3. -- Generate a VisualD .visualdproj project.
  4. -- Copyright (c) 2012-2015 Manu Evans and the Premake project
  5. --
  6. local p = premake
  7. require ("vstudio")
  8. p.modules.d.vc2010 = {}
  9. local vc2010 = p.vstudio.vc2010
  10. local m = p.modules.d.vc2010
  11. m.elements = {}
  12. local vstudio = p.vstudio
  13. local vc2010 = p.vstudio.vc2010
  14. local config = p.config
  15. --
  16. -- Patch DCompiler into the configuration properties
  17. --
  18. p.override(vc2010.elements, "configurationProperties", function(oldfn, cfg)
  19. local items = oldfn(cfg)
  20. if cfg.kind ~= p.UTILITY then
  21. table.insert(items, m.dCompiler)
  22. end
  23. return items
  24. end)
  25. function m.dCompiler(cfg)
  26. local dc = nil
  27. -- TODO: chech for explicit DMD or LDC request?
  28. if _OPTIONS.dc then
  29. local dcMap = {
  30. ["dmd"] = "DMD",
  31. ["ldc"] = "LDC",
  32. }
  33. dc = dcMap[_OPTIONS.dc]
  34. end
  35. if cfg.flags.UseLDC then
  36. dc = "LDC"
  37. end
  38. -- TODO: dunno how to use `toolset`, since it's also used by the C++ compiler :/
  39. -- local tool, version = p.config.toolset(cfg)
  40. -- if not version then
  41. -- local value = p.action.current().toolset
  42. -- tool, version = p.tools.canonical(value)
  43. -- end
  44. if dc then
  45. if cfg.kind == p.NONE or cfg.kind == p.MAKEFILE then
  46. if p.config.hasFile(cfg, path.isdfile) or _ACTION >= "vs2015" then
  47. vc2010.element("DCompiler", nil, dc)
  48. end
  49. else
  50. vc2010.element("DCompiler", nil, dc)
  51. end
  52. end
  53. end
  54. --
  55. -- Patch the dCompile step into the project items
  56. --
  57. p.override(vc2010.elements, "itemDefinitionGroup", function(oldfn, cfg)
  58. local items = oldfn(cfg)
  59. if cfg.kind ~= p.UTILITY then
  60. table.insertafter(items, vc2010.clCompile, m.dCompile)
  61. end
  62. return items
  63. end)
  64. --
  65. -- Write the <DCompile> settings block.
  66. --
  67. m.elements.dCompile = function(cfg)
  68. return {
  69. m.dOptimization,
  70. m.dImportPaths,
  71. m.dStringImportPaths,
  72. m.dVersionConstants,
  73. m.dDebugConstants,
  74. m.dCompilationModel,
  75. m.dPreserveSourcePath,
  76. m.dRuntime,
  77. m.dCodeGeneration,
  78. m.dLanguage,
  79. m.dMessages,
  80. m.dDocumentation,
  81. m.dAdditionalCompileOptions,
  82. }
  83. end
  84. function m.dCompile(cfg)
  85. if config.hasFile(cfg, path.isdfile) then
  86. p.push('<DCompile>')
  87. p.callArray(m.elements.dCompile, cfg)
  88. p.pop('</DCompile>')
  89. end
  90. end
  91. ---
  92. -- DCompile group
  93. ---
  94. vc2010.categories.DCompile = {
  95. name = "DCompile",
  96. extensions = { ".d" },
  97. priority = 3,
  98. emitFiles = function(prj, group)
  99. local fileCfgFunc = function(fcfg, condition)
  100. if fcfg then
  101. return {
  102. vc2010.excludedFromBuild,
  103. m.dOptimization,
  104. m.dImportPaths,
  105. m.dStringImportPaths,
  106. m.dVersionConstants,
  107. m.dDebugConstants,
  108. m.dCompilationModel,
  109. m.dPreserveSourcePath,
  110. m.dRuntime,
  111. m.dCodeGeneration,
  112. m.dLanguage,
  113. m.dMessages,
  114. m.dDocumentation,
  115. m.dAdditionalCompileOptions,
  116. }
  117. else
  118. return {
  119. vc2010.excludedFromBuild
  120. }
  121. end
  122. end
  123. vc2010.emitFiles(prj, group, "DCompile", {m.generatedFile}, fileCfgFunc)
  124. end,
  125. emitFilter = function(prj, group)
  126. vc2010.filterGroup(prj, group, "DCompile")
  127. end
  128. }
  129. function m.dOptimization(cfg, condition)
  130. local map = { Off="false", On="true", Debug="false", Full="true", Size="true", Speed="true" }
  131. if cfg.optimize then
  132. vc2010.element('Optimizer', condition, map[cfg.optimize] or "false")
  133. end
  134. end
  135. function m.dImportPaths(cfg, condition)
  136. if cfg.importdirs and #cfg.importdirs > 0 then
  137. local dirs = vstudio.path(cfg, cfg.importdirs)
  138. if #dirs > 0 then
  139. vc2010.element("ImportPaths", condition, "%s;%%(ImportPaths)", table.concat(dirs, ";"))
  140. end
  141. end
  142. end
  143. function m.dStringImportPaths(cfg, condition)
  144. if cfg.stringimportdirs and #cfg.stringimportdirs > 0 then
  145. local dirs = vstudio.path(cfg, cfg.stringimportdirs)
  146. if #dirs > 0 then
  147. vc2010.element("StringImportPaths", condition, "%s;%%(StringImportPaths)", table.concat(dirs, ";"))
  148. end
  149. end
  150. end
  151. function m.dVersionConstants(cfg, condition)
  152. if cfg.versionconstants and #cfg.versionconstants > 0 then
  153. local versionconstants = table.concat(cfg.versionconstants, ";")
  154. vc2010.element("VersionIdentifiers", condition, versionconstants)
  155. end
  156. end
  157. function m.dDebugConstants(cfg, condition)
  158. if cfg.debugconstants and #cfg.debugconstants > 0 then
  159. local debugconstants = table.concat(cfg.debugconstants, ";")
  160. vc2010.element("DebugIdentifiers", condition, debugconstants)
  161. end
  162. end
  163. function m.dCompilationModel(cfg, condition)
  164. if cfg.compilationmodel and cfg.compilationmodel ~= "Default" then
  165. vc2010.element("CompilationModel", condition, cfg.compilationmodel)
  166. end
  167. end
  168. function m.dPreserveSourcePath(cfg, condition)
  169. if cfg.flags.RetainPaths then
  170. vc2010.element("PreserveSourcePath", condition, "true")
  171. end
  172. end
  173. function m.dRuntime(cfg, condition)
  174. if cfg.flags.OmitDefaultLibrary then
  175. vc2010.element("CRuntimeLibrary", condition, "None")
  176. else
  177. local releaseruntime = not config.isDebugBuild(cfg)
  178. local staticruntime = true
  179. if cfg.staticruntime == "Off" then
  180. staticruntime = false
  181. end
  182. if cfg.runtime == "Debug" then
  183. releaseruntime = false
  184. elseif cfg.runtime == "Release" then
  185. releaseruntime = true
  186. end
  187. if (cfg.staticruntime and cfg.staticruntime ~= "Default") or (cfg.runtime and cfg.runtime ~= "Default") then
  188. if staticruntime == true and releaseruntime == true then
  189. vc2010.element("CRuntimeLibrary", condition, "MultiThreaded")
  190. elseif staticruntime == true and releaseruntime == false then
  191. vc2010.element("CRuntimeLibrary", condition, "MultiThreadedDebug")
  192. elseif staticruntime == false and releaseruntime == true then
  193. vc2010.element("CRuntimeLibrary", condition, "MultiThreadedDll")
  194. elseif staticruntime == false and releaseruntime == false then
  195. vc2010.element("CRuntimeLibrary", condition, "MultiThreadedDebugDll")
  196. end
  197. end
  198. end
  199. end
  200. function m.dCodeGeneration(cfg, condition)
  201. if cfg.buildtarget then
  202. local ObjectFileName = ""
  203. if cfg.buildtarget.basename then
  204. if cfg.buildtarget.prefix then
  205. ObjectFileName = cfg.buildtarget.prefix
  206. end
  207. ObjectFileName = ObjectFileName .. cfg.buildtarget.basename .. ".obj"
  208. end
  209. if cfg.buildtarget.directory then
  210. local outdir = vstudio.path(cfg, cfg.buildtarget.directory)
  211. ObjectFileName = path.join(outdir, ObjectFileName)
  212. end
  213. vc2010.element("ObjectFileName", condition, ObjectFileName)
  214. end
  215. if cfg.flags.Profile then
  216. vc2010.element("Profile", condition, "true")
  217. end
  218. if cfg.flags.ProfileGC then
  219. vc2010.element("ProfileGC", condition, "true")
  220. end
  221. if cfg.flags.CodeCoverage then
  222. vc2010.element("Coverage", condition, "true")
  223. end
  224. if cfg.flags.UnitTest then
  225. vc2010.element("Unittest", condition, "true")
  226. end
  227. if cfg.inlining and cfg.inlining ~= "Default" then
  228. local types = {
  229. Disabled = "false",
  230. Explicit = "true",
  231. Auto = "true",
  232. }
  233. vc2010.element("Inliner", condition, types[cfg.inlining])
  234. end
  235. if cfg.flags.StackFrame then
  236. vc2010.element("StackFrame", condition, "true")
  237. end
  238. if cfg.flags.StackStomp then
  239. vc2010.element("StackStomp", condition, "true")
  240. end
  241. if cfg.flags.AllInstantiate then
  242. vc2010.element("AllInst", condition, "true")
  243. end
  244. if cfg.flags.Main then
  245. vc2010.element("Main", condition, "true")
  246. end
  247. if _OPTIONS.dc ~= "ldc" and not cfg.flags.UseLDC then
  248. if cfg.vectorextensions then
  249. local vextMap = {
  250. AVX = "avx",
  251. AVX2 = "avx2",
  252. }
  253. if vextMap[cfg.vectorextensions] ~= nil then
  254. vc2010.element("CPUArchitecture", condition, vextMap[cfg.vectorextensions])
  255. end
  256. end
  257. end
  258. -- if cfg.debugcode then
  259. -- local types = {
  260. -- DebugFull = "Debug",
  261. -- DebugLight = "Default",
  262. -- Release = "Release",
  263. -- }
  264. -- vc2010.element("DebugCode", condition, types[cfg.debugcode])
  265. -- end
  266. -- TODO: proper option for this? should support unspecified...
  267. if config.isDebugBuild(cfg) then
  268. vc2010.element("DebugCode", condition, "Debug")
  269. else
  270. vc2010.element("DebugCode", condition, "Release")
  271. end
  272. if cfg.symbols then
  273. if cfg.symbols == p.Off then
  274. vc2010.element("DebugInfo", condition, "None")
  275. elseif cfg.symbols ~= "Default" then
  276. vc2010.element("DebugInfo", condition, iif(cfg.flags.SymbolsLikeC, "VS", "Mago"))
  277. end
  278. end
  279. if cfg.boundscheck and cfg.boundscheck ~= "Default" then
  280. local types = {
  281. Off = "Off",
  282. SafeOnly = "SafeOnly",
  283. On = "On",
  284. }
  285. vc2010.element("BoundsCheck", condition, types[cfg.boundscheck])
  286. end
  287. if cfg.flags.PerformSyntaxCheckOnly then
  288. vc2010.element("PerformSyntaxCheckOnly", condition, "true")
  289. end
  290. end
  291. function m.dLanguage(cfg, condition)
  292. if cfg.flags.BetterC then
  293. vc2010.element("BetterC", condition, "true")
  294. end
  295. if #cfg.preview > 0 then
  296. for _, opt in ipairs(cfg.preview) do
  297. if opt == "dip25" then
  298. vc2010.element("DIP25", condition, "true")
  299. elseif opt == "dip1000" then
  300. vc2010.element("DIP1000", condition, "true")
  301. elseif opt == "dip1008" then
  302. vc2010.element("DIP1008", condition, "true")
  303. elseif opt == "fieldwise" then
  304. vc2010.element("PreviewFieldwise", condition, "true")
  305. elseif opt == "dtorfields" then
  306. vc2010.element("PreviewDtorFields", condition, "true")
  307. elseif opt == "intpromote" then
  308. vc2010.element("PreviewIntPromote", condition, "true")
  309. elseif opt == "fixAliasThis" then
  310. vc2010.element("PreviewFixAliasThis", condition, "true")
  311. end
  312. end
  313. end
  314. if #cfg.revert > 0 then
  315. for _, opt in ipairs(cfg.revert) do
  316. if opt == "import" then
  317. vc2010.element("RevertImport", condition, "true")
  318. end
  319. end
  320. end
  321. end
  322. function m.dMessages(cfg, condition)
  323. if cfg.warnings == p.OFF then
  324. vc2010.element("Warnings", condition, "None")
  325. elseif cfg.warnings and cfg.warnings ~= "Default" then
  326. vc2010.element("Warnings", condition, iif(cfg.flags.FatalCompileWarnings, "Error", "Info"))
  327. end
  328. if cfg.deprecatedfeatures and cfg.deprecatedfeatures ~= "Default" then
  329. local types = {
  330. Error = "Error",
  331. Warn = "Info",
  332. Allow = "Allow",
  333. }
  334. vc2010.element("Deprecations", condition, types[cfg.deprecatedfeatures])
  335. end
  336. if cfg.flags.ShowCommandLine then
  337. vc2010.element("ShowCommandLine", condition, "true")
  338. end
  339. if cfg.flags.Verbose then
  340. vc2010.element("Verbose", condition, "true")
  341. end
  342. if cfg.flags.ShowTLS then
  343. vc2010.element("ShowTLS", condition, "true")
  344. end
  345. if cfg.flags.ShowGC then
  346. vc2010.element("ShowGC", condition, "true")
  347. end
  348. if cfg.flags.IgnorePragma then
  349. vc2010.element("IgnorePragma", condition, "true")
  350. end
  351. if cfg.flags.ShowDependencies then
  352. vc2010.element("ShowDependencies", condition, "true")
  353. end
  354. if #cfg.transition > 0 then
  355. for _, opt in ipairs(cfg.transition) do
  356. if opt == "field" then
  357. vc2010.element("TransitionField", condition, "true")
  358. elseif opt == "checkimports" then
  359. vc2010.element("TransitionCheckImports", condition, "true")
  360. elseif opt == "complex" then
  361. vc2010.element("TransitionComplex", condition, "true")
  362. end
  363. end
  364. end
  365. end
  366. function m.dDocumentation(cfg, condition)
  367. if cfg.docdir then
  368. vc2010.element("DocDir", condition, cfg.docdir)
  369. end
  370. if cfg.docname then
  371. vc2010.element("DocFile", condition, cfg.docname)
  372. end
  373. if #cfg.preview > 0 then
  374. for _, opt in ipairs(cfg.preview) do
  375. if opt == "markdown" then
  376. vc2010.element("PreviewMarkdown", condition, "true")
  377. end
  378. end
  379. end
  380. if #cfg.transition > 0 then
  381. for _, opt in ipairs(cfg.transition) do
  382. if opt == "vmarkdown" then
  383. vc2010.element("TransitionVMarkdown", condition, "true")
  384. end
  385. end
  386. end
  387. if cfg.dependenciesfile then
  388. vc2010.element("DepFile", condition, cfg.dependenciesfile)
  389. end
  390. if cfg.headerdir then
  391. vc2010.element("HeaderDir", condition, cfg.headerdir)
  392. end
  393. if cfg.headername then
  394. vc2010.element("HeaderFile", condition, cfg.headername)
  395. end
  396. if cfg.jsonfile then
  397. vc2010.element("JSONFile", condition, cfg.jsonfile)
  398. end
  399. end
  400. function m.dAdditionalCompileOptions(cfg, condition)
  401. local opts = cfg.buildoptions
  402. if cfg.flags.LowMem then
  403. table.insert(opts, "-lowmem")
  404. end
  405. if cfg.cppdialect and cfg.cppdialect ~= "Default" then
  406. local cppMap = {
  407. ["C++latest"] = "c++20",
  408. ["C++98"] = "c++98",
  409. ["C++0x"] = "c++11",
  410. ["C++11"] = "c++11",
  411. ["C++1y"] = "c++14",
  412. ["C++14"] = "c++14",
  413. ["C++1z"] = "c++17",
  414. ["C++17"] = "c++17",
  415. ["C++2a"] = "c++20",
  416. ["C++20"] = "c++20",
  417. ["gnu++98"] = "c++98",
  418. ["gnu++0x"] = "c++11",
  419. ["gnu++11"] = "c++11",
  420. ["gnu++1y"] = "c++14",
  421. ["gnu++14"] = "c++14",
  422. ["gnu++1z"] = "c++17",
  423. ["gnu++17"] = "c++17",
  424. ["gnu++2a"] = "c++20",
  425. ["gnu++20"] = "c++20",
  426. }
  427. if cppMap[cfg.cppdialect] ~= nil then
  428. table.insert(opts, "-extern-std=" .. cppMap[cfg.cppdialect])
  429. end
  430. end
  431. -- TODO: better way to check toolset?
  432. if _OPTIONS.dc == "ldc" or cfg.flags.UseLDC then
  433. if cfg.vectorextensions then
  434. local vextMap = {
  435. AVX = "avx",
  436. AVX2 = "avx2",
  437. SSE = "sse",
  438. SSE2 = "sse2",
  439. SSE3 = "sse3",
  440. SSSE3 = "ssse3",
  441. ["SSE4.1"] = "sse4.1",
  442. ["SSE4.2"] = "sse4.2",
  443. }
  444. if vextMap[cfg.vectorextensions] ~= nil then
  445. table.insert(opts, "-mattr=+" .. vextMap[cfg.vectorextensions])
  446. end
  447. end
  448. if #cfg.isaextensions > 0 then
  449. local isaMap = {
  450. MOVBE = "movbe",
  451. POPCNT = "popcnt",
  452. PCLMUL = "pclmul",
  453. LZCNT = "lzcnt",
  454. BMI = "bmi",
  455. BMI2 = "bmi2",
  456. F16C = "f16c",
  457. AES = "aes",
  458. FMA = "fma",
  459. FMA4 = "fma4",
  460. RDRND = "rdrnd",
  461. }
  462. for _, ext in ipairs(cfg.isaextensions) do
  463. if isaMap[ext] ~= nil then
  464. table.insert(opts, "-mattr=+" .. isaMap[ext])
  465. end
  466. end
  467. end
  468. if #cfg.computetargets > 0 then
  469. table.insert(opts, "-mdcompute-targets=" .. table.concat(cfg.computetargets, ','))
  470. end
  471. end
  472. if #opts > 0 then
  473. opts = table.concat(opts, " ")
  474. vc2010.element("AdditionalOptions", condition, '%s %%(AdditionalOptions)', opts)
  475. end
  476. end