123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009 |
- --
- -- vs2010_vcxproj.lua
- -- Generate a Visual Studio 201x C/C++ project.
- -- Copyright (c) Jason Perkins and the Premake project
- --
- local p = premake
- p.vstudio.vc2010 = {}
- local vstudio = p.vstudio
- local project = p.project
- local config = p.config
- local fileconfig = p.fileconfig
- local tree = p.tree
- local m = p.vstudio.vc2010
- ---
- -- Add namespace for element definition lists for p.callArray()
- ---
- m.elements = {}
- m.conditionalElements = {}
- --
- -- Generate a Visual Studio 201x C++ project, with support for the new platforms API.
- --
- m.elements.project = function(prj)
- return {
- m.xmlDeclaration,
- m.project,
- m.projectConfigurations,
- m.globals,
- m.importDefaultProps,
- m.configurationPropertiesGroup,
- m.importLanguageSettings,
- m.importExtensionSettings,
- m.propertySheetGroup,
- m.userMacros,
- m.outputPropertiesGroup,
- m.itemDefinitionGroups,
- m.assemblyReferences,
- m.files,
- m.projectReferences,
- m.importLanguageTargets,
- m.importExtensionTargets,
- m.ensureNuGetPackageBuildImports,
- }
- end
- function m.generate(prj)
- p.utf8()
- p.callArray(m.elements.project, prj)
- p.out('</Project>')
- end
- --
- -- Output the XML declaration and opening <Project> tag.
- --
- function m.project(prj)
- local action = p.action.current()
- if _ACTION >= "vs2019" then
- p.push('<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">')
- else
- p.push('<Project DefaultTargets="Build" ToolsVersion="%s" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">',
- action.vstudio.toolsVersion)
- end
- end
- --
- -- Write out the list of project configurations, which pairs build
- -- configurations with architectures.
- --
- function m.projectConfigurations(prj)
- -- build a list of all architectures used in this project
- local platforms = {}
- for cfg in project.eachconfig(prj) do
- local arch = vstudio.archFromConfig(cfg, true)
- if not table.contains(platforms, arch) then
- table.insert(platforms, arch)
- end
- end
- local configs = {}
- p.push('<ItemGroup Label="ProjectConfigurations">')
- for cfg in project.eachconfig(prj) do
- for _, arch in ipairs(platforms) do
- local prjcfg = vstudio.projectConfig(cfg, arch)
- if not configs[prjcfg] then
- configs[prjcfg] = prjcfg
- p.push('<ProjectConfiguration Include="%s">', vstudio.projectConfig(cfg, arch))
- p.x('<Configuration>%s</Configuration>', vstudio.projectPlatform(cfg))
- p.w('<Platform>%s</Platform>', arch)
- p.pop('</ProjectConfiguration>')
- end
- end
- end
- p.pop('</ItemGroup>')
- end
- --
- -- Write out the TargetFrameworkVersion property.
- --
- function m.targetFramework(prj)
- local action = p.action.current()
- local tools = string.format(' ToolsVersion="%s"', action.vstudio.toolsVersion)
- local framework = prj.dotnetframework or action.vstudio.targetFramework or "4.0"
- p.w('<TargetFrameworkVersion>v%s</TargetFrameworkVersion>', framework)
- end
- --
- -- Write out the Globals property group.
- --
- m.elements.globals = function(prj)
- return {
- m.projectGuid,
- m.ignoreWarnDuplicateFilename,
- m.keyword,
- m.projectName,
- m.preferredToolArchitecture,
- m.latestTargetPlatformVersion,
- m.windowsTargetPlatformVersion,
- m.fastUpToDateCheck,
- m.toolsVersion,
- }
- end
- m.elements.globalsCondition = function(prj, cfg)
- return {
- m.windowsTargetPlatformVersion,
- m.xpDeprecationWarning,
- }
- end
- function m.globals(prj)
- -- Write out the project-level globals
- m.propertyGroup(nil, "Globals")
- p.callArray(m.elements.globals, prj)
- p.pop('</PropertyGroup>')
- -- Write out the configurable globals
- for cfg in project.eachconfig(prj) do
- -- Find out whether we're going to actually write a property out
- local captured = p.capture( function()
- p.push()
- p.callArray(m.elements.globalsCondition, prj, cfg)
- p.pop()
- end)
- -- If we do have something, create the entry, skip otherwise
- if captured ~= '' then
- m.propertyGroup(cfg, "Globals")
- p.callArray(m.elements.globalsCondition, prj, cfg)
- p.pop('</PropertyGroup>')
- end
- end
- end
- --
- -- Write out the configuration property group: what kind of binary it
- -- produces, and some global settings.
- --
- m.elements.configurationProperties = function(cfg)
- if cfg.kind == p.UTILITY then
- return {
- m.configurationType,
- m.platformToolset,
- m.toolsVersion,
- }
- else
- return {
- m.configurationType,
- m.useDebugLibraries,
- m.useOfMfc,
- m.useOfAtl,
- m.clrSupport,
- m.characterSet,
- m.platformToolset,
- m.toolsVersion,
- m.wholeProgramOptimization,
- m.spectreMitigations, --OpenMPT
- m.nmakeOutDirs,
- m.windowsSDKDesktopARMSupport,
- }
- end
- end
- function m.configurationProperties(cfg)
- m.propertyGroup(cfg, "Configuration")
- p.callArray(m.elements.configurationProperties, cfg)
- p.pop('</PropertyGroup>')
- end
- function m.configurationPropertiesGroup(prj)
- for cfg in project.eachconfig(prj) do
- m.configurationProperties(cfg)
- end
- end
- --
- -- Write the output property group, which includes the output and intermediate
- -- directories, manifest, etc.
- --
- m.elements.outputProperties = function(cfg)
- if cfg.kind == p.UTILITY then
- return {
- m.outDir,
- m.intDir,
- m.extensionsToDeleteOnClean,
- m.executablePath,
- }
- else
- return {
- m.linkIncremental,
- m.ignoreImportLibrary,
- m.outDir,
- m.intDir,
- m.targetName,
- m.targetExt,
- m.includePath,
- m.libraryPath,
- m.generateManifest,
- m.extensionsToDeleteOnClean,
- m.executablePath,
- }
- end
- end
- function m.outputProperties(cfg)
- if not vstudio.isMakefile(cfg) then
- m.propertyGroup(cfg)
- p.callArray(m.elements.outputProperties, cfg)
- p.pop('</PropertyGroup>')
- end
- end
- --
- -- Write the NMake property group for Makefile projects, which includes the custom
- -- build commands, output file location, etc.
- --
- m.elements.nmakeProperties = function(cfg)
- return {
- m.executablePath,
- m.includePath,
- m.libraryPath,
- m.nmakeOutput,
- m.nmakeBuildCommands,
- m.nmakeRebuildCommands,
- m.nmakeCleanCommands,
- m.nmakePreprocessorDefinitions,
- m.nmakeIncludeDirs,
- m.additionalCompileOptions
- }
- end
- function m.nmakeProperties(cfg)
- if vstudio.isMakefile(cfg) then
- m.propertyGroup(cfg)
- p.callArray(m.elements.nmakeProperties, cfg)
- p.pop('</PropertyGroup>')
- end
- end
- --
- -- Output properties and NMake properties should appear side-by-side
- -- for each configuration.
- --
- function m.outputPropertiesGroup(prj)
- for cfg in project.eachconfig(prj) do
- m.outputProperties(cfg)
- m.nmakeProperties(cfg)
- end
- end
- --
- -- Write a configuration's item definition group, which contains all
- -- of the per-configuration compile and link settings.
- --
- m.elements.itemDefinitionGroup = function(cfg)
- if cfg.kind == p.UTILITY then
- return {
- m.ruleVars,
- m.buildEvents,
- m.buildLog,
- }
- else
- return {
- m.clCompile,
- m.buildStep,
- m.fxCompile,
- m.resourceCompile,
- m.linker,
- m.manifest,
- m.buildEvents,
- m.ruleVars,
- m.buildLog,
- }
- end
- end
- function m.itemDefinitionGroup(cfg)
- if not vstudio.isMakefile(cfg) then
- p.push('<ItemDefinitionGroup %s>', m.condition(cfg))
- p.callArray(m.elements.itemDefinitionGroup, cfg)
- p.pop('</ItemDefinitionGroup>')
- else
- if cfg == project.getfirstconfig(cfg.project) then
- p.w('<ItemDefinitionGroup>')
- p.w('</ItemDefinitionGroup>')
- end
- end
- end
- function m.itemDefinitionGroups(prj)
- for cfg in project.eachconfig(prj) do
- m.itemDefinitionGroup(cfg)
- end
- end
- --
- -- Write the the <ClCompile> compiler settings block.
- --
- m.elements.clCompile = function(cfg)
- local calls = {
- m.precompiledHeader,
- m.warningLevel,
- m.treatWarningAsError,
- m.disableSpecificWarnings,
- m.treatSpecificWarningsAsErrors,
- m.basicRuntimeChecks,
- m.clCompilePreprocessorDefinitions,
- m.clCompileUndefinePreprocessorDefinitions,
- m.clCompileAdditionalIncludeDirectories,
- m.clCompileAdditionalUsingDirectories,
- m.forceIncludes,
- m.debugInformationFormat,
- m.optimization,
- m.functionLevelLinking,
- m.intrinsicFunctions,
- m.justMyCodeDebugging,
- m.supportOpenMP,
- m.minimalRebuild,
- m.omitFramePointers,
- m.stringPooling,
- m.runtimeLibrary,
- m.omitDefaultLib,
- m.exceptionHandling,
- m.runtimeTypeInfo,
- m.bufferSecurityCheck,
- m.treatWChar_tAsBuiltInType,
- m.floatingPointModel,
- m.floatingPointExceptions,
- m.inlineFunctionExpansion,
- m.enableEnhancedInstructionSet,
- m.multiProcessorCompilation,
- m.additionalCompileOptions,
- m.compileAs,
- m.callingConvention,
- m.languageStandard,
- m.conformanceMode,
- m.structMemberAlignment,
- m.useFullPaths,
- m.removeUnreferencedCodeData
- }
- if cfg.kind == p.STATICLIB then
- table.insert(calls, m.programDatabaseFileName)
- end
- return calls
- end
- function m.clCompile(cfg)
- p.push('<ClCompile>')
- p.callArray(m.elements.clCompile, cfg)
- p.pop('</ClCompile>')
- end
- --
- -- Write the the <CustomBuildStep> compiler settings block.
- --
- m.elements.buildStep = function(cfg)
- local calls = {
- m.buildCommands,
- m.buildMessage,
- m.buildOutputs,
- m.buildInputs
- }
- return calls
- end
- function m.buildStep(cfg)
- if #cfg.buildCommands > 0 or #cfg.buildOutputs > 0 or #cfg.buildInputs > 0 or cfg.buildMessage then
- p.push('<CustomBuildStep>')
- p.callArray(m.elements.buildStep, cfg)
- p.pop('</CustomBuildStep>')
- end
- end
- --
- -- Write the <FxCompile> settings block.
- --
- m.elements.fxCompile = function(cfg)
- return {
- m.fxCompilePreprocessorDefinition,
- m.fxCompileAdditionalIncludeDirs,
- m.fxCompileShaderType,
- m.fxCompileShaderModel,
- m.fxCompileShaderEntry,
- m.fxCompileShaderVariableName,
- m.fxCompileShaderHeaderOutput,
- m.fxCompileShaderObjectOutput,
- m.fxCompileShaderAssembler,
- m.fxCompileShaderAssemblerOutput,
- m.fxCompileShaderAdditionalOptions,
- }
- end
- function m.fxCompile(cfg)
- if p.config.hasFile(cfg, path.ishlslfile) then
- local contents = p.capture(function ()
- p.push()
- p.callArray(m.elements.fxCompile, cfg)
- p.pop()
- end)
- if #contents > 0 then
- p.push('<FxCompile>')
- p.outln(contents)
- p.pop('</FxCompile>')
- end
- end
- end
- --
- -- Write out the resource compiler block.
- --
- m.elements.resourceCompile = function(cfg)
- return {
- m.resourcePreprocessorDefinitions,
- m.resourceAdditionalIncludeDirectories,
- m.culture,
- }
- end
- function m.resourceCompile(cfg)
- if p.config.hasFile(cfg, path.isresourcefile) then
- local contents = p.capture(function ()
- p.push()
- p.callArray(m.elements.resourceCompile, cfg)
- p.pop()
- end)
- if #contents > 0 then
- p.push('<ResourceCompile>')
- p.outln(contents)
- p.pop('</ResourceCompile>')
- end
- end
- end
- --
- -- Write out the linker tool block.
- --
- m.elements.linker = function(cfg, explicit)
- return {
- m.link,
- m.lib,
- m.linkLibraryDependencies,
- }
- end
- function m.linker(cfg)
- local explicit = vstudio.needsExplicitLink(cfg)
- p.callArray(m.elements.linker, cfg, explicit)
- end
- m.elements.link = function(cfg, explicit)
- if cfg.kind == p.STATICLIB then
- return {
- m.subSystem,
- m.fullProgramDatabaseFile,
- m.generateDebugInformation,
- m.optimizeReferences,
- }
- else
- return {
- m.subSystem,
- m.fullProgramDatabaseFile,
- m.generateDebugInformation,
- m.optimizeReferences,
- m.additionalDependencies,
- m.additionalLibraryDirectories,
- m.importLibrary,
- m.entryPointSymbol,
- m.generateMapFile,
- m.moduleDefinitionFile,
- m.treatLinkerWarningAsErrors,
- m.ignoreDefaultLibraries,
- m.dataExecutionPrevention, --OpenMPT
- m.largeAddressAware,
- m.targetMachine,
- m.additionalLinkOptions,
- m.programDatabaseFile,
- m.assemblyDebug,
- }
- end
- end
- function m.link(cfg, explicit)
- local contents = p.capture(function ()
- p.push()
- p.callArray(m.elements.link, cfg, explicit)
- p.pop()
- end)
- if #contents > 0 then
- p.push('<Link>')
- p.outln(contents)
- p.pop('</Link>')
- end
- end
- m.elements.lib = function(cfg, explicit)
- if cfg.kind == p.STATICLIB then
- return {
- m.additionalDependencies,
- m.additionalLibraryDirectories,
- m.treatLinkerWarningAsErrors,
- m.targetMachine,
- m.additionalLinkOptions,
- }
- else
- return {}
- end
- end
- function m.lib(cfg, explicit)
- local contents = p.capture(function ()
- p.push()
- p.callArray(m.elements.lib, cfg, explicit)
- p.pop()
- end)
- if #contents > 0 then
- p.push('<Lib>')
- p.outln(contents)
- p.pop('</Lib>')
- end
- end
- --
- -- Write the manifest section.
- --
- m.elements.manifest = function(cfg)
- return {
- m.enableDpiAwareness,
- m.additionalManifestFiles,
- }
- end
- function m.manifest(cfg)
- if cfg.kind ~= p.STATICLIB then
- local contents = p.capture(function ()
- p.push()
- p.callArray(m.elements.manifest, cfg)
- p.pop()
- end)
- if #contents > 0 then
- p.push('<Manifest>')
- p.outln(contents)
- p.pop('</Manifest>')
- end
- end
- end
- ---
- -- Write out the pre- and post-build event settings.
- ---
- function m.buildEvents(cfg)
- local write = function (event)
- local name = event .. "Event"
- local field = event:lower()
- local steps = cfg[field .. "commands"]
- local msg = cfg[field .. "message"]
- if #steps > 0 then
- steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location)
- p.push('<%s>', name)
- p.x('<Command>%s</Command>', table.implode(steps, "", "", "\r\n"))
- if msg then
- p.x('<Message>%s</Message>', msg)
- end
- p.pop('</%s>', name)
- end
- end
- write("PreBuild")
- write("PreLink")
- write("PostBuild")
- end
- ---
- -- Transform property to string
- ---
- function m.getRulePropertyString(rule, prop, value, kind)
- -- list of paths
- if kind == "list:path" then
- return table.concat(vstudio.path(cfg, value), ';')
- end
- -- path
- if kind == "path" then
- return vstudio.path(cfg, value)
- end
- -- list
- if type(value) == "table" then
- return table.concat(value, ";")
- end
- -- enum
- if prop.values then
- value = table.findKeyByValue(prop.values, value)
- end
- -- primitive
- return tostring(value)
- end
- ---
- -- Write out project-level custom rule variables.
- ---
- function m.ruleVars(cfg)
- for i = 1, #cfg.rules do
- local rule = p.global.getRule(cfg.rules[i])
- local contents = p.capture(function ()
- p.push()
- for prop in p.rule.eachProperty(rule) do
- local fld = p.rule.getPropertyField(rule, prop)
- local value = cfg[fld.name]
- if value ~= nil then
- value = m.getRulePropertyString(rule, prop, value, fld.kind)
- if value ~= nil and #value > 0 then
- m.element(prop.name, nil, '%s', value)
- end
- end
- end
- p.pop()
- end)
- if #contents > 0 then
- p.push('<%s>', rule.name)
- p.outln(contents)
- p.pop('</%s>', rule.name)
- end
- end
- end
- --
- -- Reference any managed assemblies listed in the links()
- --
- function m.assemblyReferences(prj)
- -- Visual Studio doesn't support per-config references; use
- -- whatever is contained in the first configuration
- local cfg = project.getfirstconfig(prj)
- local refs = config.getlinks(cfg, "system", "fullpath", "managed")
- if #refs > 0 then
- p.push('<ItemGroup>')
- for i = 1, #refs do
- local value = refs[i]
- -- If the link contains a '/' then it is a relative path to
- -- a local assembly. Otherwise treat it as a system assembly.
- if value:find('/', 1, true) then
- p.push('<Reference Include="%s">', path.getbasename(value))
- p.x('<HintPath>%s</HintPath>', path.translate(value))
- p.pop('</Reference>')
- else
- p.x('<Reference Include="%s" />', path.getbasename(value))
- end
- end
- p.pop('</ItemGroup>')
- end
- end
- function m.generatedFile(cfg, file)
- if file.generated then
- local path = path.translate(file.dependsOn.relpath)
- m.element("AutoGen", nil, 'true')
- m.element("DependentUpon", nil, path)
- end
- end
- ---
- -- Write out the list of source code files, and any associated configuration.
- ---
- function m.files(prj)
- local groups = m.categorizeSources(prj)
- for _, group in ipairs(groups) do
- group.category.emitFiles(prj, group)
- end
- end
- m.categories = {}
- ---
- -- ClInclude group
- ---
- m.categories.ClInclude = {
- name = "ClInclude",
- extensions = { ".h", ".hh", ".hpp", ".hxx", ".inl" },
- priority = 1,
- emitFiles = function(prj, group)
- m.emitFiles(prj, group, "ClInclude", {m.generatedFile})
- end,
- emitFilter = function(prj, group)
- m.filterGroup(prj, group, "ClInclude")
- end
- }
- ---
- -- ClCompile group
- ---
- m.categories.ClCompile = {
- name = "ClCompile",
- extensions = { ".cc", ".cpp", ".cxx", ".c++", ".c", ".s", ".m", ".mm" },
- priority = 2,
- emitFiles = function(prj, group)
- local fileCfgFunc = function(fcfg, condition)
- if fcfg then
- return {
- m.excludedFromBuild,
- m.objectFileName,
- m.clCompilePreprocessorDefinitions,
- m.clCompileUndefinePreprocessorDefinitions,
- m.optimization,
- m.forceIncludes,
- m.precompiledHeader,
- m.enableEnhancedInstructionSet,
- m.additionalCompileOptions,
- m.disableSpecificWarnings,
- m.treatSpecificWarningsAsErrors,
- m.basicRuntimeChecks,
- m.exceptionHandling,
- m.compileAsManaged,
- m.compileAs,
- m.runtimeTypeInfo,
- m.warningLevelFile,
- }
- else
- return {
- m.excludedFromBuild
- }
- end
- end
- m.emitFiles(prj, group, "ClCompile", {m.generatedFile}, fileCfgFunc)
- end,
- emitFilter = function(prj, group)
- m.filterGroup(prj, group, "ClCompile")
- end
- }
- ---
- -- FxCompile group
- ---
- m.categories.FxCompile = {
- name = "FxCompile",
- extensions = { ".hlsl" },
- priority = 4,
- emitFiles = function(prj, group)
- local fileCfgFunc = function(fcfg, condition)
- if fcfg then
- return {
- m.excludedFromBuild,
- m.fxCompilePreprocessorDefinition,
- m.fxCompileAdditionalIncludeDirs,
- m.fxCompileShaderType,
- m.fxCompileShaderModel,
- m.fxCompileShaderEntry,
- m.fxCompileShaderVariableName,
- m.fxCompileShaderHeaderOutput,
- m.fxCompileShaderObjectOutput,
- m.fxCompileShaderAssembler,
- m.fxCompileShaderAssemblerOutput,
- m.fxCompileShaderAdditionalOptions,
- }
- else
- return {
- m.excludedFromBuild
- }
- end
- end
- m.emitFiles(prj, group, "FxCompile", nil, fileCfgFunc)
- end,
- emitFilter = function(prj, group)
- m.filterGroup(prj, group, "FxCompile")
- end
- }
- ---
- -- None group
- ---
- m.categories.None = {
- name = "None",
- priority = 5,
- emitFiles = function(prj, group)
- m.emitFiles(prj, group, "None", {m.generatedFile})
- end,
- emitFilter = function(prj, group)
- m.filterGroup(prj, group, "None")
- end
- }
- ---
- -- ResourceCompile group
- ---
- m.categories.ResourceCompile = {
- name = "ResourceCompile",
- extensions = ".rc",
- priority = 6,
- emitFiles = function(prj, group)
- local fileCfgFunc = {
- m.excludedFromBuild
- }
- m.emitFiles(prj, group, "ResourceCompile", nil, fileCfgFunc)
- end,
- emitFilter = function(prj, group)
- m.filterGroup(prj, group, "ResourceCompile")
- end
- }
- ---
- -- CustomBuild group
- ---
- m.categories.CustomBuild = {
- name = "CustomBuild",
- priority = 7,
- emitFiles = function(prj, group)
- local fileFunc = {
- m.fileType
- }
- local fileCfgFunc = {
- m.excludedFromBuild,
- m.buildCommands,
- m.buildOutputs,
- m.linkObjects,
- m.buildMessage,
- m.buildAdditionalInputs
- }
- m.emitFiles(prj, group, "CustomBuild", fileFunc, fileCfgFunc, function (cfg, fcfg)
- return fileconfig.hasCustomBuildRule(fcfg)
- end)
- end,
- emitFilter = function(prj, group)
- m.filterGroup(prj, group, "CustomBuild")
- end
- }
- ---
- -- Midl group
- ---
- m.categories.Midl = {
- name = "Midl",
- extensions = ".idl",
- priority = 8,
- emitFiles = function(prj, group)
- local fileCfgFunc = {
- m.excludedFromBuild
- }
- m.emitFiles(prj, group, "Midl", nil, fileCfgFunc, function(cfg)
- return cfg.system == p.WINDOWS
- end)
- end,
- emitFilter = function(prj, group)
- m.filterGroup(prj, group, "Midl")
- end
- }
- ---
- -- Masm group
- ---
- m.categories.Masm = {
- name = "Masm",
- extensions = ".asm",
- priority = 9,
- emitFiles = function(prj, group)
- local fileCfgFunc = function(fcfg, condition)
- if fcfg then
- return {
- m.MasmPreprocessorDefinitions,
- m.excludedFromBuild,
- m.exceptionHandlingSEH,
- }
- else
- return {
- m.excludedFromBuild
- }
- end
- end
- m.emitFiles(prj, group, "Masm", nil, fileCfgFunc)
- end,
- emitFilter = function(prj, group)
- m.filterGroup(prj, group, "Masm")
- end,
- emitExtensionSettings = function(prj, group)
- p.w('<Import Project="$(VCTargetsPath)\\BuildCustomizations\\masm.props" />')
- end,
- emitExtensionTargets = function(prj, group)
- p.w('<Import Project="$(VCTargetsPath)\\BuildCustomizations\\masm.targets" />')
- end
- }
- ---
- -- Image group
- ---
- m.categories.Image = {
- name = "Image",
- extensions = { ".gif", ".jpg", ".jpe", ".png", ".bmp", ".dib", "*.tif", "*.wmf", "*.ras", "*.eps", "*.pcx", "*.pcd", "*.tga", "*.dds" },
- priority = 10,
- emitFiles = function(prj, group)
- local fileCfgFunc = function(fcfg, condition)
- return {
- m.excludedFromBuild
- }
- end
- m.emitFiles(prj, group, "Image", nil, fileCfgFunc)
- end,
- emitFilter = function(prj, group)
- m.filterGroup(prj, group, "Image")
- end
- }
- ---
- -- Natvis group
- ---
- m.categories.Natvis = {
- name = "Natvis",
- extensions = { ".natvis" },
- priority = 11,
- emitFiles = function(prj, group)
- m.emitFiles(prj, group, "Natvis", {m.generatedFile})
- end,
- emitFilter = function(prj, group)
- m.filterGroup(prj, group, "Natvis")
- end
- }
- ---
- -- Categorize files into groups.
- ---
- function m.categorizeSources(prj)
- -- if we already did this, return the cached result.
- if prj._vc2010_sources then
- return prj._vc2010_sources
- end
- -- build the new group table.
- local result = {}
- local groups = {}
- prj._vc2010_sources = result
- local tr = project.getsourcetree(prj)
- tree.traverse(tr, {
- onleaf = function(node)
- local cat = m.categorizeFile(prj, node)
- groups[cat.name] = groups[cat.name] or {
- category = cat,
- files = {}
- }
- table.insert(groups[cat.name].files, node)
- end
- })
- -- sort by relative-to path; otherwise VS will reorder the files
- for name, group in pairs(groups) do
- table.sort(group.files, function (a, b)
- return a.relpath < b.relpath
- end)
- table.insert(result, group)
- end
- -- sort by category priority then name; so we get stable results.
- table.sort(result, function (a, b)
- if (a.category.priority == b.category.priority) then
- return a.category.name < b.category.name
- end
- return a.category.priority < b.category.priority
- end)
- return result
- end
- function m.categorizeFile(prj, file)
- for cfg in project.eachconfig(prj) do
- local fcfg = fileconfig.getconfig(file, cfg)
- if fcfg then
- -- If any configuration for this file uses a custom build step, that's the category to use
- if fileconfig.hasCustomBuildRule(fcfg) then
- return m.categories.CustomBuild
- end
- -- also check for buildaction
- if fcfg.buildaction then
- return m.categories[fcfg.buildaction] or m.categories.None
- end
- end
- end
- -- If there is a custom rule associated with it, use that
- local rule = p.global.getRuleForFile(file.name, prj.rules)
- if rule then
- return {
- name = rule.name,
- priority = 100,
- rule = rule,
- emitFiles = function(prj, group)
- m.emitRuleFiles(prj, group)
- end,
- emitFilter = function(prj, group)
- m.filterGroup(prj, group, group.category.name)
- end
- }
- end
- -- Otherwise use the file extension to deduce a category
- for _, cat in pairs(m.categories) do
- if cat.extensions and path.hasextension(file.name, cat.extensions) then
- return cat
- end
- end
- return m.categories.None
- end
- function m.configPair(cfg)
- return vstudio.projectPlatform(cfg) .. "|" .. vstudio.archFromConfig(cfg, true)
- end
- function m.getTotalCfgCount(prj)
- if prj._totalCfgCount then
- return prj._totalCfgCount
- else
- local result = 0
- for _ in p.project.eachconfig(prj) do
- result = result + 1
- end
- -- cache result
- prj._totalCfgCount = result
- return result
- end
- end
- function m.indexConditionalElements()
- local nameMap, nameList, settingList
- nameMap = {}
- nameList = {} -- to preserve ordering
- settingList = {} -- to preserve ordering
- for _, element in ipairs(m.conditionalElements) do
- local settingMap = nameMap[element.name]
- if not settingMap then
- settingMap = {}
- nameMap[element.name] = settingMap
- if not table.contains(nameList, element.name) then
- table.insert(nameList, element.name)
- end
- end
- --setting will either be value or args
- local elementSet = settingMap[element.setting]
- if elementSet then
- table.insert(elementSet, element)
- else
- elementSet = {element}
- settingMap[element.setting] = elementSet
- if not table.contains(settingList, element.setting) then
- table.insert(settingList, element.setting)
- end
- end
- end
- return nameMap, nameList, settingList
- end
- function m.emitConditionalElements(prj)
- local keyCount = function(tbl)
- local count = 0
- for _ in pairs(tbl) do count = count + 1 end
- return count
- end
- local nameMap, nameList, settingList
- nameMap, nameList, settingList = m.indexConditionalElements()
- local totalCfgCount = m.getTotalCfgCount(prj)
- for _, name in ipairs(nameList) do
- local settingMap = nameMap[name]
- local done = false
- if keyCount(settingMap)==1 then
- for _, setting in ipairs(settingList) do
- local elements = settingMap[setting]
- if elements~=nil and #elements==totalCfgCount then
- local element = elements[1]
- local format = string.format('<%s>%s</%s>', name, element.value, name)
- p.w(format, table.unpack(element.args))
- done = true
- end
- end
- end
- if not done then
- for _, setting in ipairs(settingList) do
- local elements = settingMap[setting]
- if elements then
- for _, element in ipairs(elements) do
- local format = string.format('<%s %s>%s</%s>', name, m.conditionFromConfigText(element.condition), element.value, name)
- p.w(format, table.unpack(element.args))
- end
- end
- end
- end
- end
- end
- function m.emitFiles(prj, group, tag, fileFunc, fileCfgFunc, checkFunc)
- local files = group.files
- if files and #files > 0 then
- p.push('<ItemGroup>')
- for _, file in ipairs(files) do
- local contents = p.capture(function ()
- p.push()
- p.callArray(fileFunc, cfg, file)
- m.conditionalElements = {}
- for cfg in project.eachconfig(prj) do
- local fcfg = fileconfig.getconfig(file, cfg)
- if not checkFunc or checkFunc(cfg, fcfg) then
- p.callArray(fileCfgFunc, fcfg, m.configPair(cfg))
- end
- end
- if #m.conditionalElements > 0 then
- m.emitConditionalElements(prj)
- end
- p.pop()
- end)
- local rel = path.translate(file.relpath)
- -- SharedItems projects paths are prefixed with a magical variable
- if prj.kind == p.SHAREDITEMS then
- rel = "$(MSBuildThisFileDirectory)" .. rel
- end
- if #contents > 0 then
- p.push('<%s Include="%s">', tag, rel)
- p.outln(contents)
- p.pop('</%s>', tag)
- else
- p.x('<%s Include="%s" />', tag, rel)
- end
- end
- p.pop('</ItemGroup>')
- end
- end
- function m.emitRuleFiles(prj, group)
- local files = group.files
- local rule = group.category.rule
- if files and #files > 0 then
- p.push('<ItemGroup>')
- for _, file in ipairs(files) do
- local contents = p.capture(function()
- p.push()
- for prop in p.rule.eachProperty(rule) do
- local fld = p.rule.getPropertyField(rule, prop)
- m.conditionalElements = {}
- for cfg in project.eachconfig(prj) do
- local fcfg = fileconfig.getconfig(file, cfg)
- if fcfg and fcfg[fld.name] then
- local value = m.getRulePropertyString(rule, prop, fcfg[fld.name])
- if value and #value > 0 then
- m.element(prop.name, m.configPair(cfg), '%s', value)
- end
- end
- end
- if #m.conditionalElements > 0 then
- m.emitConditionalElements(prj)
- end
- end
- p.pop()
- end)
- if #contents > 0 then
- p.push('<%s Include=\"%s\">', rule.name, path.translate(file.relpath))
- p.outln(contents)
- p.pop('</%s>', rule.name)
- else
- p.x('<%s Include=\"%s\" />', rule.name, path.translate(file.relpath))
- end
- end
- p.pop('</ItemGroup>')
- end
- end
- function m.isClrMixed(prj)
- -- check to see if any files are marked with clr
- local isMixed = false
- if not prj.clr or prj.clr == p.OFF then
- if prj._isClrMixed ~= nil then
- isMixed = prj._isClrMixed
- else
- table.foreachi(prj._.files, function(file)
- for cfg in p.project.eachconfig(prj) do
- local fcfg = p.fileconfig.getconfig(file, cfg)
- if fcfg and fcfg.clr and fcfg.clr ~= p.OFF then
- isMixed = true
- end
- end
- end)
- prj._isClrMixed = isMixed -- cache the results
- end
- end
- return isMixed
- end
- --
- -- Generate the list of project dependencies.
- --
- m.elements.projectReferences = function(prj, ref)
- if prj.clr ~= p.OFF or (m.isClrMixed(prj) and ref and ref.kind ~=p.STATICLIB) then
- return {
- m.referenceProject,
- m.referencePrivate,
- m.referenceOutputAssembly,
- m.referenceCopyLocalSatelliteAssemblies,
- m.referenceLinkLibraryDependencies,
- m.referenceUseLibraryDependences,
- }
- else
- return {
- m.referenceProject,
- }
- end
- end
- function m.projectReferences(prj)
- local refs = project.getdependencies(prj, 'linkOnly')
- -- Handle linked shared items projects
- local contents = p.capture(function()
- p.push()
- for _, ref in ipairs(refs) do
- if ref.kind == p.SHAREDITEMS then
- local relpath = vstudio.path(prj, vstudio.projectfile(ref))
- p.x('<Import Project="%s" Label="Shared" />', relpath)
- end
- end
- p.pop()
- end)
- if #contents > 0 then
- p.push('<ImportGroup Label="Shared">')
- p.outln(contents)
- p.pop('</ImportGroup>')
- end
- -- Handle all other linked projects
- local contents = p.capture(function()
- p.push()
- for _, ref in ipairs(refs) do
- if ref.kind ~= p.SHAREDITEMS then
- local relpath = vstudio.path(prj, vstudio.projectfile(ref))
- p.push('<ProjectReference Include=\"%s\">', relpath)
- p.callArray(m.elements.projectReferences, prj, ref)
- p.pop('</ProjectReference>')
- end
- end
- p.pop()
- end)
- if #contents > 0 then
- p.push('<ItemGroup>')
- p.outln(contents)
- p.pop('</ItemGroup>')
- end
- end
- ---------------------------------------------------------------------------
- --
- -- Handlers for individual project elements
- --
- ---------------------------------------------------------------------------
- function m.additionalDependencies(cfg, explicit)
- local links
- -- check to see if this project uses an external toolset. If so, let the
- -- toolset define the format of the links
- local toolset = config.toolset(cfg)
- if cfg.system ~= premake.WINDOWS and toolset then
- links = toolset.getlinks(cfg, not explicit)
- else
- links = vstudio.getLinks(cfg, explicit)
- end
- if #links > 0 then
- links = path.translate(table.concat(links, ";"))
- m.element("AdditionalDependencies", nil, "%s;%%(AdditionalDependencies)", links)
- end
- end
- function m.additionalIncludeDirectories(cfg, includedirs)
- if #includedirs > 0 then
- local dirs = vstudio.path(cfg, includedirs)
- if #dirs > 0 then
- m.element("AdditionalIncludeDirectories", nil, "%s;%%(AdditionalIncludeDirectories)", table.concat(dirs, ";"))
- end
- end
- end
- function m.additionalLibraryDirectories(cfg)
- if #cfg.libdirs > 0 then
- local dirs = table.concat(vstudio.path(cfg, cfg.libdirs), ";")
- m.element("AdditionalLibraryDirectories", nil, "%s;%%(AdditionalLibraryDirectories)", dirs)
- end
- end
- function m.additionalManifestFiles(cfg)
- -- get the manifests files
- local manifests = {}
- for _, fname in ipairs(cfg.files) do
- if path.getextension(fname) == ".manifest" then
- table.insert(manifests, project.getrelative(cfg.project, fname))
- end
- end
- if #manifests > 0 then
- m.element("AdditionalManifestFiles", nil, "%s;%%(AdditionalManifestFiles)", table.concat(manifests, ";"))
- end
- end
- function m.additionalUsingDirectories(cfg)
- if #cfg.usingdirs > 0 then
- local dirs = vstudio.path(cfg, cfg.usingdirs)
- if #dirs > 0 then
- m.element("AdditionalUsingDirectories", nil, "%s;%%(AdditionalUsingDirectories)", table.concat(dirs, ";"))
- end
- end
- end
- function m.dataExecutionPrevention(cfg) --OpenMPT
- if (cfg.dataexecutionprevention == 'Off') then --OpenMPT
- m.element("DataExecutionPrevention", nil, 'false') --OpenMPT
- end --OpenMPT
- end --OpenMPT
- function m.largeAddressAware(cfg)
- if (cfg.largeaddressaware == true) then
- m.element("LargeAddressAware", nil, 'true')
- end
- end
- function m.languageStandard(cfg)
- if _ACTION >= "vs2022" then --OpenMPT
- if (cfg.cppdialect == "C++14") then --OpenMPT
- m.element("LanguageStandard", nil, 'stdcpp14') --OpenMPT
- elseif (cfg.cppdialect == "C++17") then --OpenMPT
- m.element("LanguageStandard", nil, 'stdcpp17') --OpenMPT
- elseif (cfg.cppdialect == "C++20") then --OpenMPT
- m.element("LanguageStandard", nil, 'stdcpp20') --OpenMPT
- elseif (cfg.cppdialect == "C++latest") then --OpenMPT
- m.element("LanguageStandard", nil, 'stdcpplatest') --OpenMPT
- end --OpenMPT
- else --OpenMPT
- if _ACTION >= "vs2017" then
- if (cfg.cppdialect == "C++14") then
- m.element("LanguageStandard", nil, 'stdcpp14')
- elseif (cfg.cppdialect == "C++17") then
- m.element("LanguageStandard", nil, 'stdcpp17')
- elseif (cfg.cppdialect == "C++20") then
- m.element("LanguageStandard", nil, 'stdcpplatest')
- elseif (cfg.cppdialect == "C++latest") then
- m.element("LanguageStandard", nil, 'stdcpplatest')
- end
- end
- end --OpenMPT
- end
- function m.conformanceMode(cfg)
- if _ACTION >= "vs2017" then
- if cfg.conformancemode ~= nil then
- if cfg.conformancemode then
- m.element("ConformanceMode", nil, "true")
- else
- m.element("ConformanceMode", nil, "false")
- end
- end
- end
- end
- function m.structMemberAlignment(cfg)
- local map = {
- [1] = "1Byte",
- [2] = "2Bytes",
- [4] = "4Bytes",
- [8] = "8Bytes",
- [16] = "16Bytes"
- }
- local value = map[cfg.structmemberalign]
- if value then
- m.element("StructMemberAlignment", nil, value)
- end
- end
- function m.useFullPaths(cfg)
- if cfg.useFullPaths ~= nil then
- if cfg.useFullPaths then
- m.element("UseFullPaths", nil, "true")
- else
- m.element("UseFullPaths", nil, "false")
- end
- end
- end
- function m.removeUnreferencedCodeData(cfg)
- if cfg.removeUnreferencedCodeData ~= nil then
- if cfg.removeUnreferencedCodeData then
- m.element("RemoveUnreferencedCodeData", nil, "true")
- else
- m.element("RemoveUnreferencedCodeData", nil, "false")
- end
- end
- end
- function m.additionalCompileOptions(cfg, condition)
- local opts = cfg.buildoptions
- if _ACTION == "vs2015" or vstudio.isMakefile(cfg) then
- if (cfg.cppdialect == "C++14") then
- table.insert(opts, "/std:c++14")
- elseif (cfg.cppdialect == "C++17") then
- table.insert(opts, "/std:c++17")
- elseif (cfg.cppdialect == "C++20") then
- table.insert(opts, "/std:c++latest")
- elseif (cfg.cppdialect == "C++latest") then
- table.insert(opts, "/std:c++latest")
- end
- end
- if cfg.toolset and cfg.toolset:startswith("msc") then
- local value = iif(cfg.unsignedchar, "On", "Off")
- table.insert(opts, p.tools.msc.shared.unsignedchar[value])
- elseif _ACTION >= "vs2019" and cfg.toolset and cfg.toolset == "clang" then
- local value = iif(cfg.unsignedchar, "On", "Off")
- table.insert(opts, p.tools.msc.shared.unsignedchar[value])
- end
- if #opts > 0 then
- opts = table.concat(opts, " ")
- m.element("AdditionalOptions", condition, '%s %%(AdditionalOptions)', opts)
- end
- end
- function m.additionalLinkOptions(cfg)
- if #cfg.linkoptions > 0 then
- local opts = table.concat(cfg.linkoptions, " ")
- m.element("AdditionalOptions", nil, "%s %%(AdditionalOptions)", opts)
- end
- end
- function m.compileAsManaged(fcfg, condition)
- if fcfg.clr and fcfg ~= p.OFF then
- m.element("CompileAsManaged", condition, "true")
- end
- end
- function m.basicRuntimeChecks(cfg, condition)
- local prjcfg, filecfg = p.config.normalize(cfg)
- local runtime = config.getruntime(prjcfg) or iif(config.isDebugBuild(cfg), "Debug", "Release")
- if filecfg then
- if filecfg.flags.NoRuntimeChecks or (config.isOptimizedBuild(filecfg) and runtime:endswith("Debug")) then
- m.element("BasicRuntimeChecks", condition, "Default")
- end
- else
- if prjcfg.flags.NoRuntimeChecks or (config.isOptimizedBuild(prjcfg) and runtime:endswith("Debug")) then
- m.element("BasicRuntimeChecks", nil, "Default")
- end
- end
- end
- function m.buildInputs(cfg, condition)
- if cfg.buildinputs and #cfg.buildinputs > 0 then
- local inputs = project.getrelative(cfg.project, cfg.buildinputs)
- m.element("Inputs", condition, '%s', table.concat(inputs, ";"))
- end
- end
- function m.buildAdditionalInputs(fcfg, condition)
- if fcfg.buildinputs and #fcfg.buildinputs > 0 then
- local inputs = project.getrelative(fcfg.project, fcfg.buildinputs)
- m.element("AdditionalInputs", condition, '%s', table.concat(inputs, ";"))
- end
- end
- function m.buildCommands(fcfg, condition)
- if #fcfg.buildcommands > 0 then
- local commands = os.translateCommandsAndPaths(fcfg.buildcommands, fcfg.project.basedir, fcfg.project.location)
- m.element("Command", condition, '%s', table.concat(commands,'\r\n'))
- end
- end
- function m.buildLog(cfg)
- if cfg.buildlog and #cfg.buildlog > 0 then
- p.push('<BuildLog>')
- m.element("Path", nil, "%s", vstudio.path(cfg, cfg.buildlog))
- p.pop('</BuildLog>')
- end
- end
- function m.buildMessage(fcfg, condition)
- if fcfg.buildmessage then
- m.element("Message", condition, '%s', fcfg.buildmessage)
- end
- end
- function m.buildOutputs(fcfg, condition)
- if #fcfg.buildoutputs > 0 then
- local outputs = project.getrelative(fcfg.project, fcfg.buildoutputs)
- m.element("Outputs", condition, '%s', table.concat(outputs, ";"))
- end
- end
- function m.linkObjects(fcfg, condition)
- if fcfg.linkbuildoutputs ~= nil then
- m.element("LinkObjects", condition, tostring(fcfg.linkbuildoutputs))
- end
- end
- function m.characterSet(cfg)
- if not vstudio.isMakefile(cfg) then
- local charactersets = {
- ASCII = "NotSet",
- MBCS = "MultiByte",
- Unicode = "Unicode",
- Default = "Unicode"
- }
- m.element("CharacterSet", nil, charactersets[cfg.characterset])
- end
- end
- function m.wholeProgramOptimization(cfg)
- if cfg.flags.LinkTimeOptimization then
- m.element("WholeProgramOptimization", nil, "true")
- end
- end
- function m.spectreMitigations(cfg) --OpenMPT
- if (cfg.spectremitigations == 'On') then --OpenMPT
- if _ACTION >= "vs2017" then --OpenMPT
- m.element("SpectreMitigation", nil, "Spectre") --OpenMPT
- end --OpenMPT
- end --OpenMPT
- end --OpenMPT
- function m.clCompileAdditionalIncludeDirectories(cfg)
- m.additionalIncludeDirectories(cfg, cfg.includedirs)
- end
- function m.clCompileAdditionalUsingDirectories(cfg)
- m.additionalUsingDirectories(cfg, cfg.usingdirs)
- end
- function m.clCompilePreprocessorDefinitions(cfg, condition)
- local defines = cfg.defines
- if cfg.exceptionhandling == p.OFF then
- defines = table.join(defines, "_HAS_EXCEPTIONS=0")
- end
- m.preprocessorDefinitions(cfg, defines, false, condition)
- end
- function m.clCompileUndefinePreprocessorDefinitions(cfg, condition)
- m.undefinePreprocessorDefinitions(cfg, cfg.undefines, false, condition)
- end
- function m.clrSupport(cfg)
- local value
- if cfg.clr == "On" or cfg.clr == "Unsafe" then
- value = "true"
- elseif cfg.clr ~= p.OFF then
- value = cfg.clr
- end
- if value then
- m.element("CLRSupport", nil, value)
- end
- end
- function m.compileAs(cfg, condition)
- if p.languages.isc(cfg.compileas) then
- m.element("CompileAs", condition, "CompileAsC")
- elseif p.languages.iscpp(cfg.compileas) then
- m.element("CompileAs", condition, "CompileAsCpp")
- elseif cfg.compileas == "Module" then
- m.element("CompileAs", condition, "CompileAsCppModule")
- elseif cfg.compileas == "ModulePartition" then
- m.element("CompileAs", condition, "CompileAsCppModuleInternalPartition")
- elseif cfg.compileas == "HeaderUnit" then
- m.element("CompileAs", condition, "CompileAsHeaderUnit")
- end
- end
- function m.configurationType(cfg)
- local types = {
- SharedLib = "DynamicLibrary",
- StaticLib = "StaticLibrary",
- ConsoleApp = "Application",
- WindowedApp = "Application",
- Makefile = "Makefile",
- None = "Makefile",
- Utility = "Utility",
- }
- m.element("ConfigurationType", nil, types[cfg.kind])
- end
- function m.culture(cfg)
- local value = vstudio.cultureForLocale(cfg.locale)
- if value then
- m.element("Culture", nil, "0x%04x", tostring(value))
- end
- end
- function m.debugInformationFormat(cfg)
- local value
- local tool, toolVersion = p.config.toolset(cfg)
- if (cfg.symbols == p.ON) or (cfg.symbols == "FastLink") or (cfg.symbols == "Full") then
- if cfg.debugformat == "c7" then
- value = "OldStyle"
- elseif (cfg.architecture == "x86_64" and _ACTION < "vs2015") or
- cfg.clr ~= p.OFF or
- config.isOptimizedBuild(cfg) or
- cfg.editandcontinue == p.OFF or
- (toolVersion and toolVersion:startswith("LLVM-vs"))
- then
- value = "ProgramDatabase"
- else
- value = "EditAndContinue"
- end
- m.element("DebugInformationFormat", nil, value)
- elseif cfg.symbols == p.OFF then
- -- leave field blank for vs2013 and older to workaround bug
- if _ACTION < "vs2015" then
- value = ""
- else
- value = "None"
- end
- m.element("DebugInformationFormat", nil, value)
- end
- end
- function m.enableDpiAwareness(cfg)
- local awareness = {
- None = "false",
- High = "true",
- HighPerMonitor = "PerMonitorHighDPIAware",
- }
- local value = awareness[cfg.dpiawareness]
- if value then
- m.element("EnableDpiAwareness", nil, value)
- end
- end
- function m.enableEnhancedInstructionSet(cfg, condition)
- local v
- local x = cfg.vectorextensions
- if x == "AVX" and _ACTION > "vs2010" then
- v = "AdvancedVectorExtensions"
- elseif x == "AVX2" and _ACTION > "vs2012" then
- v = "AdvancedVectorExtensions2"
- elseif cfg.architecture ~= "x86_64" then
- if x == "SSE2" or x == "SSE3" or x == "SSSE3" or x == "SSE4.1" or x == "SSE4.2" then
- v = "StreamingSIMDExtensions2"
- elseif x == "SSE" then
- v = "StreamingSIMDExtensions"
- elseif x == "IA32" and _ACTION > "vs2010" then
- v = "NoExtensions"
- end
- end
- if v then
- m.element('EnableEnhancedInstructionSet', condition, v)
- end
- end
- function m.entryPointSymbol(cfg)
- if cfg.entrypoint then
- m.element("EntryPointSymbol", nil, cfg.entrypoint)
- end
- end
- function m.exceptionHandling(cfg, condition)
- if cfg.exceptionhandling == p.OFF then
- m.element("ExceptionHandling", condition, "false")
- elseif cfg.exceptionhandling == "SEH" then
- m.element("ExceptionHandling", condition, "Async")
- elseif cfg.exceptionhandling == "On" then
- m.element("ExceptionHandling", condition, "Sync")
- elseif cfg.exceptionhandling == "CThrow" then
- m.element("ExceptionHandling", condition, "SyncCThrow")
- end
- end
- function m.excludedFromBuild(filecfg, condition)
- if not filecfg or filecfg.flags.ExcludeFromBuild then
- m.element("ExcludedFromBuild", condition, "true")
- end
- end
- function m.exceptionHandlingSEH(filecfg, condition)
- if not filecfg or filecfg.exceptionhandling == "SEH" then
- m.element("UseSafeExceptionHandlers", condition, "true")
- end
- end
- function m.extensionsToDeleteOnClean(cfg)
- if #cfg.cleanextensions > 0 then
- local value = table.implode(cfg.cleanextensions, "*", ";", "")
- m.element("ExtensionsToDeleteOnClean", nil, value .. "$(ExtensionsToDeleteOnClean)")
- end
- end
- function m.fileType(cfg, file)
- m.element("FileType", nil, "Document")
- end
- function m.floatingPointModel(cfg)
- if cfg.floatingpoint and cfg.floatingpoint ~= "Default" then
- m.element("FloatingPointModel", nil, cfg.floatingpoint)
- end
- end
- function m.floatingPointExceptions(cfg)
- if cfg.floatingpointexceptions ~= nil then
- if cfg.floatingpointexceptions then
- m.element("FloatingPointExceptions", nil, "true")
- else
- m.element("FloatingPointExceptions", nil, "false")
- end
- end
- end
- function m.inlineFunctionExpansion(cfg)
- if cfg.inlining then
- local types = {
- Default = "Default",
- Disabled = "Disabled",
- Explicit = "OnlyExplicitInline",
- Auto = "AnySuitable",
- }
- m.element("InlineFunctionExpansion", nil, types[cfg.inlining])
- end
- end
- function m.forceIncludes(cfg, condition)
- if #cfg.forceincludes > 0 then
- local includes = vstudio.path(cfg, cfg.forceincludes)
- if #includes > 0 then
- m.element("ForcedIncludeFiles", condition, table.concat(includes, ';'))
- end
- end
- if #cfg.forceusings > 0 then
- local usings = vstudio.path(cfg, cfg.forceusings)
- if #usings > 0 then
- m.element("ForcedUsingFiles", condition, table.concat(usings, ';'))
- end
- end
- end
- function m.fullProgramDatabaseFile(cfg)
- if _ACTION >= "vs2015" and cfg.symbols == "FastLink" then
- m.element("FullProgramDatabaseFile", nil, "true")
- end
- end
- function m.assemblyDebug(cfg)
- if cfg.assemblydebug then
- m.element("AssemblyDebug", nil, "true")
- end
- end
- function m.functionLevelLinking(cfg)
- if cfg.functionlevellinking ~= nil then
- if cfg.functionlevellinking then
- m.element("FunctionLevelLinking", nil, "true")
- else
- m.element("FunctionLevelLinking", nil, "false")
- end
- elseif config.isOptimizedBuild(cfg) then
- m.element("FunctionLevelLinking", nil, "true")
- end
- end
- function m.generateDebugInformation(cfg)
- local lookup = {}
- if _ACTION >= "vs2017" then
- lookup[p.ON] = "true"
- lookup[p.OFF] = "false"
- lookup["FastLink"] = "DebugFastLink"
- lookup["Full"] = "DebugFull"
- elseif _ACTION == "vs2015" then
- lookup[p.ON] = "true"
- lookup[p.OFF] = "false"
- lookup["FastLink"] = "DebugFastLink"
- lookup["Full"] = "true"
- else
- lookup[p.ON] = "true"
- lookup[p.OFF] = "false"
- lookup["FastLink"] = "true"
- lookup["Full"] = "true"
- end
- local value = lookup[cfg.symbols]
- if value then
- m.element("GenerateDebugInformation", nil, value)
- end
- end
- function m.generateManifest(cfg)
- if cfg.flags.NoManifest then
- m.element("GenerateManifest", nil, "false")
- end
- end
- function m.generateMapFile(cfg)
- if cfg.flags.Maps then
- m.element("GenerateMapFile", nil, "true")
- end
- end
- function m.ignoreDefaultLibraries(cfg)
- if #cfg.ignoredefaultlibraries > 0 then
- local ignored = cfg.ignoredefaultlibraries
- for i = 1, #ignored do
- -- Add extension if required
- if not p.tools.msc.getLibraryExtensions()[ignored[i]:match("[^.]+$")] then
- ignored[i] = path.appendextension(ignored[i], ".lib")
- end
- end
- m.element("IgnoreSpecificDefaultLibraries", condition, table.concat(ignored, ';'))
- end
- end
- function m.ignoreWarnDuplicateFilename(prj)
- -- VS 2013 warns on duplicate file names, even those files which are
- -- contained in different, mututally exclusive configurations. See:
- -- http://connect.microsoft.com/VisualStudio/feedback/details/797460/incorrect-warning-msb8027-reported-for-files-excluded-from-build
- -- Premake already adds unique object names to conflicting file names, so
- -- just go ahead and disable that warning.
- if _ACTION > "vs2012" then
- m.element("IgnoreWarnCompileDuplicatedFilename", nil, "true")
- end
- end
- function m.ignoreImportLibrary(cfg)
- if cfg.kind == p.SHAREDLIB and cfg.flags.NoImportLib then
- m.element("IgnoreImportLibrary", nil, "true")
- end
- end
- function m.importLanguageTargets(prj)
- p.w('<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" />')
- end
- m.elements.importExtensionTargets = function(prj)
- return {
- m.importGroupTargets,
- m.importRuleTargets,
- m.importNuGetTargets,
- m.importBuildCustomizationsTargets
- }
- end
- function m.importExtensionTargets(prj)
- p.push('<ImportGroup Label="ExtensionTargets">')
- p.callArray(m.elements.importExtensionTargets, prj)
- p.pop('</ImportGroup>')
- end
- function m.importGroupTargets(prj)
- local groups = m.categorizeSources(prj)
- for _, group in ipairs(groups) do
- if group.category.emitExtensionTargets then
- group.category.emitExtensionTargets(prj, group)
- end
- end
- end
- function m.importRuleTargets(prj)
- for i = 1, #prj.rules do
- local rule = p.global.getRule(prj.rules[i])
- local loc = vstudio.path(prj, p.filename(rule, ".targets"))
- p.x('<Import Project="%s" />', loc)
- end
- end
- local function nuGetTargetsFile(prj, package)
- local packageAPIInfo = vstudio.nuget2010.packageAPIInfo(prj, package)
- 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))))
- end
- function m.importNuGetTargets(prj)
- if not vstudio.nuget2010.supportsPackageReferences(prj) then
- for i = 1, #prj.nuget do
- local targetsFile = nuGetTargetsFile(prj, prj.nuget[i])
- p.x('<Import Project="%s" Condition="Exists(\'%s\')" />', targetsFile, targetsFile)
- end
- end
- end
- function m.importBuildCustomizationsTargets(prj)
- for i, build in ipairs(prj.buildcustomizations) do
- p.w('<Import Project="$(VCTargetsPath)\\%s.targets" />', path.translate(build))
- end
- end
- function m.ensureNuGetPackageBuildImports(prj)
- if #prj.nuget > 0 then
- p.push('<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">')
- p.push('<PropertyGroup>')
- 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>')
- p.pop('</PropertyGroup>')
- for i = 1, #prj.nuget do
- local targetsFile = nuGetTargetsFile(prj, prj.nuget[i])
- p.x('<Error Condition="!Exists(\'%s\')" Text="$([System.String]::Format(\'$(ErrorText)\', \'%s\'))" />', targetsFile, targetsFile)
- end
- p.pop('</Target>')
- end
- end
- function m.importDefaultProps(prj)
- p.w('<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />')
- end
- function m.importLanguageSettings(prj)
- p.w('<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props" />')
- end
- m.elements.importExtensionSettings = function(prj)
- return {
- m.importGroupSettings,
- m.importRuleSettings,
- m.importBuildCustomizationsProps
- }
- end
- function m.importExtensionSettings(prj)
- p.push('<ImportGroup Label="ExtensionSettings">')
- p.callArray(m.elements.importExtensionSettings, prj)
- p.pop('</ImportGroup>')
- end
- function m.importGroupSettings(prj)
- local groups = m.categorizeSources(prj)
- for _, group in ipairs(groups) do
- if group.category.emitExtensionSettings then
- group.category.emitExtensionSettings(prj, group)
- end
- end
- end
- function m.importRuleSettings(prj)
- for i = 1, #prj.rules do
- local rule = p.global.getRule(prj.rules[i])
- local loc = vstudio.path(prj, p.filename(rule, ".props"))
- p.x('<Import Project="%s" />', loc)
- end
- end
- function m.importBuildCustomizationsProps(prj)
- for i, build in ipairs(prj.buildcustomizations) do
- p.w('<Import Project="$(VCTargetsPath)\\%s.props" />', path.translate(build))
- end
- end
- function m.importLibrary(cfg)
- if cfg.kind == p.SHAREDLIB then
- m.element("ImportLibrary", nil, "%s", path.translate(cfg.linktarget.relpath))
- end
- end
- function m.includePath(cfg)
- local dirs = vstudio.path(cfg, cfg.sysincludedirs)
- if #dirs > 0 then
- m.element("IncludePath", nil, "%s;$(IncludePath)", table.concat(dirs, ";"))
- end
- end
- function m.intDir(cfg)
- local objdir = vstudio.path(cfg, cfg.objdir)
- m.element("IntDir", nil, "%s\\", objdir)
- end
- function m.intrinsicFunctions(cfg)
- if cfg.intrinsics ~= nil then
- if cfg.intrinsics then
- m.element("IntrinsicFunctions", nil, "true")
- else
- m.element("IntrinsicFunctions", nil, "false")
- end
- elseif config.isOptimizedBuild(cfg) then
- m.element("IntrinsicFunctions", nil, "true")
- end
- end
- function m.justMyCodeDebugging(cfg)
- if _ACTION >= "vs2017" then
- local jmc = cfg.justmycode
- if jmc == "On" then
- m.element("SupportJustMyCode", nil, "true")
- elseif jmc == "Off" then
- m.element("SupportJustMyCode", nil, "false")
- end
- end
- end
- function m.supportOpenMP(cfg)
- if cfg.openmp == "On" then
- m.element("OpenMPSupport", nil, "true")
- elseif cfg.openmp == "Off" then
- m.element("OpenMPSupport", nil, "false")
- end
- end
- function m.keyword(prj)
- -- try to determine what kind of targets we're building here
- local isWin, isManaged, isMakefile
- for cfg in project.eachconfig(prj) do
- if cfg.system == p.WINDOWS then
- isWin = true
- end
- if cfg.clr ~= p.OFF then
- isManaged = true
- end
- if vstudio.isMakefile(cfg) then
- isMakefile = true
- end
- end
- if isWin then
- if isMakefile then
- m.element("Keyword", nil, "MakeFileProj")
- else
- if isManaged or m.isClrMixed(prj) then
- m.targetFramework(prj)
- end
- if isManaged then
- m.element("Keyword", nil, "ManagedCProj")
- else
- m.element("Keyword", nil, "Win32Proj")
- end
- m.element("RootNamespace", nil, "%s", prj.name)
- end
- end
- end
- function m.libraryPath(cfg)
- local dirs = vstudio.path(cfg, cfg.syslibdirs)
- if #dirs > 0 then
- m.element("LibraryPath", nil, "%s;$(LibraryPath)", table.concat(dirs, ";"))
- end
- end
- function m.linkIncremental(cfg)
- if cfg.kind ~= p.STATICLIB then
- m.element("LinkIncremental", nil, "%s", tostring(config.canLinkIncremental(cfg)))
- end
- end
- function m.linkLibraryDependencies(cfg, explicit)
- -- Left to its own devices, VS will happily link against a project dependency
- -- that has been excluded from the build. As a workaround, disable dependency
- -- linking and list all siblings explicitly
- if explicit then
- p.push('<ProjectReference>')
- m.element("LinkLibraryDependencies", nil, "false")
- p.pop('</ProjectReference>')
- end
- end
- function m.MasmPreprocessorDefinitions(cfg, condition)
- if cfg.defines then
- m.preprocessorDefinitions(cfg, cfg.defines, false, condition)
- end
- end
- function m.minimalRebuild(cfg)
- if config.isOptimizedBuild(cfg) or
- cfg.flags.NoMinimalRebuild or
- cfg.flags.MultiProcessorCompile or
- cfg.debugformat == p.C7
- then
- m.element("MinimalRebuild", nil, "false")
- end
- end
- function m.moduleDefinitionFile(cfg)
- local df = config.findfile(cfg, ".def")
- if df then
- m.element("ModuleDefinitionFile", nil, "%s", df)
- end
- end
- function m.multiProcessorCompilation(cfg)
- if cfg.flags.MultiProcessorCompile then
- m.element("MultiProcessorCompilation", nil, "true")
- end
- end
- function m.nmakeBuildCommands(cfg)
- m.nmakeCommandLine(cfg, cfg.buildcommands, "Build")
- end
- function m.nmakeCleanCommands(cfg)
- m.nmakeCommandLine(cfg, cfg.cleancommands, "Clean")
- end
- function m.nmakeCommandLine(cfg, commands, phase)
- if #commands > 0 then
- commands = os.translateCommandsAndPaths(commands, cfg.project.basedir, cfg.project.location)
- commands = table.concat(p.esc(commands), p.eol())
- p.w('<NMake%sCommandLine>%s</NMake%sCommandLine>', phase, commands, phase)
- end
- end
- function m.nmakeIncludeDirs(cfg)
- if cfg.kind ~= p.NONE and #cfg.includedirs > 0 then
- local dirs = vstudio.path(cfg, cfg.includedirs)
- if #dirs > 0 then
- m.element("NMakeIncludeSearchPath", nil, "%s", table.concat(dirs, ";"))
- end
- end
- end
- function m.nmakeOutDirs(cfg)
- if vstudio.isMakefile(cfg) then
- m.outDir(cfg)
- m.intDir(cfg)
- end
- end
- function m.windowsSDKDesktopARMSupport(cfg)
- if cfg.system == p.WINDOWS then
- if cfg.architecture == p.ARM then
- p.w('<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>')
- end
- if cfg.architecture == p.ARM64 then
- p.w('<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>')
- end
- end
- end
- function m.nmakeOutput(cfg)
- m.element("NMakeOutput", nil, "$(OutDir)%s", cfg.buildtarget.name)
- end
- function m.nmakePreprocessorDefinitions(cfg)
- if cfg.kind ~= p.NONE and #cfg.defines > 0 then
- local defines = table.concat(cfg.defines, ";")
- defines = defines .. ";$(NMakePreprocessorDefinitions)"
- m.element('NMakePreprocessorDefinitions', nil, defines)
- end
- end
- function m.nmakeRebuildCommands(cfg)
- m.nmakeCommandLine(cfg, cfg.rebuildcommands, "ReBuild")
- end
- function m.objectFileName(fcfg)
- if fcfg.objname ~= fcfg.basename then
- m.element("ObjectFileName", m.configPair(fcfg.config), "$(IntDir)\\%s.obj", fcfg.objname)
- end
- end
- function m.omitDefaultLib(cfg)
- if cfg.flags.OmitDefaultLibrary then
- m.element("OmitDefaultLibName", nil, "true")
- end
- end
- function m.omitFramePointers(cfg)
- local map = { Off = "false", On = "true" }
- local value = map[cfg.omitframepointer]
- if value then
- m.element("OmitFramePointers", nil, value)
- end
- end
- function m.optimizeReferences(cfg)
- if config.isOptimizedBuild(cfg) then
- m.element("EnableCOMDATFolding", nil, "true")
- m.element("OptimizeReferences", nil, "true")
- end
- end
- function m.optimization(cfg, condition)
- local map = { Off="Disabled", On="Full", Debug="Disabled", Full="Full", Size="MinSpace", Speed="MaxSpeed" }
- local value = map[cfg.optimize]
- if value or not condition then
- m.element('Optimization', condition, value or "Disabled")
- end
- end
- function m.outDir(cfg)
- local outdir = vstudio.path(cfg, cfg.buildtarget.directory)
- m.element("OutDir", nil, "%s\\", outdir)
- end
- function m.executablePath(cfg)
- local dirs = vstudio.path(cfg, cfg.bindirs)
- if #dirs > 0 then
- dirs = table.translate(dirs, function(dir)
- if path.isabsolute(dir) then
- return dir
- end
- return "$(ProjectDir)" .. dir
- end)
- m.element("ExecutablePath", nil, "%s;$(ExecutablePath)", table.concat(dirs, ";"))
- end
- end
- function m.toolsVersion(cfg)
- local version = cfg.toolsversion
- if _ACTION >= "vs2017" and version then
- m.element("VCToolsVersion", nil, version)
- end
- end
- function m.platformToolset(cfg)
- local tool, version = p.config.toolset(cfg)
- if not version and _ACTION >= "vs2019" and cfg.toolset == "clang" then
- version = "ClangCL"
- end
- if not version then
- local value = p.action.current().toolset
- tool, version = p.tools.canonical(value)
- end
- if version then
- if cfg.kind == p.NONE or cfg.kind == p.MAKEFILE then
- if p.config.hasFile(cfg, path.iscppfile) or _ACTION >= "vs2015" then
- m.element("PlatformToolset", nil, version)
- end
- else
- m.element("PlatformToolset", nil, version)
- end
- end
- end
- function m.precompiledHeaderFile(fileName, cfg)
- m.element("PrecompiledHeaderFile", nil, "%s", fileName)
- end
- function m.precompiledHeader(cfg, condition)
- local prjcfg, filecfg = p.config.normalize(cfg)
- if filecfg then
- if prjcfg.pchsource == filecfg.abspath and not prjcfg.flags.NoPCH then
- m.element('PrecompiledHeader', condition, 'Create')
- elseif filecfg.flags.NoPCH then
- m.element('PrecompiledHeader', condition, 'NotUsing')
- end
- else
- if not prjcfg.flags.NoPCH and prjcfg.pchheader then
- m.element("PrecompiledHeader", nil, "Use")
- m.precompiledHeaderFile(prjcfg.pchheader, prjcfg)
- else
- m.element("PrecompiledHeader", nil, "NotUsing")
- end
- end
- end
- function m.preprocessorDefinitions(cfg, defines, escapeQuotes, condition)
- if #defines > 0 then
- defines = table.concat(defines, ";")
- if escapeQuotes then
- defines = defines:gsub('"', '\\"')
- end
- defines = defines .. ";%%(PreprocessorDefinitions)"
- m.element('PreprocessorDefinitions', condition, defines)
- end
- end
- function m.undefinePreprocessorDefinitions(cfg, undefines, escapeQuotes, condition)
- if #undefines > 0 then
- undefines = table.concat(undefines, ";")
- if escapeQuotes then
- undefines = undefines:gsub('"', '\\"')
- end
- undefines = undefines .. ";%%(UndefinePreprocessorDefinitions)"
- m.element('UndefinePreprocessorDefinitions', condition, undefines)
- end
- end
- local function getSymbolsPathRelative(cfg)
- if cfg.symbolspath and cfg.symbols ~= p.OFF and cfg.debugformat ~= "c7" then
- return p.project.getrelative(cfg.project, cfg.symbolspath)
- else
- return nil
- end
- end
- function m.programDatabaseFile(cfg)
- local value = getSymbolsPathRelative(cfg)
- if value then
- m.element("ProgramDatabaseFile", nil, value)
- end
- end
- function m.programDatabaseFileName(cfg)
- local value = getSymbolsPathRelative(cfg)
- if value then
- m.element("ProgramDataBaseFileName", nil, value)
- end
- end
- function m.projectGuid(prj)
- m.element("ProjectGuid", nil, "{%s}", prj.uuid)
- end
- function m.projectName(prj)
- if prj.name ~= prj.filename then
- m.element("ProjectName", nil, "%s", prj.name)
- end
- end
- function m.propertyGroup(cfg, label)
- local cond
- if cfg then
- cond = string.format(' %s', m.condition(cfg))
- end
- if label then
- label = string.format(' Label="%s"', label)
- end
- p.push('<PropertyGroup%s%s>', cond or "", label or "")
- end
- function m.propertySheets(cfg)
- p.push('<ImportGroup Label="PropertySheets" %s>', m.condition(cfg))
- p.w('<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists(\'$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\')" Label="LocalAppDataPlatform" />')
- p.pop('</ImportGroup>')
- end
- function m.propertySheetGroup(prj)
- for cfg in project.eachconfig(prj) do
- m.propertySheets(cfg)
- end
- end
- function m.referenceCopyLocalSatelliteAssemblies(prj, ref)
- m.element("CopyLocalSatelliteAssemblies", nil, "false")
- end
- function m.referenceLinkLibraryDependencies(prj, ref)
- m.element("LinkLibraryDependencies", nil, "true")
- end
- function m.referenceOutputAssembly(prj, ref)
- m.element("ReferenceOutputAssembly", nil, "true")
- end
- function m.referencePrivate(prj, ref)
- m.element("Private", nil, "true")
- end
- function m.referenceProject(prj, ref)
- m.element("Project", nil, "{%s}", ref.uuid)
- end
- function m.referenceUseLibraryDependences(prj, ref)
- m.element("UseLibraryDependencyInputs", nil, "false")
- end
- function m.resourceAdditionalIncludeDirectories(cfg)
- m.additionalIncludeDirectories(cfg, table.join(cfg.includedirs, cfg.resincludedirs))
- end
- function m.resourcePreprocessorDefinitions(cfg)
- local defines = table.join(cfg.defines, cfg.resdefines)
- if cfg.exceptionhandling == p.OFF then
- table.insert(defines, "_HAS_EXCEPTIONS=0")
- end
- m.preprocessorDefinitions(cfg, defines, true)
- end
- function m.runtimeLibrary(cfg)
- local runtimes = {
- StaticDebug = "MultiThreadedDebug",
- StaticRelease = "MultiThreaded",
- SharedDebug = "MultiThreadedDebugDLL",
- SharedRelease = "MultiThreadedDLL"
- }
- local runtime = config.getruntime(cfg)
- if runtime then
- m.element("RuntimeLibrary", nil, runtimes[runtime])
- end
- end
- function m.callingConvention(cfg)
- if cfg.callingconvention then
- m.element("CallingConvention", nil, cfg.callingconvention)
- end
- end
- function m.runtimeTypeInfo(cfg, condition)
- if cfg.rtti == p.OFF and ((not cfg.clr) or cfg.clr == p.OFF) then
- m.element("RuntimeTypeInfo", condition, "false")
- elseif cfg.rtti == p.ON then
- m.element("RuntimeTypeInfo", condition, "true")
- end
- end
- function m.bufferSecurityCheck(cfg)
- local tool, toolVersion = p.config.toolset(cfg)
- if cfg.flags.NoBufferSecurityCheck or (toolVersion and toolVersion:startswith("LLVM-vs")) then
- m.element("BufferSecurityCheck", nil, "false")
- end
- end
- function m.stringPooling(cfg)
- if cfg.stringpooling ~= nil then
- if cfg.stringpooling then
- m.element("StringPooling", nil, "true")
- else
- m.element("StringPooling", nil, "false")
- end
- elseif config.isOptimizedBuild(cfg) then
- m.element("StringPooling", nil, "true")
- end
- end
- function m.subSystem(cfg)
- local subsystem = iif(cfg.kind == p.CONSOLEAPP, "Console", "Windows")
- m.element("SubSystem", nil, subsystem)
- end
- function m.targetExt(cfg)
- local ext = cfg.buildtarget.extension
- if ext ~= "" then
- m.element("TargetExt", nil, "%s", ext)
- else
- p.w('<TargetExt>')
- p.w('</TargetExt>')
- end
- end
- function m.targetMachine(cfg)
- -- If a static library project contains a resource file, VS will choke with
- -- "LINK : warning LNK4068: /MACHINE not specified; defaulting to X86"
- local targetmachine = {
- x86 = "MachineX86",
- x86_64 = "MachineX64",
- }
- if cfg.kind == p.STATICLIB and config.hasFile(cfg, path.isresourcefile) then
- local value = targetmachine[cfg.architecture]
- if value ~= nil then
- m.element("TargetMachine", nil, '%s', value)
- end
- end
- end
- function m.targetName(cfg)
- m.element("TargetName", nil, "%s%s", cfg.buildtarget.prefix, cfg.buildtarget.basename)
- end
- function m.latestTargetPlatformVersion(prj)
- -- See https://developercommunity.visualstudio.com/content/problem/140294/windowstargetplatformversion-makes-it-impossible-t.html
- if _ACTION == "vs2017" then
- m.element("LatestTargetPlatformVersion", nil, "$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))")
- end
- end
- function m.windowsTargetPlatformVersion(prj, cfg)
- if _ACTION < "vs2015" then
- return
- end
- local target = cfg or prj
- local version = project.systemversion(target)
- -- if this is a config, only emit if different from project
- if cfg then
- local prjVersion = project.systemversion(prj)
- if not prjVersion or version == prjVersion then
- return
- end
- end
- -- See https://developercommunity.visualstudio.com/content/problem/140294/windowstargetplatformversion-makes-it-impossible-t.html
- if version == "latest" then
- if _ACTION == "vs2015" then
- version = nil -- SDK v10 is not supported by VS2015
- elseif _ACTION == "vs2017" then
- version = "$(LatestTargetPlatformVersion)"
- else
- version = "10.0"
- end
- end
- if version then
- m.element("WindowsTargetPlatformVersion", nil, version)
- end
- end
- function m.xpDeprecationWarning(prj, cfg)
- if cfg.toolset == "msc-v141_xp" then
- m.element("XPDeprecationWarning", nil, "false")
- end
- end
- function m.fastUpToDateCheck(prj)
- if prj.fastuptodate ~= nil then
- m.element("DisableFastUpToDateCheck", nil, iif(prj.fastuptodate, "false", "true"))
- end
- end
- function m.preferredToolArchitecture(prj)
- if _ACTION >= "vs2013" then
- if prj.preferredtoolarchitecture == p.X86_64 then
- m.element("PreferredToolArchitecture", nil, 'x64')
- elseif prj.preferredtoolarchitecture == p.X86 then
- m.element("PreferredToolArchitecture", nil, 'x86')
- end
- else
- if prj.preferredtoolarchitecture == p.X86_64 then
- m.element("UseNativeEnvironment", nil, 'true')
- end
- end
- end
- function m.treatLinkerWarningAsErrors(cfg)
- if cfg.flags.FatalLinkWarnings then
- local el = iif(cfg.kind == p.STATICLIB, "Lib", "Linker")
- m.element("Treat" .. el .. "WarningAsErrors", nil, "true")
- end
- end
- function m.treatWChar_tAsBuiltInType(cfg)
- local map = { On = "true", Off = "false" }
- local value = map[cfg.nativewchar]
- if value then
- m.element("TreatWChar_tAsBuiltInType", nil, value)
- end
- end
- function m.treatWarningAsError(cfg)
- if cfg.flags.FatalCompileWarnings and cfg.warnings ~= p.OFF then
- m.element("TreatWarningAsError", nil, "true")
- end
- end
- function m.disableSpecificWarnings(cfg, condition)
- if #cfg.disablewarnings > 0 then
- local warnings = table.concat(cfg.disablewarnings, ";")
- warnings = warnings .. ";%%(DisableSpecificWarnings)"
- m.element('DisableSpecificWarnings', condition, warnings)
- end
- end
- function m.treatSpecificWarningsAsErrors(cfg, condition)
- if #cfg.fatalwarnings > 0 then
- local fatal = table.concat(cfg.fatalwarnings, ";")
- fatal = fatal .. ";%%(TreatSpecificWarningsAsErrors)"
- m.element('TreatSpecificWarningsAsErrors', condition, fatal)
- end
- end
- function m.useDebugLibraries(cfg)
- local runtime = config.getruntime(cfg) or iif(config.isDebugBuild(cfg), "Debug", "Release")
- m.element("UseDebugLibraries", nil, tostring(runtime:endswith("Debug")))
- end
- function m.useOfMfc(cfg)
- if cfg.flags.MFC then
- m.element("UseOfMfc", nil, iif(cfg.staticruntime == "On", "Static", "Dynamic"))
- end
- end
- function m.useOfAtl(cfg)
- if cfg.atl then
- m.element("UseOfATL", nil, cfg.atl)
- end
- end
- function m.userMacros(cfg)
- p.w('<PropertyGroup Label="UserMacros" />')
- end
- function m.warningLevel(cfg)
- local map = { Off = "TurnOffAllWarnings", High = "Level4", Extra = "Level4", Everything = "EnableAllWarnings" }
- m.element("WarningLevel", nil, map[cfg.warnings] or "Level3")
- end
- function m.warningLevelFile(cfg, condition)
- local map = { Off = "TurnOffAllWarnings", High = "Level4", Extra = "Level4", Everything = "EnableAllWarnings" }
- if cfg.warnings then
- m.element("WarningLevel", condition, map[cfg.warnings] or "Level3")
- end
- end
- function m.xmlDeclaration()
- p.xmlUtf8()
- end
- -- Fx Functions
- --------------------------------------------------------------------------------------------------------------
- --------------------------------------------------------------------------------------------------------------
- function m.fxCompilePreprocessorDefinition(cfg, condition)
- if cfg.shaderdefines and #cfg.shaderdefines > 0 then
- local shaderdefines = table.concat(cfg.shaderdefines, ";")
- shaderdefines = shaderdefines .. ";%%(PreprocessorDefinitions)"
- m.element('PreprocessorDefinitions', condition, shaderdefines)
- end
- end
- function m.fxCompileAdditionalIncludeDirs(cfg, condition)
- if cfg.shaderincludedirs and #cfg.shaderincludedirs > 0 then
- local dirs = vstudio.path(cfg, cfg.shaderincludedirs)
- m.element('AdditionalIncludeDirectories', condition, "%s;%%(AdditionalIncludeDirectories)", table.concat(dirs, ";"))
- end
- end
- function m.fxCompileShaderType(cfg, condition)
- if cfg.shadertype then
- m.element("ShaderType", condition, cfg.shadertype)
- end
- end
- function m.fxCompileShaderModel(cfg, condition)
- if cfg.shadermodel then
- m.element("ShaderModel", condition, cfg.shadermodel)
- end
- end
- function m.fxCompileShaderEntry(cfg, condition)
- if cfg.shaderentry then
- m.element("EntryPointName", condition, cfg.shaderentry)
- end
- end
- function m.fxCompileShaderVariableName(cfg, condition)
- if cfg.shadervariablename then
- m.element("VariableName", condition, cfg.shadervariablename)
- end
- end
- function m.fxCompileShaderHeaderOutput(cfg, condition)
- if cfg.shaderheaderfileoutput then
- m.element("HeaderFileOutput", condition, cfg.shaderheaderfileoutput)
- end
- end
- function m.fxCompileShaderObjectOutput(cfg, condition)
- if cfg.shaderobjectfileoutput then
- m.element("ObjectFileOutput", condition, cfg.shaderobjectfileoutput)
- end
- end
- function m.fxCompileShaderAssembler(cfg, condition)
- if cfg.shaderassembler then
- m.element("AssemblerOutput", condition, cfg.shaderassembler)
- end
- end
- function m.fxCompileShaderAssemblerOutput(cfg, condition)
- if cfg.shaderassembleroutput then
- m.element("AssemblerOutputFile", condition, cfg.shaderassembleroutput)
- end
- end
- function m.fxCompileShaderAdditionalOptions(cfg, condition)
- local opts = cfg.shaderoptions
- if #opts > 0 then
- opts = table.concat(opts, " ")
- m.element("AdditionalOptions", condition, '%s %%(AdditionalOptions)', opts)
- end
- end
- ---------------------------------------------------------------------------
- --
- -- Support functions
- --
- ---------------------------------------------------------------------------
- --
- -- Format and return a Visual Studio Condition attribute.
- --
- function m.conditionFromConfigText(cfgText)
- return string.format('Condition="\'$(Configuration)|$(Platform)\'==\'%s\'"', p.esc(cfgText))
- end
- function m.condition(cfg)
- return m.conditionFromConfigText(vstudio.projectConfig(cfg))
- end
- --
- -- Output an individual project XML element, with an optional configuration
- -- condition.
- --
- -- @param depth
- -- How much to indent the element.
- -- @param name
- -- The element name.
- -- @param condition
- -- An optional configuration condition, formatted with vc2010.condition().
- -- @param value
- -- The element value, which may contain printf formatting tokens.
- -- @param ...
- -- Optional additional arguments to satisfy any tokens in the value.
- --
- function m.element(name, condition, value, ...)
- local arg = {...}
- if select('#',...) == 0 then
- value = p.esc(value)
- else
- for i = 1, #arg do
- arg[i] = p.esc(arg[i])
- end
- end
- if condition then
- --defer output
- local element = {}
- element.name = name
- element.condition = condition
- element.value = value
- element.args = arg
- if ... then
- if value == '%s' then
- element.setting = table.concat(arg)
- else
- element.setting = value .. table.concat(arg)
- end
- else
- element.setting = element.value
- end
- table.insert(m.conditionalElements, element)
- else
- local format = string.format('<%s>%s</%s>', name, value, name)
- p.w(format, table.unpack(arg))
- end
- end
|