vs2010_vcxproj.lua 72 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009
  1. --
  2. -- vs2010_vcxproj.lua
  3. -- Generate a Visual Studio 201x C/C++ project.
  4. -- Copyright (c) Jason Perkins and the Premake project
  5. --
  6. local p = premake
  7. p.vstudio.vc2010 = {}
  8. local vstudio = p.vstudio
  9. local project = p.project
  10. local config = p.config
  11. local fileconfig = p.fileconfig
  12. local tree = p.tree
  13. local m = p.vstudio.vc2010
  14. ---
  15. -- Add namespace for element definition lists for p.callArray()
  16. ---
  17. m.elements = {}
  18. m.conditionalElements = {}
  19. --
  20. -- Generate a Visual Studio 201x C++ project, with support for the new platforms API.
  21. --
  22. m.elements.project = function(prj)
  23. return {
  24. m.xmlDeclaration,
  25. m.project,
  26. m.projectConfigurations,
  27. m.globals,
  28. m.importDefaultProps,
  29. m.configurationPropertiesGroup,
  30. m.importLanguageSettings,
  31. m.importExtensionSettings,
  32. m.propertySheetGroup,
  33. m.userMacros,
  34. m.outputPropertiesGroup,
  35. m.itemDefinitionGroups,
  36. m.assemblyReferences,
  37. m.files,
  38. m.projectReferences,
  39. m.importLanguageTargets,
  40. m.importExtensionTargets,
  41. m.ensureNuGetPackageBuildImports,
  42. }
  43. end
  44. function m.generate(prj)
  45. p.utf8()
  46. p.callArray(m.elements.project, prj)
  47. p.out('</Project>')
  48. end
  49. --
  50. -- Output the XML declaration and opening <Project> tag.
  51. --
  52. function m.project(prj)
  53. local action = p.action.current()
  54. if _ACTION >= "vs2019" then
  55. p.push('<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">')
  56. else
  57. p.push('<Project DefaultTargets="Build" ToolsVersion="%s" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">',
  58. action.vstudio.toolsVersion)
  59. end
  60. end
  61. --
  62. -- Write out the list of project configurations, which pairs build
  63. -- configurations with architectures.
  64. --
  65. function m.projectConfigurations(prj)
  66. -- build a list of all architectures used in this project
  67. local platforms = {}
  68. for cfg in project.eachconfig(prj) do
  69. local arch = vstudio.archFromConfig(cfg, true)
  70. if not table.contains(platforms, arch) then
  71. table.insert(platforms, arch)
  72. end
  73. end
  74. local configs = {}
  75. p.push('<ItemGroup Label="ProjectConfigurations">')
  76. for cfg in project.eachconfig(prj) do
  77. for _, arch in ipairs(platforms) do
  78. local prjcfg = vstudio.projectConfig(cfg, arch)
  79. if not configs[prjcfg] then
  80. configs[prjcfg] = prjcfg
  81. p.push('<ProjectConfiguration Include="%s">', vstudio.projectConfig(cfg, arch))
  82. p.x('<Configuration>%s</Configuration>', vstudio.projectPlatform(cfg))
  83. p.w('<Platform>%s</Platform>', arch)
  84. p.pop('</ProjectConfiguration>')
  85. end
  86. end
  87. end
  88. p.pop('</ItemGroup>')
  89. end
  90. --
  91. -- Write out the TargetFrameworkVersion property.
  92. --
  93. function m.targetFramework(prj)
  94. local action = p.action.current()
  95. local tools = string.format(' ToolsVersion="%s"', action.vstudio.toolsVersion)
  96. local framework = prj.dotnetframework or action.vstudio.targetFramework or "4.0"
  97. p.w('<TargetFrameworkVersion>v%s</TargetFrameworkVersion>', framework)
  98. end
  99. --
  100. -- Write out the Globals property group.
  101. --
  102. m.elements.globals = function(prj)
  103. return {
  104. m.projectGuid,
  105. m.ignoreWarnDuplicateFilename,
  106. m.keyword,
  107. m.projectName,
  108. m.preferredToolArchitecture,
  109. m.latestTargetPlatformVersion,
  110. m.windowsTargetPlatformVersion,
  111. m.fastUpToDateCheck,
  112. m.toolsVersion,
  113. }
  114. end
  115. m.elements.globalsCondition = function(prj, cfg)
  116. return {
  117. m.windowsTargetPlatformVersion,
  118. m.xpDeprecationWarning,
  119. }
  120. end
  121. function m.globals(prj)
  122. -- Write out the project-level globals
  123. m.propertyGroup(nil, "Globals")
  124. p.callArray(m.elements.globals, prj)
  125. p.pop('</PropertyGroup>')
  126. -- Write out the configurable globals
  127. for cfg in project.eachconfig(prj) do
  128. -- Find out whether we're going to actually write a property out
  129. local captured = p.capture( function()
  130. p.push()
  131. p.callArray(m.elements.globalsCondition, prj, cfg)
  132. p.pop()
  133. end)
  134. -- If we do have something, create the entry, skip otherwise
  135. if captured ~= '' then
  136. m.propertyGroup(cfg, "Globals")
  137. p.callArray(m.elements.globalsCondition, prj, cfg)
  138. p.pop('</PropertyGroup>')
  139. end
  140. end
  141. end
  142. --
  143. -- Write out the configuration property group: what kind of binary it
  144. -- produces, and some global settings.
  145. --
  146. m.elements.configurationProperties = function(cfg)
  147. if cfg.kind == p.UTILITY then
  148. return {
  149. m.configurationType,
  150. m.platformToolset,
  151. m.toolsVersion,
  152. }
  153. else
  154. return {
  155. m.configurationType,
  156. m.useDebugLibraries,
  157. m.useOfMfc,
  158. m.useOfAtl,
  159. m.clrSupport,
  160. m.characterSet,
  161. m.platformToolset,
  162. m.toolsVersion,
  163. m.wholeProgramOptimization,
  164. m.spectreMitigations, --OpenMPT
  165. m.nmakeOutDirs,
  166. m.windowsSDKDesktopARMSupport,
  167. }
  168. end
  169. end
  170. function m.configurationProperties(cfg)
  171. m.propertyGroup(cfg, "Configuration")
  172. p.callArray(m.elements.configurationProperties, cfg)
  173. p.pop('</PropertyGroup>')
  174. end
  175. function m.configurationPropertiesGroup(prj)
  176. for cfg in project.eachconfig(prj) do
  177. m.configurationProperties(cfg)
  178. end
  179. end
  180. --
  181. -- Write the output property group, which includes the output and intermediate
  182. -- directories, manifest, etc.
  183. --
  184. m.elements.outputProperties = function(cfg)
  185. if cfg.kind == p.UTILITY then
  186. return {
  187. m.outDir,
  188. m.intDir,
  189. m.extensionsToDeleteOnClean,
  190. m.executablePath,
  191. }
  192. else
  193. return {
  194. m.linkIncremental,
  195. m.ignoreImportLibrary,
  196. m.outDir,
  197. m.intDir,
  198. m.targetName,
  199. m.targetExt,
  200. m.includePath,
  201. m.libraryPath,
  202. m.generateManifest,
  203. m.extensionsToDeleteOnClean,
  204. m.executablePath,
  205. }
  206. end
  207. end
  208. function m.outputProperties(cfg)
  209. if not vstudio.isMakefile(cfg) then
  210. m.propertyGroup(cfg)
  211. p.callArray(m.elements.outputProperties, cfg)
  212. p.pop('</PropertyGroup>')
  213. end
  214. end
  215. --
  216. -- Write the NMake property group for Makefile projects, which includes the custom
  217. -- build commands, output file location, etc.
  218. --
  219. m.elements.nmakeProperties = function(cfg)
  220. return {
  221. m.executablePath,
  222. m.includePath,
  223. m.libraryPath,
  224. m.nmakeOutput,
  225. m.nmakeBuildCommands,
  226. m.nmakeRebuildCommands,
  227. m.nmakeCleanCommands,
  228. m.nmakePreprocessorDefinitions,
  229. m.nmakeIncludeDirs,
  230. m.additionalCompileOptions
  231. }
  232. end
  233. function m.nmakeProperties(cfg)
  234. if vstudio.isMakefile(cfg) then
  235. m.propertyGroup(cfg)
  236. p.callArray(m.elements.nmakeProperties, cfg)
  237. p.pop('</PropertyGroup>')
  238. end
  239. end
  240. --
  241. -- Output properties and NMake properties should appear side-by-side
  242. -- for each configuration.
  243. --
  244. function m.outputPropertiesGroup(prj)
  245. for cfg in project.eachconfig(prj) do
  246. m.outputProperties(cfg)
  247. m.nmakeProperties(cfg)
  248. end
  249. end
  250. --
  251. -- Write a configuration's item definition group, which contains all
  252. -- of the per-configuration compile and link settings.
  253. --
  254. m.elements.itemDefinitionGroup = function(cfg)
  255. if cfg.kind == p.UTILITY then
  256. return {
  257. m.ruleVars,
  258. m.buildEvents,
  259. m.buildLog,
  260. }
  261. else
  262. return {
  263. m.clCompile,
  264. m.buildStep,
  265. m.fxCompile,
  266. m.resourceCompile,
  267. m.linker,
  268. m.manifest,
  269. m.buildEvents,
  270. m.ruleVars,
  271. m.buildLog,
  272. }
  273. end
  274. end
  275. function m.itemDefinitionGroup(cfg)
  276. if not vstudio.isMakefile(cfg) then
  277. p.push('<ItemDefinitionGroup %s>', m.condition(cfg))
  278. p.callArray(m.elements.itemDefinitionGroup, cfg)
  279. p.pop('</ItemDefinitionGroup>')
  280. else
  281. if cfg == project.getfirstconfig(cfg.project) then
  282. p.w('<ItemDefinitionGroup>')
  283. p.w('</ItemDefinitionGroup>')
  284. end
  285. end
  286. end
  287. function m.itemDefinitionGroups(prj)
  288. for cfg in project.eachconfig(prj) do
  289. m.itemDefinitionGroup(cfg)
  290. end
  291. end
  292. --
  293. -- Write the the <ClCompile> compiler settings block.
  294. --
  295. m.elements.clCompile = function(cfg)
  296. local calls = {
  297. m.precompiledHeader,
  298. m.warningLevel,
  299. m.treatWarningAsError,
  300. m.disableSpecificWarnings,
  301. m.treatSpecificWarningsAsErrors,
  302. m.basicRuntimeChecks,
  303. m.clCompilePreprocessorDefinitions,
  304. m.clCompileUndefinePreprocessorDefinitions,
  305. m.clCompileAdditionalIncludeDirectories,
  306. m.clCompileAdditionalUsingDirectories,
  307. m.forceIncludes,
  308. m.debugInformationFormat,
  309. m.optimization,
  310. m.functionLevelLinking,
  311. m.intrinsicFunctions,
  312. m.justMyCodeDebugging,
  313. m.supportOpenMP,
  314. m.minimalRebuild,
  315. m.omitFramePointers,
  316. m.stringPooling,
  317. m.runtimeLibrary,
  318. m.omitDefaultLib,
  319. m.exceptionHandling,
  320. m.runtimeTypeInfo,
  321. m.bufferSecurityCheck,
  322. m.treatWChar_tAsBuiltInType,
  323. m.floatingPointModel,
  324. m.floatingPointExceptions,
  325. m.inlineFunctionExpansion,
  326. m.enableEnhancedInstructionSet,
  327. m.multiProcessorCompilation,
  328. m.additionalCompileOptions,
  329. m.compileAs,
  330. m.callingConvention,
  331. m.languageStandard,
  332. m.conformanceMode,
  333. m.structMemberAlignment,
  334. m.useFullPaths,
  335. m.removeUnreferencedCodeData
  336. }
  337. if cfg.kind == p.STATICLIB then
  338. table.insert(calls, m.programDatabaseFileName)
  339. end
  340. return calls
  341. end
  342. function m.clCompile(cfg)
  343. p.push('<ClCompile>')
  344. p.callArray(m.elements.clCompile, cfg)
  345. p.pop('</ClCompile>')
  346. end
  347. --
  348. -- Write the the <CustomBuildStep> compiler settings block.
  349. --
  350. m.elements.buildStep = function(cfg)
  351. local calls = {
  352. m.buildCommands,
  353. m.buildMessage,
  354. m.buildOutputs,
  355. m.buildInputs
  356. }
  357. return calls
  358. end
  359. function m.buildStep(cfg)
  360. if #cfg.buildCommands > 0 or #cfg.buildOutputs > 0 or #cfg.buildInputs > 0 or cfg.buildMessage then
  361. p.push('<CustomBuildStep>')
  362. p.callArray(m.elements.buildStep, cfg)
  363. p.pop('</CustomBuildStep>')
  364. end
  365. end
  366. --
  367. -- Write the <FxCompile> settings block.
  368. --
  369. m.elements.fxCompile = function(cfg)
  370. return {
  371. m.fxCompilePreprocessorDefinition,
  372. m.fxCompileAdditionalIncludeDirs,
  373. m.fxCompileShaderType,
  374. m.fxCompileShaderModel,
  375. m.fxCompileShaderEntry,
  376. m.fxCompileShaderVariableName,
  377. m.fxCompileShaderHeaderOutput,
  378. m.fxCompileShaderObjectOutput,
  379. m.fxCompileShaderAssembler,
  380. m.fxCompileShaderAssemblerOutput,
  381. m.fxCompileShaderAdditionalOptions,
  382. }
  383. end
  384. function m.fxCompile(cfg)
  385. if p.config.hasFile(cfg, path.ishlslfile) then
  386. local contents = p.capture(function ()
  387. p.push()
  388. p.callArray(m.elements.fxCompile, cfg)
  389. p.pop()
  390. end)
  391. if #contents > 0 then
  392. p.push('<FxCompile>')
  393. p.outln(contents)
  394. p.pop('</FxCompile>')
  395. end
  396. end
  397. end
  398. --
  399. -- Write out the resource compiler block.
  400. --
  401. m.elements.resourceCompile = function(cfg)
  402. return {
  403. m.resourcePreprocessorDefinitions,
  404. m.resourceAdditionalIncludeDirectories,
  405. m.culture,
  406. }
  407. end
  408. function m.resourceCompile(cfg)
  409. if p.config.hasFile(cfg, path.isresourcefile) then
  410. local contents = p.capture(function ()
  411. p.push()
  412. p.callArray(m.elements.resourceCompile, cfg)
  413. p.pop()
  414. end)
  415. if #contents > 0 then
  416. p.push('<ResourceCompile>')
  417. p.outln(contents)
  418. p.pop('</ResourceCompile>')
  419. end
  420. end
  421. end
  422. --
  423. -- Write out the linker tool block.
  424. --
  425. m.elements.linker = function(cfg, explicit)
  426. return {
  427. m.link,
  428. m.lib,
  429. m.linkLibraryDependencies,
  430. }
  431. end
  432. function m.linker(cfg)
  433. local explicit = vstudio.needsExplicitLink(cfg)
  434. p.callArray(m.elements.linker, cfg, explicit)
  435. end
  436. m.elements.link = function(cfg, explicit)
  437. if cfg.kind == p.STATICLIB then
  438. return {
  439. m.subSystem,
  440. m.fullProgramDatabaseFile,
  441. m.generateDebugInformation,
  442. m.optimizeReferences,
  443. }
  444. else
  445. return {
  446. m.subSystem,
  447. m.fullProgramDatabaseFile,
  448. m.generateDebugInformation,
  449. m.optimizeReferences,
  450. m.additionalDependencies,
  451. m.additionalLibraryDirectories,
  452. m.importLibrary,
  453. m.entryPointSymbol,
  454. m.generateMapFile,
  455. m.moduleDefinitionFile,
  456. m.treatLinkerWarningAsErrors,
  457. m.ignoreDefaultLibraries,
  458. m.dataExecutionPrevention, --OpenMPT
  459. m.largeAddressAware,
  460. m.targetMachine,
  461. m.additionalLinkOptions,
  462. m.programDatabaseFile,
  463. m.assemblyDebug,
  464. }
  465. end
  466. end
  467. function m.link(cfg, explicit)
  468. local contents = p.capture(function ()
  469. p.push()
  470. p.callArray(m.elements.link, cfg, explicit)
  471. p.pop()
  472. end)
  473. if #contents > 0 then
  474. p.push('<Link>')
  475. p.outln(contents)
  476. p.pop('</Link>')
  477. end
  478. end
  479. m.elements.lib = function(cfg, explicit)
  480. if cfg.kind == p.STATICLIB then
  481. return {
  482. m.additionalDependencies,
  483. m.additionalLibraryDirectories,
  484. m.treatLinkerWarningAsErrors,
  485. m.targetMachine,
  486. m.additionalLinkOptions,
  487. }
  488. else
  489. return {}
  490. end
  491. end
  492. function m.lib(cfg, explicit)
  493. local contents = p.capture(function ()
  494. p.push()
  495. p.callArray(m.elements.lib, cfg, explicit)
  496. p.pop()
  497. end)
  498. if #contents > 0 then
  499. p.push('<Lib>')
  500. p.outln(contents)
  501. p.pop('</Lib>')
  502. end
  503. end
  504. --
  505. -- Write the manifest section.
  506. --
  507. m.elements.manifest = function(cfg)
  508. return {
  509. m.enableDpiAwareness,
  510. m.additionalManifestFiles,
  511. }
  512. end
  513. function m.manifest(cfg)
  514. if cfg.kind ~= p.STATICLIB then
  515. local contents = p.capture(function ()
  516. p.push()
  517. p.callArray(m.elements.manifest, cfg)
  518. p.pop()
  519. end)
  520. if #contents > 0 then
  521. p.push('<Manifest>')
  522. p.outln(contents)
  523. p.pop('</Manifest>')
  524. end
  525. end
  526. end
  527. ---
  528. -- Write out the pre- and post-build event settings.
  529. ---
  530. function m.buildEvents(cfg)
  531. local write = function (event)
  532. local name = event .. "Event"
  533. local field = event:lower()
  534. local steps = cfg[field .. "commands"]
  535. local msg = cfg[field .. "message"]
  536. if #steps > 0 then
  537. steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location)
  538. p.push('<%s>', name)
  539. p.x('<Command>%s</Command>', table.implode(steps, "", "", "\r\n"))
  540. if msg then
  541. p.x('<Message>%s</Message>', msg)
  542. end
  543. p.pop('</%s>', name)
  544. end
  545. end
  546. write("PreBuild")
  547. write("PreLink")
  548. write("PostBuild")
  549. end
  550. ---
  551. -- Transform property to string
  552. ---
  553. function m.getRulePropertyString(rule, prop, value, kind)
  554. -- list of paths
  555. if kind == "list:path" then
  556. return table.concat(vstudio.path(cfg, value), ';')
  557. end
  558. -- path
  559. if kind == "path" then
  560. return vstudio.path(cfg, value)
  561. end
  562. -- list
  563. if type(value) == "table" then
  564. return table.concat(value, ";")
  565. end
  566. -- enum
  567. if prop.values then
  568. value = table.findKeyByValue(prop.values, value)
  569. end
  570. -- primitive
  571. return tostring(value)
  572. end
  573. ---
  574. -- Write out project-level custom rule variables.
  575. ---
  576. function m.ruleVars(cfg)
  577. for i = 1, #cfg.rules do
  578. local rule = p.global.getRule(cfg.rules[i])
  579. local contents = p.capture(function ()
  580. p.push()
  581. for prop in p.rule.eachProperty(rule) do
  582. local fld = p.rule.getPropertyField(rule, prop)
  583. local value = cfg[fld.name]
  584. if value ~= nil then
  585. value = m.getRulePropertyString(rule, prop, value, fld.kind)
  586. if value ~= nil and #value > 0 then
  587. m.element(prop.name, nil, '%s', value)
  588. end
  589. end
  590. end
  591. p.pop()
  592. end)
  593. if #contents > 0 then
  594. p.push('<%s>', rule.name)
  595. p.outln(contents)
  596. p.pop('</%s>', rule.name)
  597. end
  598. end
  599. end
  600. --
  601. -- Reference any managed assemblies listed in the links()
  602. --
  603. function m.assemblyReferences(prj)
  604. -- Visual Studio doesn't support per-config references; use
  605. -- whatever is contained in the first configuration
  606. local cfg = project.getfirstconfig(prj)
  607. local refs = config.getlinks(cfg, "system", "fullpath", "managed")
  608. if #refs > 0 then
  609. p.push('<ItemGroup>')
  610. for i = 1, #refs do
  611. local value = refs[i]
  612. -- If the link contains a '/' then it is a relative path to
  613. -- a local assembly. Otherwise treat it as a system assembly.
  614. if value:find('/', 1, true) then
  615. p.push('<Reference Include="%s">', path.getbasename(value))
  616. p.x('<HintPath>%s</HintPath>', path.translate(value))
  617. p.pop('</Reference>')
  618. else
  619. p.x('<Reference Include="%s" />', path.getbasename(value))
  620. end
  621. end
  622. p.pop('</ItemGroup>')
  623. end
  624. end
  625. function m.generatedFile(cfg, file)
  626. if file.generated then
  627. local path = path.translate(file.dependsOn.relpath)
  628. m.element("AutoGen", nil, 'true')
  629. m.element("DependentUpon", nil, path)
  630. end
  631. end
  632. ---
  633. -- Write out the list of source code files, and any associated configuration.
  634. ---
  635. function m.files(prj)
  636. local groups = m.categorizeSources(prj)
  637. for _, group in ipairs(groups) do
  638. group.category.emitFiles(prj, group)
  639. end
  640. end
  641. m.categories = {}
  642. ---
  643. -- ClInclude group
  644. ---
  645. m.categories.ClInclude = {
  646. name = "ClInclude",
  647. extensions = { ".h", ".hh", ".hpp", ".hxx", ".inl" },
  648. priority = 1,
  649. emitFiles = function(prj, group)
  650. m.emitFiles(prj, group, "ClInclude", {m.generatedFile})
  651. end,
  652. emitFilter = function(prj, group)
  653. m.filterGroup(prj, group, "ClInclude")
  654. end
  655. }
  656. ---
  657. -- ClCompile group
  658. ---
  659. m.categories.ClCompile = {
  660. name = "ClCompile",
  661. extensions = { ".cc", ".cpp", ".cxx", ".c++", ".c", ".s", ".m", ".mm" },
  662. priority = 2,
  663. emitFiles = function(prj, group)
  664. local fileCfgFunc = function(fcfg, condition)
  665. if fcfg then
  666. return {
  667. m.excludedFromBuild,
  668. m.objectFileName,
  669. m.clCompilePreprocessorDefinitions,
  670. m.clCompileUndefinePreprocessorDefinitions,
  671. m.optimization,
  672. m.forceIncludes,
  673. m.precompiledHeader,
  674. m.enableEnhancedInstructionSet,
  675. m.additionalCompileOptions,
  676. m.disableSpecificWarnings,
  677. m.treatSpecificWarningsAsErrors,
  678. m.basicRuntimeChecks,
  679. m.exceptionHandling,
  680. m.compileAsManaged,
  681. m.compileAs,
  682. m.runtimeTypeInfo,
  683. m.warningLevelFile,
  684. }
  685. else
  686. return {
  687. m.excludedFromBuild
  688. }
  689. end
  690. end
  691. m.emitFiles(prj, group, "ClCompile", {m.generatedFile}, fileCfgFunc)
  692. end,
  693. emitFilter = function(prj, group)
  694. m.filterGroup(prj, group, "ClCompile")
  695. end
  696. }
  697. ---
  698. -- FxCompile group
  699. ---
  700. m.categories.FxCompile = {
  701. name = "FxCompile",
  702. extensions = { ".hlsl" },
  703. priority = 4,
  704. emitFiles = function(prj, group)
  705. local fileCfgFunc = function(fcfg, condition)
  706. if fcfg then
  707. return {
  708. m.excludedFromBuild,
  709. m.fxCompilePreprocessorDefinition,
  710. m.fxCompileAdditionalIncludeDirs,
  711. m.fxCompileShaderType,
  712. m.fxCompileShaderModel,
  713. m.fxCompileShaderEntry,
  714. m.fxCompileShaderVariableName,
  715. m.fxCompileShaderHeaderOutput,
  716. m.fxCompileShaderObjectOutput,
  717. m.fxCompileShaderAssembler,
  718. m.fxCompileShaderAssemblerOutput,
  719. m.fxCompileShaderAdditionalOptions,
  720. }
  721. else
  722. return {
  723. m.excludedFromBuild
  724. }
  725. end
  726. end
  727. m.emitFiles(prj, group, "FxCompile", nil, fileCfgFunc)
  728. end,
  729. emitFilter = function(prj, group)
  730. m.filterGroup(prj, group, "FxCompile")
  731. end
  732. }
  733. ---
  734. -- None group
  735. ---
  736. m.categories.None = {
  737. name = "None",
  738. priority = 5,
  739. emitFiles = function(prj, group)
  740. m.emitFiles(prj, group, "None", {m.generatedFile})
  741. end,
  742. emitFilter = function(prj, group)
  743. m.filterGroup(prj, group, "None")
  744. end
  745. }
  746. ---
  747. -- ResourceCompile group
  748. ---
  749. m.categories.ResourceCompile = {
  750. name = "ResourceCompile",
  751. extensions = ".rc",
  752. priority = 6,
  753. emitFiles = function(prj, group)
  754. local fileCfgFunc = {
  755. m.excludedFromBuild
  756. }
  757. m.emitFiles(prj, group, "ResourceCompile", nil, fileCfgFunc)
  758. end,
  759. emitFilter = function(prj, group)
  760. m.filterGroup(prj, group, "ResourceCompile")
  761. end
  762. }
  763. ---
  764. -- CustomBuild group
  765. ---
  766. m.categories.CustomBuild = {
  767. name = "CustomBuild",
  768. priority = 7,
  769. emitFiles = function(prj, group)
  770. local fileFunc = {
  771. m.fileType
  772. }
  773. local fileCfgFunc = {
  774. m.excludedFromBuild,
  775. m.buildCommands,
  776. m.buildOutputs,
  777. m.linkObjects,
  778. m.buildMessage,
  779. m.buildAdditionalInputs
  780. }
  781. m.emitFiles(prj, group, "CustomBuild", fileFunc, fileCfgFunc, function (cfg, fcfg)
  782. return fileconfig.hasCustomBuildRule(fcfg)
  783. end)
  784. end,
  785. emitFilter = function(prj, group)
  786. m.filterGroup(prj, group, "CustomBuild")
  787. end
  788. }
  789. ---
  790. -- Midl group
  791. ---
  792. m.categories.Midl = {
  793. name = "Midl",
  794. extensions = ".idl",
  795. priority = 8,
  796. emitFiles = function(prj, group)
  797. local fileCfgFunc = {
  798. m.excludedFromBuild
  799. }
  800. m.emitFiles(prj, group, "Midl", nil, fileCfgFunc, function(cfg)
  801. return cfg.system == p.WINDOWS
  802. end)
  803. end,
  804. emitFilter = function(prj, group)
  805. m.filterGroup(prj, group, "Midl")
  806. end
  807. }
  808. ---
  809. -- Masm group
  810. ---
  811. m.categories.Masm = {
  812. name = "Masm",
  813. extensions = ".asm",
  814. priority = 9,
  815. emitFiles = function(prj, group)
  816. local fileCfgFunc = function(fcfg, condition)
  817. if fcfg then
  818. return {
  819. m.MasmPreprocessorDefinitions,
  820. m.excludedFromBuild,
  821. m.exceptionHandlingSEH,
  822. }
  823. else
  824. return {
  825. m.excludedFromBuild
  826. }
  827. end
  828. end
  829. m.emitFiles(prj, group, "Masm", nil, fileCfgFunc)
  830. end,
  831. emitFilter = function(prj, group)
  832. m.filterGroup(prj, group, "Masm")
  833. end,
  834. emitExtensionSettings = function(prj, group)
  835. p.w('<Import Project="$(VCTargetsPath)\\BuildCustomizations\\masm.props" />')
  836. end,
  837. emitExtensionTargets = function(prj, group)
  838. p.w('<Import Project="$(VCTargetsPath)\\BuildCustomizations\\masm.targets" />')
  839. end
  840. }
  841. ---
  842. -- Image group
  843. ---
  844. m.categories.Image = {
  845. name = "Image",
  846. extensions = { ".gif", ".jpg", ".jpe", ".png", ".bmp", ".dib", "*.tif", "*.wmf", "*.ras", "*.eps", "*.pcx", "*.pcd", "*.tga", "*.dds" },
  847. priority = 10,
  848. emitFiles = function(prj, group)
  849. local fileCfgFunc = function(fcfg, condition)
  850. return {
  851. m.excludedFromBuild
  852. }
  853. end
  854. m.emitFiles(prj, group, "Image", nil, fileCfgFunc)
  855. end,
  856. emitFilter = function(prj, group)
  857. m.filterGroup(prj, group, "Image")
  858. end
  859. }
  860. ---
  861. -- Natvis group
  862. ---
  863. m.categories.Natvis = {
  864. name = "Natvis",
  865. extensions = { ".natvis" },
  866. priority = 11,
  867. emitFiles = function(prj, group)
  868. m.emitFiles(prj, group, "Natvis", {m.generatedFile})
  869. end,
  870. emitFilter = function(prj, group)
  871. m.filterGroup(prj, group, "Natvis")
  872. end
  873. }
  874. ---
  875. -- Categorize files into groups.
  876. ---
  877. function m.categorizeSources(prj)
  878. -- if we already did this, return the cached result.
  879. if prj._vc2010_sources then
  880. return prj._vc2010_sources
  881. end
  882. -- build the new group table.
  883. local result = {}
  884. local groups = {}
  885. prj._vc2010_sources = result
  886. local tr = project.getsourcetree(prj)
  887. tree.traverse(tr, {
  888. onleaf = function(node)
  889. local cat = m.categorizeFile(prj, node)
  890. groups[cat.name] = groups[cat.name] or {
  891. category = cat,
  892. files = {}
  893. }
  894. table.insert(groups[cat.name].files, node)
  895. end
  896. })
  897. -- sort by relative-to path; otherwise VS will reorder the files
  898. for name, group in pairs(groups) do
  899. table.sort(group.files, function (a, b)
  900. return a.relpath < b.relpath
  901. end)
  902. table.insert(result, group)
  903. end
  904. -- sort by category priority then name; so we get stable results.
  905. table.sort(result, function (a, b)
  906. if (a.category.priority == b.category.priority) then
  907. return a.category.name < b.category.name
  908. end
  909. return a.category.priority < b.category.priority
  910. end)
  911. return result
  912. end
  913. function m.categorizeFile(prj, file)
  914. for cfg in project.eachconfig(prj) do
  915. local fcfg = fileconfig.getconfig(file, cfg)
  916. if fcfg then
  917. -- If any configuration for this file uses a custom build step, that's the category to use
  918. if fileconfig.hasCustomBuildRule(fcfg) then
  919. return m.categories.CustomBuild
  920. end
  921. -- also check for buildaction
  922. if fcfg.buildaction then
  923. return m.categories[fcfg.buildaction] or m.categories.None
  924. end
  925. end
  926. end
  927. -- If there is a custom rule associated with it, use that
  928. local rule = p.global.getRuleForFile(file.name, prj.rules)
  929. if rule then
  930. return {
  931. name = rule.name,
  932. priority = 100,
  933. rule = rule,
  934. emitFiles = function(prj, group)
  935. m.emitRuleFiles(prj, group)
  936. end,
  937. emitFilter = function(prj, group)
  938. m.filterGroup(prj, group, group.category.name)
  939. end
  940. }
  941. end
  942. -- Otherwise use the file extension to deduce a category
  943. for _, cat in pairs(m.categories) do
  944. if cat.extensions and path.hasextension(file.name, cat.extensions) then
  945. return cat
  946. end
  947. end
  948. return m.categories.None
  949. end
  950. function m.configPair(cfg)
  951. return vstudio.projectPlatform(cfg) .. "|" .. vstudio.archFromConfig(cfg, true)
  952. end
  953. function m.getTotalCfgCount(prj)
  954. if prj._totalCfgCount then
  955. return prj._totalCfgCount
  956. else
  957. local result = 0
  958. for _ in p.project.eachconfig(prj) do
  959. result = result + 1
  960. end
  961. -- cache result
  962. prj._totalCfgCount = result
  963. return result
  964. end
  965. end
  966. function m.indexConditionalElements()
  967. local nameMap, nameList, settingList
  968. nameMap = {}
  969. nameList = {} -- to preserve ordering
  970. settingList = {} -- to preserve ordering
  971. for _, element in ipairs(m.conditionalElements) do
  972. local settingMap = nameMap[element.name]
  973. if not settingMap then
  974. settingMap = {}
  975. nameMap[element.name] = settingMap
  976. if not table.contains(nameList, element.name) then
  977. table.insert(nameList, element.name)
  978. end
  979. end
  980. --setting will either be value or args
  981. local elementSet = settingMap[element.setting]
  982. if elementSet then
  983. table.insert(elementSet, element)
  984. else
  985. elementSet = {element}
  986. settingMap[element.setting] = elementSet
  987. if not table.contains(settingList, element.setting) then
  988. table.insert(settingList, element.setting)
  989. end
  990. end
  991. end
  992. return nameMap, nameList, settingList
  993. end
  994. function m.emitConditionalElements(prj)
  995. local keyCount = function(tbl)
  996. local count = 0
  997. for _ in pairs(tbl) do count = count + 1 end
  998. return count
  999. end
  1000. local nameMap, nameList, settingList
  1001. nameMap, nameList, settingList = m.indexConditionalElements()
  1002. local totalCfgCount = m.getTotalCfgCount(prj)
  1003. for _, name in ipairs(nameList) do
  1004. local settingMap = nameMap[name]
  1005. local done = false
  1006. if keyCount(settingMap)==1 then
  1007. for _, setting in ipairs(settingList) do
  1008. local elements = settingMap[setting]
  1009. if elements~=nil and #elements==totalCfgCount then
  1010. local element = elements[1]
  1011. local format = string.format('<%s>%s</%s>', name, element.value, name)
  1012. p.w(format, table.unpack(element.args))
  1013. done = true
  1014. end
  1015. end
  1016. end
  1017. if not done then
  1018. for _, setting in ipairs(settingList) do
  1019. local elements = settingMap[setting]
  1020. if elements then
  1021. for _, element in ipairs(elements) do
  1022. local format = string.format('<%s %s>%s</%s>', name, m.conditionFromConfigText(element.condition), element.value, name)
  1023. p.w(format, table.unpack(element.args))
  1024. end
  1025. end
  1026. end
  1027. end
  1028. end
  1029. end
  1030. function m.emitFiles(prj, group, tag, fileFunc, fileCfgFunc, checkFunc)
  1031. local files = group.files
  1032. if files and #files > 0 then
  1033. p.push('<ItemGroup>')
  1034. for _, file in ipairs(files) do
  1035. local contents = p.capture(function ()
  1036. p.push()
  1037. p.callArray(fileFunc, cfg, file)
  1038. m.conditionalElements = {}
  1039. for cfg in project.eachconfig(prj) do
  1040. local fcfg = fileconfig.getconfig(file, cfg)
  1041. if not checkFunc or checkFunc(cfg, fcfg) then
  1042. p.callArray(fileCfgFunc, fcfg, m.configPair(cfg))
  1043. end
  1044. end
  1045. if #m.conditionalElements > 0 then
  1046. m.emitConditionalElements(prj)
  1047. end
  1048. p.pop()
  1049. end)
  1050. local rel = path.translate(file.relpath)
  1051. -- SharedItems projects paths are prefixed with a magical variable
  1052. if prj.kind == p.SHAREDITEMS then
  1053. rel = "$(MSBuildThisFileDirectory)" .. rel
  1054. end
  1055. if #contents > 0 then
  1056. p.push('<%s Include="%s">', tag, rel)
  1057. p.outln(contents)
  1058. p.pop('</%s>', tag)
  1059. else
  1060. p.x('<%s Include="%s" />', tag, rel)
  1061. end
  1062. end
  1063. p.pop('</ItemGroup>')
  1064. end
  1065. end
  1066. function m.emitRuleFiles(prj, group)
  1067. local files = group.files
  1068. local rule = group.category.rule
  1069. if files and #files > 0 then
  1070. p.push('<ItemGroup>')
  1071. for _, file in ipairs(files) do
  1072. local contents = p.capture(function()
  1073. p.push()
  1074. for prop in p.rule.eachProperty(rule) do
  1075. local fld = p.rule.getPropertyField(rule, prop)
  1076. m.conditionalElements = {}
  1077. for cfg in project.eachconfig(prj) do
  1078. local fcfg = fileconfig.getconfig(file, cfg)
  1079. if fcfg and fcfg[fld.name] then
  1080. local value = m.getRulePropertyString(rule, prop, fcfg[fld.name])
  1081. if value and #value > 0 then
  1082. m.element(prop.name, m.configPair(cfg), '%s', value)
  1083. end
  1084. end
  1085. end
  1086. if #m.conditionalElements > 0 then
  1087. m.emitConditionalElements(prj)
  1088. end
  1089. end
  1090. p.pop()
  1091. end)
  1092. if #contents > 0 then
  1093. p.push('<%s Include=\"%s\">', rule.name, path.translate(file.relpath))
  1094. p.outln(contents)
  1095. p.pop('</%s>', rule.name)
  1096. else
  1097. p.x('<%s Include=\"%s\" />', rule.name, path.translate(file.relpath))
  1098. end
  1099. end
  1100. p.pop('</ItemGroup>')
  1101. end
  1102. end
  1103. function m.isClrMixed(prj)
  1104. -- check to see if any files are marked with clr
  1105. local isMixed = false
  1106. if not prj.clr or prj.clr == p.OFF then
  1107. if prj._isClrMixed ~= nil then
  1108. isMixed = prj._isClrMixed
  1109. else
  1110. table.foreachi(prj._.files, function(file)
  1111. for cfg in p.project.eachconfig(prj) do
  1112. local fcfg = p.fileconfig.getconfig(file, cfg)
  1113. if fcfg and fcfg.clr and fcfg.clr ~= p.OFF then
  1114. isMixed = true
  1115. end
  1116. end
  1117. end)
  1118. prj._isClrMixed = isMixed -- cache the results
  1119. end
  1120. end
  1121. return isMixed
  1122. end
  1123. --
  1124. -- Generate the list of project dependencies.
  1125. --
  1126. m.elements.projectReferences = function(prj, ref)
  1127. if prj.clr ~= p.OFF or (m.isClrMixed(prj) and ref and ref.kind ~=p.STATICLIB) then
  1128. return {
  1129. m.referenceProject,
  1130. m.referencePrivate,
  1131. m.referenceOutputAssembly,
  1132. m.referenceCopyLocalSatelliteAssemblies,
  1133. m.referenceLinkLibraryDependencies,
  1134. m.referenceUseLibraryDependences,
  1135. }
  1136. else
  1137. return {
  1138. m.referenceProject,
  1139. }
  1140. end
  1141. end
  1142. function m.projectReferences(prj)
  1143. local refs = project.getdependencies(prj, 'linkOnly')
  1144. -- Handle linked shared items projects
  1145. local contents = p.capture(function()
  1146. p.push()
  1147. for _, ref in ipairs(refs) do
  1148. if ref.kind == p.SHAREDITEMS then
  1149. local relpath = vstudio.path(prj, vstudio.projectfile(ref))
  1150. p.x('<Import Project="%s" Label="Shared" />', relpath)
  1151. end
  1152. end
  1153. p.pop()
  1154. end)
  1155. if #contents > 0 then
  1156. p.push('<ImportGroup Label="Shared">')
  1157. p.outln(contents)
  1158. p.pop('</ImportGroup>')
  1159. end
  1160. -- Handle all other linked projects
  1161. local contents = p.capture(function()
  1162. p.push()
  1163. for _, ref in ipairs(refs) do
  1164. if ref.kind ~= p.SHAREDITEMS then
  1165. local relpath = vstudio.path(prj, vstudio.projectfile(ref))
  1166. p.push('<ProjectReference Include=\"%s\">', relpath)
  1167. p.callArray(m.elements.projectReferences, prj, ref)
  1168. p.pop('</ProjectReference>')
  1169. end
  1170. end
  1171. p.pop()
  1172. end)
  1173. if #contents > 0 then
  1174. p.push('<ItemGroup>')
  1175. p.outln(contents)
  1176. p.pop('</ItemGroup>')
  1177. end
  1178. end
  1179. ---------------------------------------------------------------------------
  1180. --
  1181. -- Handlers for individual project elements
  1182. --
  1183. ---------------------------------------------------------------------------
  1184. function m.additionalDependencies(cfg, explicit)
  1185. local links
  1186. -- check to see if this project uses an external toolset. If so, let the
  1187. -- toolset define the format of the links
  1188. local toolset = config.toolset(cfg)
  1189. if cfg.system ~= premake.WINDOWS and toolset then
  1190. links = toolset.getlinks(cfg, not explicit)
  1191. else
  1192. links = vstudio.getLinks(cfg, explicit)
  1193. end
  1194. if #links > 0 then
  1195. links = path.translate(table.concat(links, ";"))
  1196. m.element("AdditionalDependencies", nil, "%s;%%(AdditionalDependencies)", links)
  1197. end
  1198. end
  1199. function m.additionalIncludeDirectories(cfg, includedirs)
  1200. if #includedirs > 0 then
  1201. local dirs = vstudio.path(cfg, includedirs)
  1202. if #dirs > 0 then
  1203. m.element("AdditionalIncludeDirectories", nil, "%s;%%(AdditionalIncludeDirectories)", table.concat(dirs, ";"))
  1204. end
  1205. end
  1206. end
  1207. function m.additionalLibraryDirectories(cfg)
  1208. if #cfg.libdirs > 0 then
  1209. local dirs = table.concat(vstudio.path(cfg, cfg.libdirs), ";")
  1210. m.element("AdditionalLibraryDirectories", nil, "%s;%%(AdditionalLibraryDirectories)", dirs)
  1211. end
  1212. end
  1213. function m.additionalManifestFiles(cfg)
  1214. -- get the manifests files
  1215. local manifests = {}
  1216. for _, fname in ipairs(cfg.files) do
  1217. if path.getextension(fname) == ".manifest" then
  1218. table.insert(manifests, project.getrelative(cfg.project, fname))
  1219. end
  1220. end
  1221. if #manifests > 0 then
  1222. m.element("AdditionalManifestFiles", nil, "%s;%%(AdditionalManifestFiles)", table.concat(manifests, ";"))
  1223. end
  1224. end
  1225. function m.additionalUsingDirectories(cfg)
  1226. if #cfg.usingdirs > 0 then
  1227. local dirs = vstudio.path(cfg, cfg.usingdirs)
  1228. if #dirs > 0 then
  1229. m.element("AdditionalUsingDirectories", nil, "%s;%%(AdditionalUsingDirectories)", table.concat(dirs, ";"))
  1230. end
  1231. end
  1232. end
  1233. function m.dataExecutionPrevention(cfg) --OpenMPT
  1234. if (cfg.dataexecutionprevention == 'Off') then --OpenMPT
  1235. m.element("DataExecutionPrevention", nil, 'false') --OpenMPT
  1236. end --OpenMPT
  1237. end --OpenMPT
  1238. function m.largeAddressAware(cfg)
  1239. if (cfg.largeaddressaware == true) then
  1240. m.element("LargeAddressAware", nil, 'true')
  1241. end
  1242. end
  1243. function m.languageStandard(cfg)
  1244. if _ACTION >= "vs2022" then --OpenMPT
  1245. if (cfg.cppdialect == "C++14") then --OpenMPT
  1246. m.element("LanguageStandard", nil, 'stdcpp14') --OpenMPT
  1247. elseif (cfg.cppdialect == "C++17") then --OpenMPT
  1248. m.element("LanguageStandard", nil, 'stdcpp17') --OpenMPT
  1249. elseif (cfg.cppdialect == "C++20") then --OpenMPT
  1250. m.element("LanguageStandard", nil, 'stdcpp20') --OpenMPT
  1251. elseif (cfg.cppdialect == "C++latest") then --OpenMPT
  1252. m.element("LanguageStandard", nil, 'stdcpplatest') --OpenMPT
  1253. end --OpenMPT
  1254. else --OpenMPT
  1255. if _ACTION >= "vs2017" then
  1256. if (cfg.cppdialect == "C++14") then
  1257. m.element("LanguageStandard", nil, 'stdcpp14')
  1258. elseif (cfg.cppdialect == "C++17") then
  1259. m.element("LanguageStandard", nil, 'stdcpp17')
  1260. elseif (cfg.cppdialect == "C++20") then
  1261. m.element("LanguageStandard", nil, 'stdcpplatest')
  1262. elseif (cfg.cppdialect == "C++latest") then
  1263. m.element("LanguageStandard", nil, 'stdcpplatest')
  1264. end
  1265. end
  1266. end --OpenMPT
  1267. end
  1268. function m.conformanceMode(cfg)
  1269. if _ACTION >= "vs2017" then
  1270. if cfg.conformancemode ~= nil then
  1271. if cfg.conformancemode then
  1272. m.element("ConformanceMode", nil, "true")
  1273. else
  1274. m.element("ConformanceMode", nil, "false")
  1275. end
  1276. end
  1277. end
  1278. end
  1279. function m.structMemberAlignment(cfg)
  1280. local map = {
  1281. [1] = "1Byte",
  1282. [2] = "2Bytes",
  1283. [4] = "4Bytes",
  1284. [8] = "8Bytes",
  1285. [16] = "16Bytes"
  1286. }
  1287. local value = map[cfg.structmemberalign]
  1288. if value then
  1289. m.element("StructMemberAlignment", nil, value)
  1290. end
  1291. end
  1292. function m.useFullPaths(cfg)
  1293. if cfg.useFullPaths ~= nil then
  1294. if cfg.useFullPaths then
  1295. m.element("UseFullPaths", nil, "true")
  1296. else
  1297. m.element("UseFullPaths", nil, "false")
  1298. end
  1299. end
  1300. end
  1301. function m.removeUnreferencedCodeData(cfg)
  1302. if cfg.removeUnreferencedCodeData ~= nil then
  1303. if cfg.removeUnreferencedCodeData then
  1304. m.element("RemoveUnreferencedCodeData", nil, "true")
  1305. else
  1306. m.element("RemoveUnreferencedCodeData", nil, "false")
  1307. end
  1308. end
  1309. end
  1310. function m.additionalCompileOptions(cfg, condition)
  1311. local opts = cfg.buildoptions
  1312. if _ACTION == "vs2015" or vstudio.isMakefile(cfg) then
  1313. if (cfg.cppdialect == "C++14") then
  1314. table.insert(opts, "/std:c++14")
  1315. elseif (cfg.cppdialect == "C++17") then
  1316. table.insert(opts, "/std:c++17")
  1317. elseif (cfg.cppdialect == "C++20") then
  1318. table.insert(opts, "/std:c++latest")
  1319. elseif (cfg.cppdialect == "C++latest") then
  1320. table.insert(opts, "/std:c++latest")
  1321. end
  1322. end
  1323. if cfg.toolset and cfg.toolset:startswith("msc") then
  1324. local value = iif(cfg.unsignedchar, "On", "Off")
  1325. table.insert(opts, p.tools.msc.shared.unsignedchar[value])
  1326. elseif _ACTION >= "vs2019" and cfg.toolset and cfg.toolset == "clang" then
  1327. local value = iif(cfg.unsignedchar, "On", "Off")
  1328. table.insert(opts, p.tools.msc.shared.unsignedchar[value])
  1329. end
  1330. if #opts > 0 then
  1331. opts = table.concat(opts, " ")
  1332. m.element("AdditionalOptions", condition, '%s %%(AdditionalOptions)', opts)
  1333. end
  1334. end
  1335. function m.additionalLinkOptions(cfg)
  1336. if #cfg.linkoptions > 0 then
  1337. local opts = table.concat(cfg.linkoptions, " ")
  1338. m.element("AdditionalOptions", nil, "%s %%(AdditionalOptions)", opts)
  1339. end
  1340. end
  1341. function m.compileAsManaged(fcfg, condition)
  1342. if fcfg.clr and fcfg ~= p.OFF then
  1343. m.element("CompileAsManaged", condition, "true")
  1344. end
  1345. end
  1346. function m.basicRuntimeChecks(cfg, condition)
  1347. local prjcfg, filecfg = p.config.normalize(cfg)
  1348. local runtime = config.getruntime(prjcfg) or iif(config.isDebugBuild(cfg), "Debug", "Release")
  1349. if filecfg then
  1350. if filecfg.flags.NoRuntimeChecks or (config.isOptimizedBuild(filecfg) and runtime:endswith("Debug")) then
  1351. m.element("BasicRuntimeChecks", condition, "Default")
  1352. end
  1353. else
  1354. if prjcfg.flags.NoRuntimeChecks or (config.isOptimizedBuild(prjcfg) and runtime:endswith("Debug")) then
  1355. m.element("BasicRuntimeChecks", nil, "Default")
  1356. end
  1357. end
  1358. end
  1359. function m.buildInputs(cfg, condition)
  1360. if cfg.buildinputs and #cfg.buildinputs > 0 then
  1361. local inputs = project.getrelative(cfg.project, cfg.buildinputs)
  1362. m.element("Inputs", condition, '%s', table.concat(inputs, ";"))
  1363. end
  1364. end
  1365. function m.buildAdditionalInputs(fcfg, condition)
  1366. if fcfg.buildinputs and #fcfg.buildinputs > 0 then
  1367. local inputs = project.getrelative(fcfg.project, fcfg.buildinputs)
  1368. m.element("AdditionalInputs", condition, '%s', table.concat(inputs, ";"))
  1369. end
  1370. end
  1371. function m.buildCommands(fcfg, condition)
  1372. if #fcfg.buildcommands > 0 then
  1373. local commands = os.translateCommandsAndPaths(fcfg.buildcommands, fcfg.project.basedir, fcfg.project.location)
  1374. m.element("Command", condition, '%s', table.concat(commands,'\r\n'))
  1375. end
  1376. end
  1377. function m.buildLog(cfg)
  1378. if cfg.buildlog and #cfg.buildlog > 0 then
  1379. p.push('<BuildLog>')
  1380. m.element("Path", nil, "%s", vstudio.path(cfg, cfg.buildlog))
  1381. p.pop('</BuildLog>')
  1382. end
  1383. end
  1384. function m.buildMessage(fcfg, condition)
  1385. if fcfg.buildmessage then
  1386. m.element("Message", condition, '%s', fcfg.buildmessage)
  1387. end
  1388. end
  1389. function m.buildOutputs(fcfg, condition)
  1390. if #fcfg.buildoutputs > 0 then
  1391. local outputs = project.getrelative(fcfg.project, fcfg.buildoutputs)
  1392. m.element("Outputs", condition, '%s', table.concat(outputs, ";"))
  1393. end
  1394. end
  1395. function m.linkObjects(fcfg, condition)
  1396. if fcfg.linkbuildoutputs ~= nil then
  1397. m.element("LinkObjects", condition, tostring(fcfg.linkbuildoutputs))
  1398. end
  1399. end
  1400. function m.characterSet(cfg)
  1401. if not vstudio.isMakefile(cfg) then
  1402. local charactersets = {
  1403. ASCII = "NotSet",
  1404. MBCS = "MultiByte",
  1405. Unicode = "Unicode",
  1406. Default = "Unicode"
  1407. }
  1408. m.element("CharacterSet", nil, charactersets[cfg.characterset])
  1409. end
  1410. end
  1411. function m.wholeProgramOptimization(cfg)
  1412. if cfg.flags.LinkTimeOptimization then
  1413. m.element("WholeProgramOptimization", nil, "true")
  1414. end
  1415. end
  1416. function m.spectreMitigations(cfg) --OpenMPT
  1417. if (cfg.spectremitigations == 'On') then --OpenMPT
  1418. if _ACTION >= "vs2017" then --OpenMPT
  1419. m.element("SpectreMitigation", nil, "Spectre") --OpenMPT
  1420. end --OpenMPT
  1421. end --OpenMPT
  1422. end --OpenMPT
  1423. function m.clCompileAdditionalIncludeDirectories(cfg)
  1424. m.additionalIncludeDirectories(cfg, cfg.includedirs)
  1425. end
  1426. function m.clCompileAdditionalUsingDirectories(cfg)
  1427. m.additionalUsingDirectories(cfg, cfg.usingdirs)
  1428. end
  1429. function m.clCompilePreprocessorDefinitions(cfg, condition)
  1430. local defines = cfg.defines
  1431. if cfg.exceptionhandling == p.OFF then
  1432. defines = table.join(defines, "_HAS_EXCEPTIONS=0")
  1433. end
  1434. m.preprocessorDefinitions(cfg, defines, false, condition)
  1435. end
  1436. function m.clCompileUndefinePreprocessorDefinitions(cfg, condition)
  1437. m.undefinePreprocessorDefinitions(cfg, cfg.undefines, false, condition)
  1438. end
  1439. function m.clrSupport(cfg)
  1440. local value
  1441. if cfg.clr == "On" or cfg.clr == "Unsafe" then
  1442. value = "true"
  1443. elseif cfg.clr ~= p.OFF then
  1444. value = cfg.clr
  1445. end
  1446. if value then
  1447. m.element("CLRSupport", nil, value)
  1448. end
  1449. end
  1450. function m.compileAs(cfg, condition)
  1451. if p.languages.isc(cfg.compileas) then
  1452. m.element("CompileAs", condition, "CompileAsC")
  1453. elseif p.languages.iscpp(cfg.compileas) then
  1454. m.element("CompileAs", condition, "CompileAsCpp")
  1455. elseif cfg.compileas == "Module" then
  1456. m.element("CompileAs", condition, "CompileAsCppModule")
  1457. elseif cfg.compileas == "ModulePartition" then
  1458. m.element("CompileAs", condition, "CompileAsCppModuleInternalPartition")
  1459. elseif cfg.compileas == "HeaderUnit" then
  1460. m.element("CompileAs", condition, "CompileAsHeaderUnit")
  1461. end
  1462. end
  1463. function m.configurationType(cfg)
  1464. local types = {
  1465. SharedLib = "DynamicLibrary",
  1466. StaticLib = "StaticLibrary",
  1467. ConsoleApp = "Application",
  1468. WindowedApp = "Application",
  1469. Makefile = "Makefile",
  1470. None = "Makefile",
  1471. Utility = "Utility",
  1472. }
  1473. m.element("ConfigurationType", nil, types[cfg.kind])
  1474. end
  1475. function m.culture(cfg)
  1476. local value = vstudio.cultureForLocale(cfg.locale)
  1477. if value then
  1478. m.element("Culture", nil, "0x%04x", tostring(value))
  1479. end
  1480. end
  1481. function m.debugInformationFormat(cfg)
  1482. local value
  1483. local tool, toolVersion = p.config.toolset(cfg)
  1484. if (cfg.symbols == p.ON) or (cfg.symbols == "FastLink") or (cfg.symbols == "Full") then
  1485. if cfg.debugformat == "c7" then
  1486. value = "OldStyle"
  1487. elseif (cfg.architecture == "x86_64" and _ACTION < "vs2015") or
  1488. cfg.clr ~= p.OFF or
  1489. config.isOptimizedBuild(cfg) or
  1490. cfg.editandcontinue == p.OFF or
  1491. (toolVersion and toolVersion:startswith("LLVM-vs"))
  1492. then
  1493. value = "ProgramDatabase"
  1494. else
  1495. value = "EditAndContinue"
  1496. end
  1497. m.element("DebugInformationFormat", nil, value)
  1498. elseif cfg.symbols == p.OFF then
  1499. -- leave field blank for vs2013 and older to workaround bug
  1500. if _ACTION < "vs2015" then
  1501. value = ""
  1502. else
  1503. value = "None"
  1504. end
  1505. m.element("DebugInformationFormat", nil, value)
  1506. end
  1507. end
  1508. function m.enableDpiAwareness(cfg)
  1509. local awareness = {
  1510. None = "false",
  1511. High = "true",
  1512. HighPerMonitor = "PerMonitorHighDPIAware",
  1513. }
  1514. local value = awareness[cfg.dpiawareness]
  1515. if value then
  1516. m.element("EnableDpiAwareness", nil, value)
  1517. end
  1518. end
  1519. function m.enableEnhancedInstructionSet(cfg, condition)
  1520. local v
  1521. local x = cfg.vectorextensions
  1522. if x == "AVX" and _ACTION > "vs2010" then
  1523. v = "AdvancedVectorExtensions"
  1524. elseif x == "AVX2" and _ACTION > "vs2012" then
  1525. v = "AdvancedVectorExtensions2"
  1526. elseif cfg.architecture ~= "x86_64" then
  1527. if x == "SSE2" or x == "SSE3" or x == "SSSE3" or x == "SSE4.1" or x == "SSE4.2" then
  1528. v = "StreamingSIMDExtensions2"
  1529. elseif x == "SSE" then
  1530. v = "StreamingSIMDExtensions"
  1531. elseif x == "IA32" and _ACTION > "vs2010" then
  1532. v = "NoExtensions"
  1533. end
  1534. end
  1535. if v then
  1536. m.element('EnableEnhancedInstructionSet', condition, v)
  1537. end
  1538. end
  1539. function m.entryPointSymbol(cfg)
  1540. if cfg.entrypoint then
  1541. m.element("EntryPointSymbol", nil, cfg.entrypoint)
  1542. end
  1543. end
  1544. function m.exceptionHandling(cfg, condition)
  1545. if cfg.exceptionhandling == p.OFF then
  1546. m.element("ExceptionHandling", condition, "false")
  1547. elseif cfg.exceptionhandling == "SEH" then
  1548. m.element("ExceptionHandling", condition, "Async")
  1549. elseif cfg.exceptionhandling == "On" then
  1550. m.element("ExceptionHandling", condition, "Sync")
  1551. elseif cfg.exceptionhandling == "CThrow" then
  1552. m.element("ExceptionHandling", condition, "SyncCThrow")
  1553. end
  1554. end
  1555. function m.excludedFromBuild(filecfg, condition)
  1556. if not filecfg or filecfg.flags.ExcludeFromBuild then
  1557. m.element("ExcludedFromBuild", condition, "true")
  1558. end
  1559. end
  1560. function m.exceptionHandlingSEH(filecfg, condition)
  1561. if not filecfg or filecfg.exceptionhandling == "SEH" then
  1562. m.element("UseSafeExceptionHandlers", condition, "true")
  1563. end
  1564. end
  1565. function m.extensionsToDeleteOnClean(cfg)
  1566. if #cfg.cleanextensions > 0 then
  1567. local value = table.implode(cfg.cleanextensions, "*", ";", "")
  1568. m.element("ExtensionsToDeleteOnClean", nil, value .. "$(ExtensionsToDeleteOnClean)")
  1569. end
  1570. end
  1571. function m.fileType(cfg, file)
  1572. m.element("FileType", nil, "Document")
  1573. end
  1574. function m.floatingPointModel(cfg)
  1575. if cfg.floatingpoint and cfg.floatingpoint ~= "Default" then
  1576. m.element("FloatingPointModel", nil, cfg.floatingpoint)
  1577. end
  1578. end
  1579. function m.floatingPointExceptions(cfg)
  1580. if cfg.floatingpointexceptions ~= nil then
  1581. if cfg.floatingpointexceptions then
  1582. m.element("FloatingPointExceptions", nil, "true")
  1583. else
  1584. m.element("FloatingPointExceptions", nil, "false")
  1585. end
  1586. end
  1587. end
  1588. function m.inlineFunctionExpansion(cfg)
  1589. if cfg.inlining then
  1590. local types = {
  1591. Default = "Default",
  1592. Disabled = "Disabled",
  1593. Explicit = "OnlyExplicitInline",
  1594. Auto = "AnySuitable",
  1595. }
  1596. m.element("InlineFunctionExpansion", nil, types[cfg.inlining])
  1597. end
  1598. end
  1599. function m.forceIncludes(cfg, condition)
  1600. if #cfg.forceincludes > 0 then
  1601. local includes = vstudio.path(cfg, cfg.forceincludes)
  1602. if #includes > 0 then
  1603. m.element("ForcedIncludeFiles", condition, table.concat(includes, ';'))
  1604. end
  1605. end
  1606. if #cfg.forceusings > 0 then
  1607. local usings = vstudio.path(cfg, cfg.forceusings)
  1608. if #usings > 0 then
  1609. m.element("ForcedUsingFiles", condition, table.concat(usings, ';'))
  1610. end
  1611. end
  1612. end
  1613. function m.fullProgramDatabaseFile(cfg)
  1614. if _ACTION >= "vs2015" and cfg.symbols == "FastLink" then
  1615. m.element("FullProgramDatabaseFile", nil, "true")
  1616. end
  1617. end
  1618. function m.assemblyDebug(cfg)
  1619. if cfg.assemblydebug then
  1620. m.element("AssemblyDebug", nil, "true")
  1621. end
  1622. end
  1623. function m.functionLevelLinking(cfg)
  1624. if cfg.functionlevellinking ~= nil then
  1625. if cfg.functionlevellinking then
  1626. m.element("FunctionLevelLinking", nil, "true")
  1627. else
  1628. m.element("FunctionLevelLinking", nil, "false")
  1629. end
  1630. elseif config.isOptimizedBuild(cfg) then
  1631. m.element("FunctionLevelLinking", nil, "true")
  1632. end
  1633. end
  1634. function m.generateDebugInformation(cfg)
  1635. local lookup = {}
  1636. if _ACTION >= "vs2017" then
  1637. lookup[p.ON] = "true"
  1638. lookup[p.OFF] = "false"
  1639. lookup["FastLink"] = "DebugFastLink"
  1640. lookup["Full"] = "DebugFull"
  1641. elseif _ACTION == "vs2015" then
  1642. lookup[p.ON] = "true"
  1643. lookup[p.OFF] = "false"
  1644. lookup["FastLink"] = "DebugFastLink"
  1645. lookup["Full"] = "true"
  1646. else
  1647. lookup[p.ON] = "true"
  1648. lookup[p.OFF] = "false"
  1649. lookup["FastLink"] = "true"
  1650. lookup["Full"] = "true"
  1651. end
  1652. local value = lookup[cfg.symbols]
  1653. if value then
  1654. m.element("GenerateDebugInformation", nil, value)
  1655. end
  1656. end
  1657. function m.generateManifest(cfg)
  1658. if cfg.flags.NoManifest then
  1659. m.element("GenerateManifest", nil, "false")
  1660. end
  1661. end
  1662. function m.generateMapFile(cfg)
  1663. if cfg.flags.Maps then
  1664. m.element("GenerateMapFile", nil, "true")
  1665. end
  1666. end
  1667. function m.ignoreDefaultLibraries(cfg)
  1668. if #cfg.ignoredefaultlibraries > 0 then
  1669. local ignored = cfg.ignoredefaultlibraries
  1670. for i = 1, #ignored do
  1671. -- Add extension if required
  1672. if not p.tools.msc.getLibraryExtensions()[ignored[i]:match("[^.]+$")] then
  1673. ignored[i] = path.appendextension(ignored[i], ".lib")
  1674. end
  1675. end
  1676. m.element("IgnoreSpecificDefaultLibraries", condition, table.concat(ignored, ';'))
  1677. end
  1678. end
  1679. function m.ignoreWarnDuplicateFilename(prj)
  1680. -- VS 2013 warns on duplicate file names, even those files which are
  1681. -- contained in different, mututally exclusive configurations. See:
  1682. -- http://connect.microsoft.com/VisualStudio/feedback/details/797460/incorrect-warning-msb8027-reported-for-files-excluded-from-build
  1683. -- Premake already adds unique object names to conflicting file names, so
  1684. -- just go ahead and disable that warning.
  1685. if _ACTION > "vs2012" then
  1686. m.element("IgnoreWarnCompileDuplicatedFilename", nil, "true")
  1687. end
  1688. end
  1689. function m.ignoreImportLibrary(cfg)
  1690. if cfg.kind == p.SHAREDLIB and cfg.flags.NoImportLib then
  1691. m.element("IgnoreImportLibrary", nil, "true")
  1692. end
  1693. end
  1694. function m.importLanguageTargets(prj)
  1695. p.w('<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" />')
  1696. end
  1697. m.elements.importExtensionTargets = function(prj)
  1698. return {
  1699. m.importGroupTargets,
  1700. m.importRuleTargets,
  1701. m.importNuGetTargets,
  1702. m.importBuildCustomizationsTargets
  1703. }
  1704. end
  1705. function m.importExtensionTargets(prj)
  1706. p.push('<ImportGroup Label="ExtensionTargets">')
  1707. p.callArray(m.elements.importExtensionTargets, prj)
  1708. p.pop('</ImportGroup>')
  1709. end
  1710. function m.importGroupTargets(prj)
  1711. local groups = m.categorizeSources(prj)
  1712. for _, group in ipairs(groups) do
  1713. if group.category.emitExtensionTargets then
  1714. group.category.emitExtensionTargets(prj, group)
  1715. end
  1716. end
  1717. end
  1718. function m.importRuleTargets(prj)
  1719. for i = 1, #prj.rules do
  1720. local rule = p.global.getRule(prj.rules[i])
  1721. local loc = vstudio.path(prj, p.filename(rule, ".targets"))
  1722. p.x('<Import Project="%s" />', loc)
  1723. end
  1724. end
  1725. local function nuGetTargetsFile(prj, package)
  1726. local packageAPIInfo = vstudio.nuget2010.packageAPIInfo(prj, package)
  1727. return p.vstudio.path(prj, p.filename(prj.workspace, string.format("packages\\%s.%s\\build\\native\\%s.targets", vstudio.nuget2010.packageId(package), packageAPIInfo.verbatimVersion or packageAPIInfo.version, vstudio.nuget2010.packageId(package))))
  1728. end
  1729. function m.importNuGetTargets(prj)
  1730. if not vstudio.nuget2010.supportsPackageReferences(prj) then
  1731. for i = 1, #prj.nuget do
  1732. local targetsFile = nuGetTargetsFile(prj, prj.nuget[i])
  1733. p.x('<Import Project="%s" Condition="Exists(\'%s\')" />', targetsFile, targetsFile)
  1734. end
  1735. end
  1736. end
  1737. function m.importBuildCustomizationsTargets(prj)
  1738. for i, build in ipairs(prj.buildcustomizations) do
  1739. p.w('<Import Project="$(VCTargetsPath)\\%s.targets" />', path.translate(build))
  1740. end
  1741. end
  1742. function m.ensureNuGetPackageBuildImports(prj)
  1743. if #prj.nuget > 0 then
  1744. p.push('<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">')
  1745. p.push('<PropertyGroup>')
  1746. p.x('<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>')
  1747. p.pop('</PropertyGroup>')
  1748. for i = 1, #prj.nuget do
  1749. local targetsFile = nuGetTargetsFile(prj, prj.nuget[i])
  1750. p.x('<Error Condition="!Exists(\'%s\')" Text="$([System.String]::Format(\'$(ErrorText)\', \'%s\'))" />', targetsFile, targetsFile)
  1751. end
  1752. p.pop('</Target>')
  1753. end
  1754. end
  1755. function m.importDefaultProps(prj)
  1756. p.w('<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />')
  1757. end
  1758. function m.importLanguageSettings(prj)
  1759. p.w('<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props" />')
  1760. end
  1761. m.elements.importExtensionSettings = function(prj)
  1762. return {
  1763. m.importGroupSettings,
  1764. m.importRuleSettings,
  1765. m.importBuildCustomizationsProps
  1766. }
  1767. end
  1768. function m.importExtensionSettings(prj)
  1769. p.push('<ImportGroup Label="ExtensionSettings">')
  1770. p.callArray(m.elements.importExtensionSettings, prj)
  1771. p.pop('</ImportGroup>')
  1772. end
  1773. function m.importGroupSettings(prj)
  1774. local groups = m.categorizeSources(prj)
  1775. for _, group in ipairs(groups) do
  1776. if group.category.emitExtensionSettings then
  1777. group.category.emitExtensionSettings(prj, group)
  1778. end
  1779. end
  1780. end
  1781. function m.importRuleSettings(prj)
  1782. for i = 1, #prj.rules do
  1783. local rule = p.global.getRule(prj.rules[i])
  1784. local loc = vstudio.path(prj, p.filename(rule, ".props"))
  1785. p.x('<Import Project="%s" />', loc)
  1786. end
  1787. end
  1788. function m.importBuildCustomizationsProps(prj)
  1789. for i, build in ipairs(prj.buildcustomizations) do
  1790. p.w('<Import Project="$(VCTargetsPath)\\%s.props" />', path.translate(build))
  1791. end
  1792. end
  1793. function m.importLibrary(cfg)
  1794. if cfg.kind == p.SHAREDLIB then
  1795. m.element("ImportLibrary", nil, "%s", path.translate(cfg.linktarget.relpath))
  1796. end
  1797. end
  1798. function m.includePath(cfg)
  1799. local dirs = vstudio.path(cfg, cfg.sysincludedirs)
  1800. if #dirs > 0 then
  1801. m.element("IncludePath", nil, "%s;$(IncludePath)", table.concat(dirs, ";"))
  1802. end
  1803. end
  1804. function m.intDir(cfg)
  1805. local objdir = vstudio.path(cfg, cfg.objdir)
  1806. m.element("IntDir", nil, "%s\\", objdir)
  1807. end
  1808. function m.intrinsicFunctions(cfg)
  1809. if cfg.intrinsics ~= nil then
  1810. if cfg.intrinsics then
  1811. m.element("IntrinsicFunctions", nil, "true")
  1812. else
  1813. m.element("IntrinsicFunctions", nil, "false")
  1814. end
  1815. elseif config.isOptimizedBuild(cfg) then
  1816. m.element("IntrinsicFunctions", nil, "true")
  1817. end
  1818. end
  1819. function m.justMyCodeDebugging(cfg)
  1820. if _ACTION >= "vs2017" then
  1821. local jmc = cfg.justmycode
  1822. if jmc == "On" then
  1823. m.element("SupportJustMyCode", nil, "true")
  1824. elseif jmc == "Off" then
  1825. m.element("SupportJustMyCode", nil, "false")
  1826. end
  1827. end
  1828. end
  1829. function m.supportOpenMP(cfg)
  1830. if cfg.openmp == "On" then
  1831. m.element("OpenMPSupport", nil, "true")
  1832. elseif cfg.openmp == "Off" then
  1833. m.element("OpenMPSupport", nil, "false")
  1834. end
  1835. end
  1836. function m.keyword(prj)
  1837. -- try to determine what kind of targets we're building here
  1838. local isWin, isManaged, isMakefile
  1839. for cfg in project.eachconfig(prj) do
  1840. if cfg.system == p.WINDOWS then
  1841. isWin = true
  1842. end
  1843. if cfg.clr ~= p.OFF then
  1844. isManaged = true
  1845. end
  1846. if vstudio.isMakefile(cfg) then
  1847. isMakefile = true
  1848. end
  1849. end
  1850. if isWin then
  1851. if isMakefile then
  1852. m.element("Keyword", nil, "MakeFileProj")
  1853. else
  1854. if isManaged or m.isClrMixed(prj) then
  1855. m.targetFramework(prj)
  1856. end
  1857. if isManaged then
  1858. m.element("Keyword", nil, "ManagedCProj")
  1859. else
  1860. m.element("Keyword", nil, "Win32Proj")
  1861. end
  1862. m.element("RootNamespace", nil, "%s", prj.name)
  1863. end
  1864. end
  1865. end
  1866. function m.libraryPath(cfg)
  1867. local dirs = vstudio.path(cfg, cfg.syslibdirs)
  1868. if #dirs > 0 then
  1869. m.element("LibraryPath", nil, "%s;$(LibraryPath)", table.concat(dirs, ";"))
  1870. end
  1871. end
  1872. function m.linkIncremental(cfg)
  1873. if cfg.kind ~= p.STATICLIB then
  1874. m.element("LinkIncremental", nil, "%s", tostring(config.canLinkIncremental(cfg)))
  1875. end
  1876. end
  1877. function m.linkLibraryDependencies(cfg, explicit)
  1878. -- Left to its own devices, VS will happily link against a project dependency
  1879. -- that has been excluded from the build. As a workaround, disable dependency
  1880. -- linking and list all siblings explicitly
  1881. if explicit then
  1882. p.push('<ProjectReference>')
  1883. m.element("LinkLibraryDependencies", nil, "false")
  1884. p.pop('</ProjectReference>')
  1885. end
  1886. end
  1887. function m.MasmPreprocessorDefinitions(cfg, condition)
  1888. if cfg.defines then
  1889. m.preprocessorDefinitions(cfg, cfg.defines, false, condition)
  1890. end
  1891. end
  1892. function m.minimalRebuild(cfg)
  1893. if config.isOptimizedBuild(cfg) or
  1894. cfg.flags.NoMinimalRebuild or
  1895. cfg.flags.MultiProcessorCompile or
  1896. cfg.debugformat == p.C7
  1897. then
  1898. m.element("MinimalRebuild", nil, "false")
  1899. end
  1900. end
  1901. function m.moduleDefinitionFile(cfg)
  1902. local df = config.findfile(cfg, ".def")
  1903. if df then
  1904. m.element("ModuleDefinitionFile", nil, "%s", df)
  1905. end
  1906. end
  1907. function m.multiProcessorCompilation(cfg)
  1908. if cfg.flags.MultiProcessorCompile then
  1909. m.element("MultiProcessorCompilation", nil, "true")
  1910. end
  1911. end
  1912. function m.nmakeBuildCommands(cfg)
  1913. m.nmakeCommandLine(cfg, cfg.buildcommands, "Build")
  1914. end
  1915. function m.nmakeCleanCommands(cfg)
  1916. m.nmakeCommandLine(cfg, cfg.cleancommands, "Clean")
  1917. end
  1918. function m.nmakeCommandLine(cfg, commands, phase)
  1919. if #commands > 0 then
  1920. commands = os.translateCommandsAndPaths(commands, cfg.project.basedir, cfg.project.location)
  1921. commands = table.concat(p.esc(commands), p.eol())
  1922. p.w('<NMake%sCommandLine>%s</NMake%sCommandLine>', phase, commands, phase)
  1923. end
  1924. end
  1925. function m.nmakeIncludeDirs(cfg)
  1926. if cfg.kind ~= p.NONE and #cfg.includedirs > 0 then
  1927. local dirs = vstudio.path(cfg, cfg.includedirs)
  1928. if #dirs > 0 then
  1929. m.element("NMakeIncludeSearchPath", nil, "%s", table.concat(dirs, ";"))
  1930. end
  1931. end
  1932. end
  1933. function m.nmakeOutDirs(cfg)
  1934. if vstudio.isMakefile(cfg) then
  1935. m.outDir(cfg)
  1936. m.intDir(cfg)
  1937. end
  1938. end
  1939. function m.windowsSDKDesktopARMSupport(cfg)
  1940. if cfg.system == p.WINDOWS then
  1941. if cfg.architecture == p.ARM then
  1942. p.w('<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>')
  1943. end
  1944. if cfg.architecture == p.ARM64 then
  1945. p.w('<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>')
  1946. end
  1947. end
  1948. end
  1949. function m.nmakeOutput(cfg)
  1950. m.element("NMakeOutput", nil, "$(OutDir)%s", cfg.buildtarget.name)
  1951. end
  1952. function m.nmakePreprocessorDefinitions(cfg)
  1953. if cfg.kind ~= p.NONE and #cfg.defines > 0 then
  1954. local defines = table.concat(cfg.defines, ";")
  1955. defines = defines .. ";$(NMakePreprocessorDefinitions)"
  1956. m.element('NMakePreprocessorDefinitions', nil, defines)
  1957. end
  1958. end
  1959. function m.nmakeRebuildCommands(cfg)
  1960. m.nmakeCommandLine(cfg, cfg.rebuildcommands, "ReBuild")
  1961. end
  1962. function m.objectFileName(fcfg)
  1963. if fcfg.objname ~= fcfg.basename then
  1964. m.element("ObjectFileName", m.configPair(fcfg.config), "$(IntDir)\\%s.obj", fcfg.objname)
  1965. end
  1966. end
  1967. function m.omitDefaultLib(cfg)
  1968. if cfg.flags.OmitDefaultLibrary then
  1969. m.element("OmitDefaultLibName", nil, "true")
  1970. end
  1971. end
  1972. function m.omitFramePointers(cfg)
  1973. local map = { Off = "false", On = "true" }
  1974. local value = map[cfg.omitframepointer]
  1975. if value then
  1976. m.element("OmitFramePointers", nil, value)
  1977. end
  1978. end
  1979. function m.optimizeReferences(cfg)
  1980. if config.isOptimizedBuild(cfg) then
  1981. m.element("EnableCOMDATFolding", nil, "true")
  1982. m.element("OptimizeReferences", nil, "true")
  1983. end
  1984. end
  1985. function m.optimization(cfg, condition)
  1986. local map = { Off="Disabled", On="Full", Debug="Disabled", Full="Full", Size="MinSpace", Speed="MaxSpeed" }
  1987. local value = map[cfg.optimize]
  1988. if value or not condition then
  1989. m.element('Optimization', condition, value or "Disabled")
  1990. end
  1991. end
  1992. function m.outDir(cfg)
  1993. local outdir = vstudio.path(cfg, cfg.buildtarget.directory)
  1994. m.element("OutDir", nil, "%s\\", outdir)
  1995. end
  1996. function m.executablePath(cfg)
  1997. local dirs = vstudio.path(cfg, cfg.bindirs)
  1998. if #dirs > 0 then
  1999. dirs = table.translate(dirs, function(dir)
  2000. if path.isabsolute(dir) then
  2001. return dir
  2002. end
  2003. return "$(ProjectDir)" .. dir
  2004. end)
  2005. m.element("ExecutablePath", nil, "%s;$(ExecutablePath)", table.concat(dirs, ";"))
  2006. end
  2007. end
  2008. function m.toolsVersion(cfg)
  2009. local version = cfg.toolsversion
  2010. if _ACTION >= "vs2017" and version then
  2011. m.element("VCToolsVersion", nil, version)
  2012. end
  2013. end
  2014. function m.platformToolset(cfg)
  2015. local tool, version = p.config.toolset(cfg)
  2016. if not version and _ACTION >= "vs2019" and cfg.toolset == "clang" then
  2017. version = "ClangCL"
  2018. end
  2019. if not version then
  2020. local value = p.action.current().toolset
  2021. tool, version = p.tools.canonical(value)
  2022. end
  2023. if version then
  2024. if cfg.kind == p.NONE or cfg.kind == p.MAKEFILE then
  2025. if p.config.hasFile(cfg, path.iscppfile) or _ACTION >= "vs2015" then
  2026. m.element("PlatformToolset", nil, version)
  2027. end
  2028. else
  2029. m.element("PlatformToolset", nil, version)
  2030. end
  2031. end
  2032. end
  2033. function m.precompiledHeaderFile(fileName, cfg)
  2034. m.element("PrecompiledHeaderFile", nil, "%s", fileName)
  2035. end
  2036. function m.precompiledHeader(cfg, condition)
  2037. local prjcfg, filecfg = p.config.normalize(cfg)
  2038. if filecfg then
  2039. if prjcfg.pchsource == filecfg.abspath and not prjcfg.flags.NoPCH then
  2040. m.element('PrecompiledHeader', condition, 'Create')
  2041. elseif filecfg.flags.NoPCH then
  2042. m.element('PrecompiledHeader', condition, 'NotUsing')
  2043. end
  2044. else
  2045. if not prjcfg.flags.NoPCH and prjcfg.pchheader then
  2046. m.element("PrecompiledHeader", nil, "Use")
  2047. m.precompiledHeaderFile(prjcfg.pchheader, prjcfg)
  2048. else
  2049. m.element("PrecompiledHeader", nil, "NotUsing")
  2050. end
  2051. end
  2052. end
  2053. function m.preprocessorDefinitions(cfg, defines, escapeQuotes, condition)
  2054. if #defines > 0 then
  2055. defines = table.concat(defines, ";")
  2056. if escapeQuotes then
  2057. defines = defines:gsub('"', '\\"')
  2058. end
  2059. defines = defines .. ";%%(PreprocessorDefinitions)"
  2060. m.element('PreprocessorDefinitions', condition, defines)
  2061. end
  2062. end
  2063. function m.undefinePreprocessorDefinitions(cfg, undefines, escapeQuotes, condition)
  2064. if #undefines > 0 then
  2065. undefines = table.concat(undefines, ";")
  2066. if escapeQuotes then
  2067. undefines = undefines:gsub('"', '\\"')
  2068. end
  2069. undefines = undefines .. ";%%(UndefinePreprocessorDefinitions)"
  2070. m.element('UndefinePreprocessorDefinitions', condition, undefines)
  2071. end
  2072. end
  2073. local function getSymbolsPathRelative(cfg)
  2074. if cfg.symbolspath and cfg.symbols ~= p.OFF and cfg.debugformat ~= "c7" then
  2075. return p.project.getrelative(cfg.project, cfg.symbolspath)
  2076. else
  2077. return nil
  2078. end
  2079. end
  2080. function m.programDatabaseFile(cfg)
  2081. local value = getSymbolsPathRelative(cfg)
  2082. if value then
  2083. m.element("ProgramDatabaseFile", nil, value)
  2084. end
  2085. end
  2086. function m.programDatabaseFileName(cfg)
  2087. local value = getSymbolsPathRelative(cfg)
  2088. if value then
  2089. m.element("ProgramDataBaseFileName", nil, value)
  2090. end
  2091. end
  2092. function m.projectGuid(prj)
  2093. m.element("ProjectGuid", nil, "{%s}", prj.uuid)
  2094. end
  2095. function m.projectName(prj)
  2096. if prj.name ~= prj.filename then
  2097. m.element("ProjectName", nil, "%s", prj.name)
  2098. end
  2099. end
  2100. function m.propertyGroup(cfg, label)
  2101. local cond
  2102. if cfg then
  2103. cond = string.format(' %s', m.condition(cfg))
  2104. end
  2105. if label then
  2106. label = string.format(' Label="%s"', label)
  2107. end
  2108. p.push('<PropertyGroup%s%s>', cond or "", label or "")
  2109. end
  2110. function m.propertySheets(cfg)
  2111. p.push('<ImportGroup Label="PropertySheets" %s>', m.condition(cfg))
  2112. p.w('<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists(\'$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\')" Label="LocalAppDataPlatform" />')
  2113. p.pop('</ImportGroup>')
  2114. end
  2115. function m.propertySheetGroup(prj)
  2116. for cfg in project.eachconfig(prj) do
  2117. m.propertySheets(cfg)
  2118. end
  2119. end
  2120. function m.referenceCopyLocalSatelliteAssemblies(prj, ref)
  2121. m.element("CopyLocalSatelliteAssemblies", nil, "false")
  2122. end
  2123. function m.referenceLinkLibraryDependencies(prj, ref)
  2124. m.element("LinkLibraryDependencies", nil, "true")
  2125. end
  2126. function m.referenceOutputAssembly(prj, ref)
  2127. m.element("ReferenceOutputAssembly", nil, "true")
  2128. end
  2129. function m.referencePrivate(prj, ref)
  2130. m.element("Private", nil, "true")
  2131. end
  2132. function m.referenceProject(prj, ref)
  2133. m.element("Project", nil, "{%s}", ref.uuid)
  2134. end
  2135. function m.referenceUseLibraryDependences(prj, ref)
  2136. m.element("UseLibraryDependencyInputs", nil, "false")
  2137. end
  2138. function m.resourceAdditionalIncludeDirectories(cfg)
  2139. m.additionalIncludeDirectories(cfg, table.join(cfg.includedirs, cfg.resincludedirs))
  2140. end
  2141. function m.resourcePreprocessorDefinitions(cfg)
  2142. local defines = table.join(cfg.defines, cfg.resdefines)
  2143. if cfg.exceptionhandling == p.OFF then
  2144. table.insert(defines, "_HAS_EXCEPTIONS=0")
  2145. end
  2146. m.preprocessorDefinitions(cfg, defines, true)
  2147. end
  2148. function m.runtimeLibrary(cfg)
  2149. local runtimes = {
  2150. StaticDebug = "MultiThreadedDebug",
  2151. StaticRelease = "MultiThreaded",
  2152. SharedDebug = "MultiThreadedDebugDLL",
  2153. SharedRelease = "MultiThreadedDLL"
  2154. }
  2155. local runtime = config.getruntime(cfg)
  2156. if runtime then
  2157. m.element("RuntimeLibrary", nil, runtimes[runtime])
  2158. end
  2159. end
  2160. function m.callingConvention(cfg)
  2161. if cfg.callingconvention then
  2162. m.element("CallingConvention", nil, cfg.callingconvention)
  2163. end
  2164. end
  2165. function m.runtimeTypeInfo(cfg, condition)
  2166. if cfg.rtti == p.OFF and ((not cfg.clr) or cfg.clr == p.OFF) then
  2167. m.element("RuntimeTypeInfo", condition, "false")
  2168. elseif cfg.rtti == p.ON then
  2169. m.element("RuntimeTypeInfo", condition, "true")
  2170. end
  2171. end
  2172. function m.bufferSecurityCheck(cfg)
  2173. local tool, toolVersion = p.config.toolset(cfg)
  2174. if cfg.flags.NoBufferSecurityCheck or (toolVersion and toolVersion:startswith("LLVM-vs")) then
  2175. m.element("BufferSecurityCheck", nil, "false")
  2176. end
  2177. end
  2178. function m.stringPooling(cfg)
  2179. if cfg.stringpooling ~= nil then
  2180. if cfg.stringpooling then
  2181. m.element("StringPooling", nil, "true")
  2182. else
  2183. m.element("StringPooling", nil, "false")
  2184. end
  2185. elseif config.isOptimizedBuild(cfg) then
  2186. m.element("StringPooling", nil, "true")
  2187. end
  2188. end
  2189. function m.subSystem(cfg)
  2190. local subsystem = iif(cfg.kind == p.CONSOLEAPP, "Console", "Windows")
  2191. m.element("SubSystem", nil, subsystem)
  2192. end
  2193. function m.targetExt(cfg)
  2194. local ext = cfg.buildtarget.extension
  2195. if ext ~= "" then
  2196. m.element("TargetExt", nil, "%s", ext)
  2197. else
  2198. p.w('<TargetExt>')
  2199. p.w('</TargetExt>')
  2200. end
  2201. end
  2202. function m.targetMachine(cfg)
  2203. -- If a static library project contains a resource file, VS will choke with
  2204. -- "LINK : warning LNK4068: /MACHINE not specified; defaulting to X86"
  2205. local targetmachine = {
  2206. x86 = "MachineX86",
  2207. x86_64 = "MachineX64",
  2208. }
  2209. if cfg.kind == p.STATICLIB and config.hasFile(cfg, path.isresourcefile) then
  2210. local value = targetmachine[cfg.architecture]
  2211. if value ~= nil then
  2212. m.element("TargetMachine", nil, '%s', value)
  2213. end
  2214. end
  2215. end
  2216. function m.targetName(cfg)
  2217. m.element("TargetName", nil, "%s%s", cfg.buildtarget.prefix, cfg.buildtarget.basename)
  2218. end
  2219. function m.latestTargetPlatformVersion(prj)
  2220. -- See https://developercommunity.visualstudio.com/content/problem/140294/windowstargetplatformversion-makes-it-impossible-t.html
  2221. if _ACTION == "vs2017" then
  2222. m.element("LatestTargetPlatformVersion", nil, "$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))")
  2223. end
  2224. end
  2225. function m.windowsTargetPlatformVersion(prj, cfg)
  2226. if _ACTION < "vs2015" then
  2227. return
  2228. end
  2229. local target = cfg or prj
  2230. local version = project.systemversion(target)
  2231. -- if this is a config, only emit if different from project
  2232. if cfg then
  2233. local prjVersion = project.systemversion(prj)
  2234. if not prjVersion or version == prjVersion then
  2235. return
  2236. end
  2237. end
  2238. -- See https://developercommunity.visualstudio.com/content/problem/140294/windowstargetplatformversion-makes-it-impossible-t.html
  2239. if version == "latest" then
  2240. if _ACTION == "vs2015" then
  2241. version = nil -- SDK v10 is not supported by VS2015
  2242. elseif _ACTION == "vs2017" then
  2243. version = "$(LatestTargetPlatformVersion)"
  2244. else
  2245. version = "10.0"
  2246. end
  2247. end
  2248. if version then
  2249. m.element("WindowsTargetPlatformVersion", nil, version)
  2250. end
  2251. end
  2252. function m.xpDeprecationWarning(prj, cfg)
  2253. if cfg.toolset == "msc-v141_xp" then
  2254. m.element("XPDeprecationWarning", nil, "false")
  2255. end
  2256. end
  2257. function m.fastUpToDateCheck(prj)
  2258. if prj.fastuptodate ~= nil then
  2259. m.element("DisableFastUpToDateCheck", nil, iif(prj.fastuptodate, "false", "true"))
  2260. end
  2261. end
  2262. function m.preferredToolArchitecture(prj)
  2263. if _ACTION >= "vs2013" then
  2264. if prj.preferredtoolarchitecture == p.X86_64 then
  2265. m.element("PreferredToolArchitecture", nil, 'x64')
  2266. elseif prj.preferredtoolarchitecture == p.X86 then
  2267. m.element("PreferredToolArchitecture", nil, 'x86')
  2268. end
  2269. else
  2270. if prj.preferredtoolarchitecture == p.X86_64 then
  2271. m.element("UseNativeEnvironment", nil, 'true')
  2272. end
  2273. end
  2274. end
  2275. function m.treatLinkerWarningAsErrors(cfg)
  2276. if cfg.flags.FatalLinkWarnings then
  2277. local el = iif(cfg.kind == p.STATICLIB, "Lib", "Linker")
  2278. m.element("Treat" .. el .. "WarningAsErrors", nil, "true")
  2279. end
  2280. end
  2281. function m.treatWChar_tAsBuiltInType(cfg)
  2282. local map = { On = "true", Off = "false" }
  2283. local value = map[cfg.nativewchar]
  2284. if value then
  2285. m.element("TreatWChar_tAsBuiltInType", nil, value)
  2286. end
  2287. end
  2288. function m.treatWarningAsError(cfg)
  2289. if cfg.flags.FatalCompileWarnings and cfg.warnings ~= p.OFF then
  2290. m.element("TreatWarningAsError", nil, "true")
  2291. end
  2292. end
  2293. function m.disableSpecificWarnings(cfg, condition)
  2294. if #cfg.disablewarnings > 0 then
  2295. local warnings = table.concat(cfg.disablewarnings, ";")
  2296. warnings = warnings .. ";%%(DisableSpecificWarnings)"
  2297. m.element('DisableSpecificWarnings', condition, warnings)
  2298. end
  2299. end
  2300. function m.treatSpecificWarningsAsErrors(cfg, condition)
  2301. if #cfg.fatalwarnings > 0 then
  2302. local fatal = table.concat(cfg.fatalwarnings, ";")
  2303. fatal = fatal .. ";%%(TreatSpecificWarningsAsErrors)"
  2304. m.element('TreatSpecificWarningsAsErrors', condition, fatal)
  2305. end
  2306. end
  2307. function m.useDebugLibraries(cfg)
  2308. local runtime = config.getruntime(cfg) or iif(config.isDebugBuild(cfg), "Debug", "Release")
  2309. m.element("UseDebugLibraries", nil, tostring(runtime:endswith("Debug")))
  2310. end
  2311. function m.useOfMfc(cfg)
  2312. if cfg.flags.MFC then
  2313. m.element("UseOfMfc", nil, iif(cfg.staticruntime == "On", "Static", "Dynamic"))
  2314. end
  2315. end
  2316. function m.useOfAtl(cfg)
  2317. if cfg.atl then
  2318. m.element("UseOfATL", nil, cfg.atl)
  2319. end
  2320. end
  2321. function m.userMacros(cfg)
  2322. p.w('<PropertyGroup Label="UserMacros" />')
  2323. end
  2324. function m.warningLevel(cfg)
  2325. local map = { Off = "TurnOffAllWarnings", High = "Level4", Extra = "Level4", Everything = "EnableAllWarnings" }
  2326. m.element("WarningLevel", nil, map[cfg.warnings] or "Level3")
  2327. end
  2328. function m.warningLevelFile(cfg, condition)
  2329. local map = { Off = "TurnOffAllWarnings", High = "Level4", Extra = "Level4", Everything = "EnableAllWarnings" }
  2330. if cfg.warnings then
  2331. m.element("WarningLevel", condition, map[cfg.warnings] or "Level3")
  2332. end
  2333. end
  2334. function m.xmlDeclaration()
  2335. p.xmlUtf8()
  2336. end
  2337. -- Fx Functions
  2338. --------------------------------------------------------------------------------------------------------------
  2339. --------------------------------------------------------------------------------------------------------------
  2340. function m.fxCompilePreprocessorDefinition(cfg, condition)
  2341. if cfg.shaderdefines and #cfg.shaderdefines > 0 then
  2342. local shaderdefines = table.concat(cfg.shaderdefines, ";")
  2343. shaderdefines = shaderdefines .. ";%%(PreprocessorDefinitions)"
  2344. m.element('PreprocessorDefinitions', condition, shaderdefines)
  2345. end
  2346. end
  2347. function m.fxCompileAdditionalIncludeDirs(cfg, condition)
  2348. if cfg.shaderincludedirs and #cfg.shaderincludedirs > 0 then
  2349. local dirs = vstudio.path(cfg, cfg.shaderincludedirs)
  2350. m.element('AdditionalIncludeDirectories', condition, "%s;%%(AdditionalIncludeDirectories)", table.concat(dirs, ";"))
  2351. end
  2352. end
  2353. function m.fxCompileShaderType(cfg, condition)
  2354. if cfg.shadertype then
  2355. m.element("ShaderType", condition, cfg.shadertype)
  2356. end
  2357. end
  2358. function m.fxCompileShaderModel(cfg, condition)
  2359. if cfg.shadermodel then
  2360. m.element("ShaderModel", condition, cfg.shadermodel)
  2361. end
  2362. end
  2363. function m.fxCompileShaderEntry(cfg, condition)
  2364. if cfg.shaderentry then
  2365. m.element("EntryPointName", condition, cfg.shaderentry)
  2366. end
  2367. end
  2368. function m.fxCompileShaderVariableName(cfg, condition)
  2369. if cfg.shadervariablename then
  2370. m.element("VariableName", condition, cfg.shadervariablename)
  2371. end
  2372. end
  2373. function m.fxCompileShaderHeaderOutput(cfg, condition)
  2374. if cfg.shaderheaderfileoutput then
  2375. m.element("HeaderFileOutput", condition, cfg.shaderheaderfileoutput)
  2376. end
  2377. end
  2378. function m.fxCompileShaderObjectOutput(cfg, condition)
  2379. if cfg.shaderobjectfileoutput then
  2380. m.element("ObjectFileOutput", condition, cfg.shaderobjectfileoutput)
  2381. end
  2382. end
  2383. function m.fxCompileShaderAssembler(cfg, condition)
  2384. if cfg.shaderassembler then
  2385. m.element("AssemblerOutput", condition, cfg.shaderassembler)
  2386. end
  2387. end
  2388. function m.fxCompileShaderAssemblerOutput(cfg, condition)
  2389. if cfg.shaderassembleroutput then
  2390. m.element("AssemblerOutputFile", condition, cfg.shaderassembleroutput)
  2391. end
  2392. end
  2393. function m.fxCompileShaderAdditionalOptions(cfg, condition)
  2394. local opts = cfg.shaderoptions
  2395. if #opts > 0 then
  2396. opts = table.concat(opts, " ")
  2397. m.element("AdditionalOptions", condition, '%s %%(AdditionalOptions)', opts)
  2398. end
  2399. end
  2400. ---------------------------------------------------------------------------
  2401. --
  2402. -- Support functions
  2403. --
  2404. ---------------------------------------------------------------------------
  2405. --
  2406. -- Format and return a Visual Studio Condition attribute.
  2407. --
  2408. function m.conditionFromConfigText(cfgText)
  2409. return string.format('Condition="\'$(Configuration)|$(Platform)\'==\'%s\'"', p.esc(cfgText))
  2410. end
  2411. function m.condition(cfg)
  2412. return m.conditionFromConfigText(vstudio.projectConfig(cfg))
  2413. end
  2414. --
  2415. -- Output an individual project XML element, with an optional configuration
  2416. -- condition.
  2417. --
  2418. -- @param depth
  2419. -- How much to indent the element.
  2420. -- @param name
  2421. -- The element name.
  2422. -- @param condition
  2423. -- An optional configuration condition, formatted with vc2010.condition().
  2424. -- @param value
  2425. -- The element value, which may contain printf formatting tokens.
  2426. -- @param ...
  2427. -- Optional additional arguments to satisfy any tokens in the value.
  2428. --
  2429. function m.element(name, condition, value, ...)
  2430. local arg = {...}
  2431. if select('#',...) == 0 then
  2432. value = p.esc(value)
  2433. else
  2434. for i = 1, #arg do
  2435. arg[i] = p.esc(arg[i])
  2436. end
  2437. end
  2438. if condition then
  2439. --defer output
  2440. local element = {}
  2441. element.name = name
  2442. element.condition = condition
  2443. element.value = value
  2444. element.args = arg
  2445. if ... then
  2446. if value == '%s' then
  2447. element.setting = table.concat(arg)
  2448. else
  2449. element.setting = value .. table.concat(arg)
  2450. end
  2451. else
  2452. element.setting = element.value
  2453. end
  2454. table.insert(m.conditionalElements, element)
  2455. else
  2456. local format = string.format('<%s>%s</%s>', name, value, name)
  2457. p.w(format, table.unpack(arg))
  2458. end
  2459. end