vs200x_vcproj.lua 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621
  1. --
  2. -- vs200x_vcproj.lua
  3. -- Generate a Visual Studio 2005-2008 C/C++ project.
  4. -- Copyright (c) Jason Perkins and the Premake project
  5. --
  6. local p = premake
  7. p.vstudio.vc200x = {}
  8. local m = p.vstudio.vc200x
  9. local vstudio = p.vstudio
  10. local context = p.context
  11. local project = p.project
  12. local config = p.config
  13. local fileconfig = p.fileconfig
  14. m.elements = {}
  15. ---
  16. -- Generate a Visual Studio 200x C++ or Makefile project.
  17. ---
  18. m.elements.project = function(prj)
  19. return {
  20. m.xmlElement,
  21. m.visualStudioProject,
  22. m.platforms,
  23. m.toolFiles,
  24. m.configurations,
  25. m.references,
  26. m.files,
  27. m.globals
  28. }
  29. end
  30. function m.generate(prj)
  31. p.indent("\t")
  32. p.callArray(m.elements.project, prj)
  33. p.pop('</VisualStudioProject>')
  34. p.w()
  35. end
  36. ---
  37. -- Write the opening <VisualStudioProject> element of the project file.
  38. -- In this case, the call list is for XML attributes rather than elements.
  39. ---
  40. m.elements.visualStudioProject = function(prj)
  41. return {
  42. m.projectType,
  43. m.version,
  44. m.projectName,
  45. m.projectGUID,
  46. m.rootNamespace,
  47. m.keyword,
  48. m.targetFrameworkVersion
  49. }
  50. end
  51. function m.visualStudioProject(prj)
  52. p.push('<VisualStudioProject')
  53. p.callArray(m.elements.visualStudioProject, prj)
  54. p.w('>')
  55. end
  56. ---
  57. -- Write out the <Configurations> element group, enumerating each of the
  58. -- configuration-architecture pairings.
  59. ---
  60. function m.configurations(prj)
  61. p.push('<Configurations>')
  62. -- Visual Studio requires each configuration to be paired up with each
  63. -- architecture, even if the pairing doesn't make any sense (i.e. Win32
  64. -- DLL DCRT|PS3). Start by building a map between configurations and
  65. -- their Visual Studio names. I will use this to determine which
  66. -- pairings are "real", and which need to be synthesized.
  67. local mapping = {}
  68. for cfg in project.eachconfig(prj) do
  69. local name = vstudio.projectConfig(cfg)
  70. mapping[cfg] = name
  71. mapping[name] = cfg
  72. end
  73. -- Now enumerate each configuration and architecture pairing
  74. for cfg in project.eachconfig(prj) do
  75. for i, arch in ipairs(architectures) do
  76. local target
  77. -- Generate a Visual Studio name from this pairing and see if
  78. -- it matches. If so, I can go ahead and output the markup for
  79. -- this configuration.
  80. local testName = vstudio.projectConfig(cfg, arch)
  81. if testName == mapping[cfg] then
  82. target = cfg
  83. -- Okay, this pairing doesn't match this configuration. Check
  84. -- the mapping to see if it matches some *other* configuration.
  85. -- If it does, I can ignore it as it will getting written on
  86. -- another pass through the loop. If it does not, then this is
  87. -- one of those fake configurations that I have to synthesize.
  88. elseif not mapping[testName] then
  89. target = { fake = true }
  90. end
  91. -- If I'm not ignoring this pairing, output the result now
  92. if target then
  93. m.configuration(target, testName)
  94. m.tools(target)
  95. p.pop('</Configuration>')
  96. end
  97. end
  98. end
  99. p.pop('</Configurations>')
  100. end
  101. ---
  102. -- Write out the <Configuration> element, describing a specific Premake
  103. -- build configuration/platform pairing.
  104. ---
  105. m.elements.configuration = function(cfg)
  106. if cfg.fake then
  107. return {
  108. m.intermediateDirectory,
  109. m.configurationType
  110. }
  111. else
  112. return {
  113. m.outputDirectory,
  114. m.intermediateDirectory,
  115. m.configurationType,
  116. m.useOfMFC,
  117. m.characterSet,
  118. m.managedExtensions,
  119. }
  120. end
  121. end
  122. function m.configuration(cfg, name)
  123. p.push('<Configuration')
  124. p.w('Name="%s"', name)
  125. p.callArray(m.elements.configuration, cfg)
  126. p.w('>')
  127. end
  128. ---
  129. -- Return the list of tools required to build a specific configuration.
  130. -- Each tool gets represented by an XML element in the project file, all
  131. -- of which are implemented farther down in this file.
  132. --
  133. -- @param cfg
  134. -- The configuration being written.
  135. ---
  136. m.elements.tools = function(cfg)
  137. if vstudio.isMakefile(cfg) and not cfg.fake then
  138. return {
  139. m.VCNMakeTool
  140. }
  141. end
  142. return {
  143. m.VCPreBuildEventTool,
  144. m.VCCustomBuildTool,
  145. m.VCXMLDataGeneratorTool,
  146. m.VCWebServiceProxyGeneratorTool,
  147. m.VCMIDLTool,
  148. m.VCCLCompilerTool,
  149. m.VCManagedResourceCompilerTool,
  150. m.VCResourceCompilerTool,
  151. m.VCPreLinkEventTool,
  152. m.VCLinkerTool,
  153. m.VCALinkTool,
  154. m.VCManifestTool,
  155. m.VCXDCMakeTool,
  156. m.VCBscMakeTool,
  157. m.VCFxCopTool,
  158. m.VCAppVerifierTool,
  159. m.VCPostBuildEventTool,
  160. }
  161. end
  162. function m.tools(cfg)
  163. p.callArray(m.elements.tools, cfg, config.toolset(cfg))
  164. end
  165. ---
  166. -- Write out the <References> element group.
  167. ---
  168. m.elements.references = function(prj)
  169. return {
  170. m.assemblyReferences,
  171. m.projectReferences,
  172. }
  173. end
  174. function m.references(prj)
  175. p.push('<References>')
  176. p.callArray(m.elements.references, prj)
  177. p.pop('</References>')
  178. end
  179. ---
  180. -- Write out the <Files> element group.
  181. ---
  182. function m.files(prj)
  183. local tr = m.filesSorted(prj)
  184. p.push('<Files>')
  185. p.tree.traverse(tr, {
  186. onbranchenter = m.filesFilterStart,
  187. onbranchexit = m.filesFilterEnd,
  188. onleaf = m.filesFile,
  189. }, false)
  190. p.pop('</Files>')
  191. end
  192. function m.filesSorted(prj)
  193. -- Fetch the source tree, sorted how Visual Studio likes it: alpha
  194. -- sorted, with any leading ../ sequences ignored. At the top level
  195. -- of the tree, files go after folders, otherwise before.
  196. return project.getsourcetree(prj, function(a,b)
  197. local istop = (a.parent.parent == nil)
  198. local aSortName = a.name
  199. local bSortName = b.name
  200. -- Only file nodes have a relpath field; folder nodes do not
  201. if a.relpath then
  202. if not b.relpath then
  203. return not istop
  204. end
  205. aSortName = a.relpath:gsub("%.%.%/", "")
  206. end
  207. if b.relpath then
  208. if not a.relpath then
  209. return istop
  210. end
  211. bSortName = b.relpath:gsub("%.%.%/", "")
  212. end
  213. return aSortName < bSortName
  214. end)
  215. end
  216. function m.filesFilterStart(node)
  217. p.push('<Filter')
  218. p.w('Name="%s"', node.name)
  219. p.w('>')
  220. end
  221. function m.filesFilterEnd(node)
  222. p.pop('</Filter>')
  223. end
  224. function m.filesFile(node)
  225. p.push('<File')
  226. p.w('RelativePath="%s"', path.translate(node.relpath))
  227. p.w('>')
  228. local prj = node.project
  229. for cfg in project.eachconfig(prj) do
  230. m.fileConfiguration(cfg, node)
  231. end
  232. p.pop('</File>')
  233. end
  234. m.elements.fileConfigurationAttributes = function(filecfg)
  235. return {
  236. m.excludedFromBuild,
  237. }
  238. end
  239. function m.fileConfiguration(cfg, node)
  240. local filecfg = fileconfig.getconfig(node, cfg)
  241. -- Generate the individual sections of the file configuration
  242. -- element and capture the results to a buffer. I will only
  243. -- write the file configuration if the buffers are not empty.
  244. local configAttribs = p.capture(function ()
  245. p.push()
  246. p.callArray(m.elements.fileConfigurationAttributes, filecfg)
  247. p.pop()
  248. end)
  249. local compilerAttribs = p.capture(function ()
  250. p.push()
  251. m.VCCLCompilerTool(filecfg)
  252. p.pop()
  253. end)
  254. -- lines() > 3 skips empty <Tool Name="VCCLCompiler" /> elements
  255. if #configAttribs > 0 or compilerAttribs:lines() > 3 then
  256. p.push('<FileConfiguration')
  257. p.w('Name="%s"', vstudio.projectConfig(cfg))
  258. if #configAttribs > 0 then
  259. p.outln(configAttribs)
  260. end
  261. p.w('>')
  262. p.outln(compilerAttribs)
  263. p.pop('</FileConfiguration>')
  264. end
  265. end
  266. ---
  267. -- I don't do anything with globals yet, but here it is if you want to
  268. -- extend it.
  269. ---
  270. m.elements.globals = function(prj)
  271. return {}
  272. end
  273. function m.globals(prj)
  274. p.push('<Globals>')
  275. p.callArray(m.elements.globals, prj)
  276. p.pop('</Globals>')
  277. end
  278. ---------------------------------------------------------------------------
  279. --
  280. -- Handlers for the individual tool sections of the project.
  281. --
  282. -- There is a lot of repetition here; most of these tools are just
  283. -- placeholders for modules to override as needed.
  284. --
  285. ---------------------------------------------------------------------------
  286. ---
  287. -- The implementation of a "normal" tool. Writes the opening tool element
  288. -- and name attribute, calls the corresponding function list, and then
  289. -- closes the element.
  290. --
  291. -- @param name
  292. -- The name of the tool, e.g. "VCCustomBuildTool".
  293. -- @param ...
  294. -- Any additional arguments required by the call list.
  295. ---
  296. function m.VCTool(name, cfg, ...)
  297. p.push('<Tool')
  298. local nameFunc = m[name .. "Name"]
  299. local callFunc = m.elements[name]
  300. if nameFunc then
  301. name = nameFunc(cfg, ...)
  302. end
  303. p.w('Name="%s"', name)
  304. if cfg and not cfg.fake then
  305. p.callArray(callFunc, cfg, ...)
  306. end
  307. p.pop('/>')
  308. end
  309. ------------
  310. m.elements.DebuggerTool = function(cfg)
  311. return {}
  312. end
  313. function m.DebuggerTool(cfg)
  314. p.push('<DebuggerTool')
  315. p.pop('/>')
  316. end
  317. ------------
  318. m.elements.VCALinkTool = function(cfg)
  319. return {}
  320. end
  321. function m.VCALinkTool(cfg)
  322. m.VCTool("VCALinkTool", cfg)
  323. end
  324. ------------
  325. m.elements.VCAppVerifierTool = function(cfg)
  326. return {}
  327. end
  328. function m.VCAppVerifierTool(cfg)
  329. if cfg.kind ~= p.STATICLIB then
  330. m.VCTool("VCAppVerifierTool", cfg)
  331. end
  332. end
  333. ------------
  334. m.elements.VCBscMakeTool = function(cfg)
  335. return {}
  336. end
  337. function m.VCBscMakeTool(cfg)
  338. m.VCTool("VCBscMakeTool", cfg)
  339. end
  340. ------------
  341. m.elements.VCCLCompilerTool = function(cfg, toolset)
  342. if not toolset then
  343. -- not a custom tool, use the standard set of attributes
  344. return {
  345. m.customBuildTool,
  346. m.objectFile,
  347. m.additionalCompilerOptions,
  348. m.optimization,
  349. m.additionalIncludeDirectories,
  350. m.wholeProgramOptimization,
  351. m.preprocessorDefinitions,
  352. m.undefinePreprocessorDefinitions,
  353. m.minimalRebuild,
  354. m.basicRuntimeChecks,
  355. m.bufferSecurityCheck,
  356. m.stringPooling,
  357. m.exceptionHandling,
  358. m.runtimeLibrary,
  359. m.enableFunctionLevelLinking,
  360. m.enableEnhancedInstructionSet,
  361. m.floatingPointModel,
  362. m.runtimeTypeInfo,
  363. m.treatWChar_tAsBuiltInType,
  364. m.usePrecompiledHeader,
  365. m.programDataBaseFileName,
  366. m.warningLevel,
  367. m.warnAsError,
  368. m.detect64BitPortabilityProblems,
  369. m.debugInformationFormat,
  370. m.compileAs,
  371. m.disableSpecificWarnings,
  372. m.forcedIncludeFiles,
  373. m.omitDefaultLib,
  374. }
  375. else
  376. -- custom tool, use subset of attributes
  377. return {
  378. m.additionalExternalCompilerOptions,
  379. m.additionalIncludeDirectories,
  380. m.preprocessorDefinitions,
  381. m.undefinePreprocessorDefinitions,
  382. m.usePrecompiledHeader,
  383. m.programDataBaseFileName,
  384. m.debugInformationFormat,
  385. m.compileAs,
  386. m.forcedIncludeFiles,
  387. }
  388. end
  389. end
  390. function m.VCCLCompilerToolName(cfg)
  391. local prjcfg, filecfg = config.normalize(cfg)
  392. if filecfg and fileconfig.hasCustomBuildRule(filecfg) then
  393. return "VCCustomBuildTool"
  394. else
  395. return "VCCLCompilerTool"
  396. end
  397. end
  398. function m.VCCLCompilerTool(cfg, toolset)
  399. m.VCTool("VCCLCompilerTool", cfg, toolset)
  400. end
  401. ------------
  402. m.elements.VCCustomBuildTool = function(cfg)
  403. return {}
  404. end
  405. function m.VCCustomBuildTool(cfg)
  406. m.VCTool("VCCustomBuildTool", cfg)
  407. end
  408. ------------
  409. m.elements.VCFxCopTool = function(cfg)
  410. return {}
  411. end
  412. function m.VCFxCopTool(cfg)
  413. m.VCTool("VCFxCopTool", cfg)
  414. end
  415. ------------
  416. m.elements.VCLinkerTool = function(cfg, toolset)
  417. if cfg.kind ~= p.STATICLIB then
  418. return {
  419. m.linkLibraryDependencies,
  420. m.ignoreImportLibrary,
  421. m.additionalLinkerOptions,
  422. m.additionalDependencies,
  423. m.outputFile,
  424. m.linkIncremental,
  425. m.additionalLibraryDirectories,
  426. m.moduleDefinitionFile,
  427. m.generateManifest,
  428. m.generateDebugInformation,
  429. m.programDatabaseFile,
  430. m.subSystem,
  431. m.largeAddressAware,
  432. m.optimizeReferences,
  433. m.enableCOMDATFolding,
  434. m.entryPointSymbol,
  435. m.importLibrary,
  436. m.targetMachine,
  437. }
  438. else
  439. return {
  440. m.additionalLinkerOptions,
  441. m.additionalDependencies,
  442. m.outputFile,
  443. m.additionalLibraryDirectories,
  444. }
  445. end
  446. end
  447. function m.VCLinkerToolName(cfg)
  448. if cfg.kind == p.STATICLIB then
  449. return "VCLibrarianTool"
  450. else
  451. return "VCLinkerTool"
  452. end
  453. end
  454. function m.VCLinkerTool(cfg, toolset)
  455. m.VCTool("VCLinkerTool", cfg, toolset)
  456. end
  457. ------------
  458. m.elements.VCManagedResourceCompilerTool = function(cfg)
  459. return {}
  460. end
  461. function m.VCManagedResourceCompilerTool(cfg)
  462. m.VCTool("VCManagedResourceCompilerTool", cfg)
  463. end
  464. ------------
  465. m.elements.VCManifestTool = function(cfg)
  466. return {
  467. m.additionalManifestFiles,
  468. }
  469. end
  470. function m.VCManifestTool(cfg)
  471. if cfg.kind ~= p.STATICLIB then
  472. m.VCTool("VCManifestTool", cfg)
  473. end
  474. end
  475. ------------
  476. m.elements.VCMIDLTool = function(cfg)
  477. return {
  478. m.targetEnvironment
  479. }
  480. end
  481. function m.VCMIDLTool(cfg)
  482. m.VCTool("VCMIDLTool", cfg)
  483. end
  484. ------------
  485. m.elements.VCNMakeTool = function(cfg)
  486. return {
  487. m.buildCommandLine,
  488. m.reBuildCommandLine,
  489. m.cleanCommandLine,
  490. m.output,
  491. m.preprocessorDefinitions,
  492. m.undefinePreprocessorDefinitions,
  493. m.includeSearchPath,
  494. m.forcedIncludes,
  495. m.assemblySearchPath,
  496. m.forcedUsingAssemblies,
  497. m.compileAsManaged,
  498. }
  499. end
  500. function m.VCNMakeTool(cfg)
  501. m.VCTool("VCNMakeTool", cfg)
  502. end
  503. ------------
  504. m.elements.VCBuildTool = function(cfg, stage)
  505. return {
  506. m.commandLine,
  507. }
  508. end
  509. function m.VCBuildToolName(cfg, stage)
  510. return "VC" .. stage .. "EventTool"
  511. end
  512. function m.VCPreBuildEventTool(cfg)
  513. m.VCTool("VCBuildTool", cfg, "PreBuild")
  514. end
  515. function m.VCPreLinkEventTool(cfg)
  516. m.VCTool("VCBuildTool", cfg, "PreLink")
  517. end
  518. function m.VCPostBuildEventTool(cfg)
  519. m.VCTool("VCBuildTool", cfg, "PostBuild")
  520. end
  521. ------------
  522. m.elements.VCResourceCompilerTool = function(cfg)
  523. return {
  524. m.additionalResourceOptions,
  525. m.resourcePreprocessorDefinitions,
  526. m.additionalResourceIncludeDirectories,
  527. m.culture,
  528. }
  529. end
  530. function m.VCResourceCompilerTool(cfg)
  531. m.VCTool("VCResourceCompilerTool", cfg)
  532. end
  533. ------------
  534. m.elements.VCWebServiceProxyGeneratorTool = function(cfg)
  535. return {}
  536. end
  537. function m.VCWebServiceProxyGeneratorTool(cfg)
  538. m.VCTool("VCWebServiceProxyGeneratorTool", cfg)
  539. end
  540. ------------
  541. m.elements.VCXDCMakeTool = function(cfg)
  542. return {}
  543. end
  544. function m.VCXDCMakeTool(cfg)
  545. m.VCTool("VCXDCMakeTool", cfg)
  546. end
  547. ------------
  548. m.elements.VCXMLDataGeneratorTool = function(cfg)
  549. return {}
  550. end
  551. function m.VCXMLDataGeneratorTool(cfg)
  552. m.VCTool("VCXMLDataGeneratorTool", cfg)
  553. end
  554. ---------------------------------------------------------------------------
  555. --
  556. -- Support functions
  557. --
  558. ---------------------------------------------------------------------------
  559. --
  560. -- Return the debugging symbol level for a configuration.
  561. --
  562. function m.symbols(cfg)
  563. if not (cfg.symbols == p.ON) then
  564. return 0
  565. elseif cfg.debugformat == "c7" then
  566. return 1
  567. else
  568. -- Edit-and-continue doesn't work for some configurations
  569. if cfg.editandcontinue == p.OFF or
  570. config.isOptimizedBuild(cfg) or
  571. cfg.clr ~= p.OFF or
  572. cfg.architecture == p.X86_64
  573. then
  574. return 3
  575. else
  576. return 4
  577. end
  578. end
  579. end
  580. ---------------------------------------------------------------------------
  581. --
  582. -- Handlers for individual project elements
  583. --
  584. ---------------------------------------------------------------------------
  585. function m.additionalCompilerOptions(cfg)
  586. local opts = cfg.buildoptions
  587. if cfg.flags.MultiProcessorCompile then
  588. table.insert(opts, "/MP")
  589. end
  590. if #opts > 0 then
  591. p.x('AdditionalOptions="%s"', table.concat(opts, " "))
  592. end
  593. end
  594. function m.additionalDependencies(cfg, toolset)
  595. if #cfg.links == 0 then return end
  596. local ex = vstudio.needsExplicitLink(cfg)
  597. local links
  598. if not toolset then
  599. links = vstudio.getLinks(cfg, ex)
  600. for i, link in ipairs(links) do
  601. if link:find(" ", 1, true) then
  602. link = '"' .. link .. '"'
  603. end
  604. links[i] = path.translate(link)
  605. end
  606. else
  607. links = path.translate(toolset.getlinks(cfg, not ex))
  608. end
  609. if #links > 0 then
  610. p.x('AdditionalDependencies="%s"', table.concat(links, " "))
  611. end
  612. end
  613. function m.additionalExternalCompilerOptions(cfg, toolset)
  614. local buildoptions = table.join(toolset.getcxxflags(cfg), cfg.buildoptions)
  615. if not cfg.flags.NoPCH and cfg.pchheader then
  616. table.insert(buildoptions, '--use_pch="$(IntDir)/$(TargetName).pch"')
  617. end
  618. if #buildoptions > 0 then
  619. p.x('AdditionalOptions="%s"', table.concat(buildoptions, " "))
  620. end
  621. end
  622. function m.additionalImageOptions(cfg)
  623. if #cfg.imageoptions > 0 then
  624. p.x('AdditionalOptions="%s"', table.concat(cfg.imageoptions, " "))
  625. end
  626. end
  627. function m.additionalIncludeDirectories(cfg)
  628. if #cfg.includedirs > 0 then
  629. local dirs = vstudio.path(cfg, cfg.includedirs)
  630. p.x('AdditionalIncludeDirectories="%s"', table.concat(dirs, ";"))
  631. end
  632. end
  633. function m.additionalLibraryDirectories(cfg)
  634. if #cfg.libdirs > 0 then
  635. local dirs = vstudio.path(cfg, cfg.libdirs)
  636. p.x('AdditionalLibraryDirectories="%s"', table.concat(dirs, ";"))
  637. end
  638. end
  639. function m.additionalLinkerOptions(cfg, toolset)
  640. local flags
  641. if toolset then
  642. flags = table.join(toolset.getldflags(cfg), cfg.linkoptions)
  643. else
  644. flags = cfg.linkoptions
  645. end
  646. if #flags > 0 then
  647. p.x('AdditionalOptions="%s"', table.concat(flags, " "))
  648. end
  649. end
  650. function m.additionalManifestFiles(cfg)
  651. local manifests = {}
  652. for i, fname in ipairs(cfg.files) do
  653. if path.getextension(fname) == ".manifest" then
  654. table.insert(manifests, project.getrelative(cfg.project, fname))
  655. end
  656. end
  657. if #manifests > 0 then
  658. p.x('AdditionalManifestFiles="%s"', table.concat(manifests, ";"))
  659. end
  660. end
  661. function m.additionalResourceIncludeDirectories(cfg)
  662. local dirs = table.join(cfg.includedirs, cfg.resincludedirs)
  663. if #dirs > 0 then
  664. dirs = vstudio.path(cfg, dirs)
  665. p.x('AdditionalIncludeDirectories="%s"', table.concat(dirs, ";"))
  666. end
  667. end
  668. function m.additionalResourceOptions(cfg)
  669. if #cfg.resoptions > 0 then
  670. p.x('AdditionalOptions="%s"', table.concat(cfg.resoptions, " "))
  671. end
  672. end
  673. function m.assemblyReferences(prj)
  674. -- Visual Studio doesn't support per-config references
  675. local cfg = project.getfirstconfig(prj)
  676. local refs = config.getlinks(cfg, "system", "fullpath", "managed")
  677. table.foreachi(refs, function(value)
  678. p.push('<AssemblyReference')
  679. p.x('RelativePath="%s"', path.translate(value))
  680. p.pop('/>')
  681. end)
  682. end
  683. function m.assemblySearchPath(cfg)
  684. p.w('AssemblySearchPath=""')
  685. end
  686. function m.basicRuntimeChecks(cfg)
  687. local cfg, filecfg = config.normalize(cfg)
  688. if not filecfg
  689. and not config.isOptimizedBuild(cfg)
  690. and cfg.clr == p.OFF
  691. and not cfg.flags.NoRuntimeChecks
  692. then
  693. p.w('BasicRuntimeChecks="3"')
  694. end
  695. end
  696. function m.bufferSecurityCheck(cfg)
  697. if cfg.flags.NoBufferSecurityCheck then
  698. p.w('BufferSecurityCheck="false"')
  699. end
  700. end
  701. function m.buildCommandLine(cfg)
  702. local cmds = os.translateCommandsAndPaths(cfg.buildcommands, cfg.project.basedir, cfg.project.location)
  703. p.x('BuildCommandLine="%s"', table.concat(cmds, "\r\n"))
  704. end
  705. function m.characterSet(cfg)
  706. if not vstudio.isMakefile(cfg) then
  707. p.w('CharacterSet="%s"', iif(cfg.characterset == p.MBCS, 2, 1))
  708. end
  709. end
  710. function m.cleanCommandLine(cfg)
  711. local cmds = os.translateCommandsAndPaths(cfg.cleancommands, cfg.project.basedir, cfg.project.location)
  712. cmds = table.concat(cmds, "\r\n")
  713. p.x('CleanCommandLine="%s"', cmds)
  714. end
  715. function m.commandLine(cfg, stage)
  716. local field = stage:lower()
  717. local steps = cfg[field .. "commands"]
  718. local msg = cfg[field .. "message"]
  719. if #steps > 0 then
  720. if msg then
  721. p.x('Description="%s"', msg)
  722. end
  723. steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location)
  724. p.x('CommandLine="%s"', table.implode(steps, "", "", "\r\n"))
  725. end
  726. end
  727. function m.compileAs(cfg, toolset)
  728. local cfg, filecfg = config.normalize(cfg)
  729. local c = p.languages.isc(cfg.language)
  730. local compileAs
  731. if filecfg then
  732. if filecfg.compileas then
  733. compileAs = iif(p.languages.iscpp(filecfg.compileas), 2, 1)
  734. elseif path.iscfile(filecfg.name) ~= c then
  735. if path.iscppfile(filecfg.name) then
  736. compileAs = iif(c, 2, 1)
  737. end
  738. end
  739. else
  740. if toolset then
  741. compileAs = "0"
  742. elseif c then
  743. compileAs = "1"
  744. end
  745. end
  746. if compileAs then
  747. p.w('CompileAs="%s"', compileAs)
  748. end
  749. end
  750. function m.disableSpecificWarnings(cfg)
  751. if #cfg.disablewarnings > 0 then
  752. p.x('DisableSpecificWarnings="%s"', table.concat(cfg.disablewarnings, ";"))
  753. end
  754. end
  755. function m.compileAsManaged(cfg)
  756. p.w('CompileAsManaged=""')
  757. end
  758. function m.configurationType(cfg)
  759. local cfgtypes = {
  760. Makefile = 0,
  761. None = 0,
  762. SharedLib = 2,
  763. StaticLib = 4,
  764. }
  765. p.w('ConfigurationType="%s"', cfgtypes[cfg.kind] or 1)
  766. end
  767. function m.culture(cfg)
  768. local value = vstudio.cultureForLocale(cfg.locale)
  769. if value then
  770. p.w('Culture="%d"', value)
  771. end
  772. end
  773. function m.customBuildTool(cfg)
  774. local cfg, filecfg = config.normalize(cfg)
  775. if filecfg and fileconfig.hasCustomBuildRule(filecfg) then
  776. local cmds = os.translateCommandsAndPaths(filecfg.buildcommands, filecfg.project.basedir, filecfg.project.location)
  777. p.x('CommandLine="%s"', table.concat(cmds,'\r\n'))
  778. local outputs = project.getrelative(filecfg.project, filecfg.buildoutputs)
  779. p.x('Outputs="%s"', table.concat(outputs, ';'))
  780. if filecfg.buildinputs and #filecfg.buildinputs > 0 then
  781. local inputs = project.getrelative(filecfg.project, filecfg.buildinputs)
  782. p.x('AdditionalDependencies="%s"', table.concat(inputs, ';'))
  783. end
  784. end
  785. end
  786. function m.debugInformationFormat(cfg, toolset)
  787. local prjcfg, filecfg = config.normalize(cfg)
  788. if not filecfg then
  789. local fmt = iif(toolset, "0", m.symbols(cfg))
  790. p.w('DebugInformationFormat="%s"', fmt)
  791. end
  792. end
  793. function m.detect64BitPortabilityProblems(cfg)
  794. local prjcfg, filecfg = config.normalize(cfg)
  795. if _ACTION < "vs2008" and cfg.clr == p.OFF and cfg.warnings ~= p.OFF and not filecfg then
  796. p.w('Detect64BitPortabilityProblems="%s"', tostring(not cfg.flags.No64BitChecks))
  797. end
  798. end
  799. function m.enableCOMDATFolding(cfg, toolset)
  800. if config.isOptimizedBuild(cfg) and not toolset then
  801. p.w('EnableCOMDATFolding="2"')
  802. end
  803. end
  804. function m.largeAddressAware(cfg)
  805. if (cfg.largeaddressaware == true) then
  806. p.w('LargeAddressAware="2"')
  807. end
  808. end
  809. function m.enableEnhancedInstructionSet(cfg)
  810. local map = { SSE = "1", SSE2 = "2" }
  811. local value = map[cfg.vectorextensions]
  812. if value and cfg.architecture ~= "x86_64" then
  813. p.w('EnableEnhancedInstructionSet="%d"', value)
  814. end
  815. end
  816. function m.enableFunctionLevelLinking(cfg)
  817. local cfg, filecfg = config.normalize(cfg)
  818. if not filecfg then
  819. p.w('EnableFunctionLevelLinking="true"')
  820. end
  821. end
  822. function m.entryPointSymbol(cfg, toolset)
  823. if cfg.entrypoint then
  824. p.w('EntryPointSymbol="%s"', cfg.entrypoint)
  825. end
  826. end
  827. function m.exceptionHandling(cfg)
  828. if cfg.exceptionhandling == p.OFF then
  829. p.w('ExceptionHandling="%s"', iif(_ACTION < "vs2005", "FALSE", 0))
  830. elseif cfg.exceptionhandling == "SEH" and _ACTION > "vs2003" then
  831. p.w('ExceptionHandling="2"')
  832. end
  833. end
  834. function m.excludedFromBuild(filecfg)
  835. if not filecfg or filecfg.flags.ExcludeFromBuild then
  836. p.w('ExcludedFromBuild="true"')
  837. end
  838. end
  839. function m.floatingPointModel(cfg)
  840. local map = { Strict = "1", Fast = "2" }
  841. local value = map[cfg.floatingpoint]
  842. if value then
  843. p.w('FloatingPointModel="%d"', value)
  844. end
  845. end
  846. function m.forcedIncludeFiles(cfg)
  847. if #cfg.forceincludes > 0 then
  848. local includes = vstudio.path(cfg, cfg.forceincludes)
  849. p.w('ForcedIncludeFiles="%s"', table.concat(includes, ';'))
  850. end
  851. if #cfg.forceusings > 0 then
  852. local usings = vstudio.path(cfg, cfg.forceusings)
  853. p.w('ForcedUsingFiles="%s"', table.concat(usings, ';'))
  854. end
  855. end
  856. function m.forcedIncludes(cfg)
  857. p.w('ForcedIncludes=""')
  858. end
  859. function m.forcedUsingAssemblies(cfg)
  860. p.w('ForcedUsingAssemblies=""')
  861. end
  862. function m.keyword(prj)
  863. local windows, managed, makefile
  864. for cfg in project.eachconfig(prj) do
  865. if cfg.system == p.WINDOWS then windows = true end
  866. if cfg.clr ~= p.OFF then managed = true end
  867. if vstudio.isMakefile(cfg) then makefile = true end
  868. end
  869. if windows then
  870. local keyword = "Win32Proj"
  871. if managed then
  872. keyword = "ManagedCProj"
  873. end
  874. if makefile then
  875. keyword = "MakeFileProj"
  876. end
  877. p.w('Keyword="%s"', keyword)
  878. end
  879. end
  880. function m.generateDebugInformation(cfg, toolset)
  881. if not toolset then
  882. p.w('GenerateDebugInformation="%s"', tostring(m.symbols(cfg) ~= 0))
  883. end
  884. end
  885. function m.generateManifest(cfg, toolset)
  886. if cfg.flags.NoManifest or toolset then
  887. p.w('GenerateManifest="false"')
  888. end
  889. end
  890. function m.ignoreImportLibrary(cfg, toolset)
  891. if cfg.flags.NoImportLib and not toolset then
  892. p.w('IgnoreImportLibrary="true"')
  893. end
  894. end
  895. function m.importLibrary(cfg, toolset)
  896. if cfg.kind == p.SHAREDLIB and not toolset then
  897. local implibdir = cfg.linktarget.abspath
  898. -- I can't actually stop the import lib, but I can hide it in the objects directory
  899. if cfg.flags.NoImportLib then
  900. implibdir = path.join(cfg.objdir, path.getname(implibdir))
  901. end
  902. implibdir = vstudio.path(cfg, implibdir)
  903. p.x('ImportLibrary="%s"', implibdir)
  904. end
  905. end
  906. function m.includeSearchPath(cfg)
  907. p.w('IncludeSearchPath=""')
  908. end
  909. function m.intermediateDirectory(cfg)
  910. local objdir
  911. if not cfg.fake then
  912. objdir = vstudio.path(cfg, cfg.objdir)
  913. else
  914. objdir = "$(PlatformName)\\$(ConfigurationName)"
  915. end
  916. p.x('IntermediateDirectory="%s"', objdir)
  917. end
  918. function m.linkIncremental(cfg, toolset)
  919. local value
  920. if not toolset then
  921. value = iif(config.canLinkIncremental(cfg) , 2, 1)
  922. else
  923. value = 0
  924. end
  925. p.w('LinkIncremental="%s"', value)
  926. end
  927. function m.linkLibraryDependencies(cfg, toolset)
  928. if vstudio.needsExplicitLink(cfg) and not toolset then
  929. p.w('LinkLibraryDependencies="false"')
  930. end
  931. end
  932. function m.managedExtensions(cfg)
  933. if cfg.clr ~= p.OFF then
  934. p.w('ManagedExtensions="1"')
  935. end
  936. end
  937. function m.minimalRebuild(cfg)
  938. if config.isDebugBuild(cfg) and
  939. cfg.debugformat ~= "c7" and
  940. not cfg.flags.NoMinimalRebuild and
  941. cfg.clr == p.OFF and
  942. not cfg.flags.MultiProcessorCompile
  943. then
  944. p.w('MinimalRebuild="true"')
  945. end
  946. end
  947. function m.moduleDefinitionFile(cfg, toolset)
  948. if not toolset then
  949. local deffile = config.findfile(cfg, ".def")
  950. if deffile then
  951. p.w('ModuleDefinitionFile="%s"', deffile)
  952. end
  953. end
  954. end
  955. function m.objectFile(cfg)
  956. local cfg, filecfg = config.normalize(cfg)
  957. if filecfg and path.iscppfile(filecfg.name) then
  958. if filecfg.objname ~= path.getbasename(filecfg.abspath) then
  959. p.x('ObjectFile="$(IntDir)\\%s.obj"', filecfg.objname)
  960. end
  961. end
  962. end
  963. function m.omitDefaultLib(cfg)
  964. if cfg.flags.OmitDefaultLibrary then
  965. p.w('OmitDefaultLibName="true"')
  966. end
  967. end
  968. function m.omitFramePointers(cfg)
  969. if cfg.omitframepointer == "On" then
  970. p.w('OmitFramePointers="true"')
  971. end
  972. end
  973. function m.optimization(cfg)
  974. local map = { Off=0, On=3, Debug=0, Full=3, Size=1, Speed=2 }
  975. local value = map[cfg.optimize]
  976. if value or not cfg.abspath then
  977. p.w('Optimization="%s"', value or 0)
  978. end
  979. end
  980. function m.optimizeReferences(cfg, toolset)
  981. if config.isOptimizedBuild(cfg) and not toolset then
  982. p.w('OptimizeReferences="2"')
  983. end
  984. end
  985. function m.output(cfg)
  986. p.w('Output="$(OutDir)%s"', cfg.buildtarget.name)
  987. end
  988. function m.outputDirectory(cfg)
  989. local outdir = project.getrelative(cfg.project, cfg.buildtarget.directory)
  990. p.x('OutputDirectory="%s"', path.translate(outdir))
  991. end
  992. function m.outputFile(cfg)
  993. p.x('OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
  994. end
  995. function m.outputFileName(cfg)
  996. if cfg.imagepath ~= nil then
  997. p.x('OutputFileName="%s"', path.translate(cfg.imagepath))
  998. end
  999. end
  1000. function m.platforms(prj)
  1001. architectures = {}
  1002. for cfg in project.eachconfig(prj) do
  1003. local arch = vstudio.archFromConfig(cfg, true)
  1004. if not table.contains(architectures, arch) then
  1005. table.insert(architectures, arch)
  1006. end
  1007. end
  1008. p.push('<Platforms>')
  1009. table.foreachi(architectures, function(arch)
  1010. p.push('<Platform')
  1011. p.w('Name="%s"', arch)
  1012. p.pop('/>')
  1013. end)
  1014. p.pop('</Platforms>')
  1015. end
  1016. function m.preprocessorDefinitions(cfg)
  1017. if #cfg.defines > 0 or vstudio.isMakefile(cfg) then
  1018. p.x('PreprocessorDefinitions="%s"', table.concat(cfg.defines, ";"))
  1019. end
  1020. end
  1021. function m.undefinePreprocessorDefinitions(cfg)
  1022. if #cfg.undefines > 0 then
  1023. p.x('UndefinePreprocessorDefinitions="%s"', table.concat(cfg.undefines, ";"))
  1024. end
  1025. end
  1026. function m.programDatabaseFile(cfg, toolset)
  1027. if toolset then
  1028. p.w('ProgramDatabaseFile=""')
  1029. end
  1030. end
  1031. function m.programDataBaseFileName(cfg, toolset)
  1032. if toolset then
  1033. p.w('ProgramDataBaseFileName=""')
  1034. end
  1035. end
  1036. function m.projectGUID(prj)
  1037. p.w('ProjectGUID="{%s}"', prj.uuid)
  1038. end
  1039. function m.projectName(prj)
  1040. p.x('Name="%s"', prj.name)
  1041. end
  1042. function m.projectReferences(prj)
  1043. local deps = project.getdependencies(prj)
  1044. if #deps > 0 then
  1045. -- This is a little odd: Visual Studio wants the "relative path to project"
  1046. -- to be relative to the *workspace*, rather than the project doing the
  1047. -- referencing. Which, in theory, would break if the project is included
  1048. -- in more than one workspace. But that's how they do it.
  1049. for i, dep in ipairs(deps) do
  1050. local relpath = vstudio.path(prj.workspace, vstudio.projectfile(dep))
  1051. -- Visual Studio wants the path to start with ./ or ../
  1052. if not relpath:startswith(".") then
  1053. relpath = ".\\" .. relpath
  1054. end
  1055. p.push('<ProjectReference')
  1056. p.w('ReferencedProjectIdentifier="{%s}"', dep.uuid)
  1057. p.w('RelativePathToProject="%s"', relpath)
  1058. p.pop('/>')
  1059. end
  1060. end
  1061. end
  1062. function m.projectType(prj)
  1063. p.w('ProjectType="Visual C++"')
  1064. end
  1065. function m.reBuildCommandLine(cfg)
  1066. commands = table.concat(cfg.rebuildcommands, "\r\n")
  1067. p.x('ReBuildCommandLine="%s"', commands)
  1068. end
  1069. function m.resourcePreprocessorDefinitions(cfg)
  1070. local defs = table.join(cfg.defines, cfg.resdefines)
  1071. if #defs > 0 then
  1072. p.x('PreprocessorDefinitions="%s"', table.concat(defs, ";"))
  1073. end
  1074. end
  1075. function m.rootNamespace(prj)
  1076. local hasWindows = project.hasConfig(prj, function(cfg)
  1077. return cfg.system == p.WINDOWS
  1078. end)
  1079. -- Technically, this should be skipped for pure makefile projects that
  1080. -- do not contain any empty configurations. But I need to figure out a
  1081. -- a good way to check the empty configuration bit first.
  1082. if hasWindows and _ACTION > "vs2003" then
  1083. p.x('RootNamespace="%s"', prj.name)
  1084. end
  1085. end
  1086. function m.runtimeLibrary(cfg)
  1087. local cfg, filecfg = config.normalize(cfg)
  1088. if not filecfg then
  1089. local runtimes = {
  1090. StaticRelease = 0,
  1091. StaticDebug = 1,
  1092. SharedRelease = 2,
  1093. SharedDebug = 3,
  1094. }
  1095. local runtime = config.getruntime(cfg)
  1096. if runtime then
  1097. p.w('RuntimeLibrary="%s"', runtimes[runtime])
  1098. else
  1099. -- TODO: this path should probably be omitted and left for default
  1100. -- ...but I can't really test this, so I'm a leave it how I found it
  1101. p.w('RuntimeLibrary="%s"', iif(config.isDebugBuild(cfg), 3, 2))
  1102. end
  1103. end
  1104. end
  1105. function m.runtimeTypeInfo(cfg)
  1106. if cfg.rtti == p.OFF and cfg.clr == p.OFF then
  1107. p.w('RuntimeTypeInfo="false"')
  1108. elseif cfg.rtti == p.ON then
  1109. p.w('RuntimeTypeInfo="true"')
  1110. end
  1111. end
  1112. function m.stringPooling(cfg)
  1113. if config.isOptimizedBuild(cfg) then
  1114. p.w('StringPooling="true"')
  1115. end
  1116. end
  1117. function m.subSystem(cfg, toolset)
  1118. if not toolset then
  1119. p.w('SubSystem="%s"', iif(cfg.kind == "ConsoleApp", 1, 2))
  1120. end
  1121. end
  1122. function m.targetEnvironment(cfg)
  1123. if cfg.architecture == "x86_64" then
  1124. p.w('TargetEnvironment="3"')
  1125. end
  1126. end
  1127. function m.targetFrameworkVersion(prj)
  1128. local windows, makefile
  1129. for cfg in project.eachconfig(prj) do
  1130. if cfg.system == p.WINDOWS then windows = true end
  1131. if vstudio.isMakefile(cfg) then makefile = true end
  1132. end
  1133. local version = 0
  1134. if makefile or not windows then
  1135. version = 196613
  1136. end
  1137. p.w('TargetFrameworkVersion="%d"', version)
  1138. end
  1139. function m.targetMachine(cfg, toolset)
  1140. if not toolset then
  1141. p.w('TargetMachine="%d"', iif(cfg.architecture == "x86_64", 17, 1))
  1142. end
  1143. end
  1144. function m.toolFiles(prj)
  1145. if _ACTION > "vs2003" then
  1146. p.w('<ToolFiles>')
  1147. p.w('</ToolFiles>')
  1148. end
  1149. end
  1150. function m.treatWChar_tAsBuiltInType(cfg)
  1151. local map = { On = "true", Off = "false" }
  1152. local value = map[cfg.nativewchar]
  1153. if value then
  1154. p.w('TreatWChar_tAsBuiltInType="%s"', value)
  1155. end
  1156. end
  1157. function m.useOfMFC(cfg)
  1158. if (cfg.flags.MFC) then
  1159. p.w('UseOfMFC="%d"', iif(cfg.staticruntime == "On", 1, 2))
  1160. end
  1161. end
  1162. function m.usePrecompiledHeader(cfg)
  1163. local prj, file = config.normalize(cfg)
  1164. if file then
  1165. if prj.pchsource == file.abspath and
  1166. not prj.flags.NoPCH and
  1167. prj.system == p.WINDOWS
  1168. then
  1169. p.w('UsePrecompiledHeader="1"')
  1170. elseif file.flags.NoPCH then
  1171. p.w('UsePrecompiledHeader="0"')
  1172. end
  1173. else
  1174. if not prj.flags.NoPCH and prj.pchheader then
  1175. p.w('UsePrecompiledHeader="%s"', iif(_ACTION < "vs2005", 3, 2))
  1176. p.x('PrecompiledHeaderThrough="%s"', prj.pchheader)
  1177. else
  1178. p.w('UsePrecompiledHeader="%s"', iif(_ACTION > "vs2003" or prj.flags.NoPCH, 0, 2))
  1179. end
  1180. end
  1181. end
  1182. function m.version(prj)
  1183. local map = {
  1184. vs2002 = '7.0',
  1185. vs2003 = '7.1',
  1186. vs2005 = '8.0',
  1187. vs2008 = '9.0'
  1188. }
  1189. p.w('Version="%s0"', map[_ACTION])
  1190. end
  1191. function m.warnAsError(cfg)
  1192. if cfg.flags.FatalCompileWarnings and cfg.warnings ~= p.OFF then
  1193. p.w('WarnAsError="true"')
  1194. end
  1195. end
  1196. function m.warningLevel(cfg)
  1197. local prjcfg, filecfg = config.normalize(cfg)
  1198. local level
  1199. if cfg.warnings == p.OFF then
  1200. level = "0"
  1201. elseif cfg.warnings == "High" then
  1202. level = "4"
  1203. elseif cfg.warnings == "Extra" then
  1204. level = "4"
  1205. elseif not filecfg then
  1206. level = "3"
  1207. end
  1208. if level then
  1209. p.w('WarningLevel="%s"', level)
  1210. end
  1211. end
  1212. function m.wholeProgramOptimization(cfg)
  1213. if cfg.flags.LinkTimeOptimization then
  1214. p.x('WholeProgramOptimization="true"')
  1215. end
  1216. end
  1217. function m.xmlElement()
  1218. p.w('<?xml version="1.0" encoding="Windows-1252"?>')
  1219. end