1-- 2-- vs2005_dotnetbase.lua 3-- Generate a Visual Studio 2005+ .NET project. 4-- Copyright (c) Jason Perkins and the Premake project 5-- 6 7 local p = premake 8 p.vstudio.dotnetbase = {} 9 10 local vstudio = p.vstudio 11 local dotnetbase = p.vstudio.dotnetbase 12 local project = p.project 13 local config = p.config 14 local fileconfig = p.fileconfig 15 local dotnet = p.tools.dotnet 16 17 18 dotnetbase.elements = {} 19 dotnetbase.langObj = {} 20 dotnetbase.netcore = {} 21 22-- 23-- Generate a Visual Studio 200x dotnet project, with support for the new platforms API. 24-- 25 26 function dotnetbase.prepare(langObj) 27 dotnetbase.elements.project = langObj.elements.project 28 dotnetbase.elements.projectProperties = langObj.elements.projectProperties 29 dotnetbase.elements.configuration = langObj.elements.configuration 30 31 dotnetbase.langObj = langObj 32 end 33 34 35 function dotnetbase.generate(prj) 36 p.utf8() 37 38 p.callArray(dotnetbase.elements.project, prj) 39 40 _p(1,'<ItemGroup>') 41 dotnetbase.files(prj) 42 _p(1,'</ItemGroup>') 43 44 dotnetbase.projectReferences(prj) 45 dotnetbase.packageReferences(prj) 46 dotnetbase.langObj.targets(prj) 47 dotnetbase.buildEvents(prj) 48 49 p.out('</Project>') 50 end 51 52 53-- 54-- Write the opening <Project> element. 55-- 56 57 function dotnetbase.projectElement(prj) 58 if dotnetbase.isNewFormatProject(prj) then 59 if prj.flags.WPF then 60 _p('<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">') 61 else 62 _p('<Project Sdk="Microsoft.NET.Sdk">') 63 end 64 else 65 local ver = '' 66 local action = p.action.current() 67 if action.vstudio.toolsVersion then 68 ver = string.format(' ToolsVersion="%s"', action.vstudio.toolsVersion) 69 end 70 _p('<Project%s DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">', ver) 71 end 72 end 73 74 75-- 76-- Write the opening PropertyGroup, which contains the project-level settings. 77-- 78 79 80 function dotnetbase.projectProperties(prj) 81 _p(1,'<PropertyGroup>') 82 local cfg = project.getfirstconfig(prj) 83 p.callArray(dotnetbase.elements.projectProperties, cfg) 84 _p(1,'</PropertyGroup>') 85 end 86 87 88-- 89-- Write out the settings for the project configurations. 90-- 91 92 93 function dotnetbase.configurations(prj) 94 for cfg in project.eachconfig(prj) do 95 dotnetbase.configuration(cfg) 96 end 97 end 98 99 function dotnetbase.configuration(cfg) 100 p.callArray(dotnetbase.elements.configuration, cfg) 101 _p(1,'</PropertyGroup>') 102 end 103 104 105 function dotnetbase.dofile(node, cfg, condition) 106 local filecfg = fileconfig.getconfig(node, cfg) 107 if filecfg then 108 local fname = path.translate(node.relpath) 109 110 -- Files that live outside of the project tree need to be "linked" 111 -- and provided with a project relative pseudo-path. Check for any 112 -- leading "../" sequences and, if found, remove them and mark this 113 -- path as external. 114 local link, count = node.relpath:gsub("%.%.%/", "") 115 local external = (count > 0) 116 117 -- Try to provide a little bit of flexibility by allowing virtual 118 -- paths for external files. Would be great to support them for all 119 -- files but Visual Studio chokes if file is already in project area. 120 if external and node.vpath ~= node.relpath then 121 link = node.vpath 122 end 123 124 -- Deduce what, if any, special attributes are required for this file. 125 -- For example, forms may have related source, designer, and resource 126 -- files which need to be associated. 127 128 local info = dotnet.fileinfo(filecfg) 129 130 -- Process any sub-elements required by this file; choose the write 131 -- element form to use based on the results. 132 133 local contents = p.capture(function () 134 -- Try to write file-level elements in the same order as Visual Studio 135 local elements = { 136 "AutoGen", 137 "CopyToOutputDirectory", 138 "DesignTime", 139 "DependentUpon", 140 "DesignTimeSharedInput", 141 "Generator", 142 "LastGenOutput", 143 "SubType", 144 } 145 146 for _, el in ipairs(elements) do 147 local value = info[el] 148 if value then 149 _p(3,"<%s>%s</%s>", el, value, el) 150 end 151 end 152 if info.action == "EmbeddedResource" and cfg.customtoolnamespace then 153 _p(3,"<CustomToolNamespace>%s</CustomToolNamespace>", cfg.customtoolnamespace) 154 end 155 end) 156 157 if #contents > 0 or external then 158 _p(2,'<%s%s Include="%s">', info.action, condition, fname) 159 if external and info.action ~= "EmbeddedResource" then 160 _p(3,'<Link>%s</Link>', path.translate(link)) 161 end 162 if #contents > 0 then 163 _p("%s", contents) 164 end 165 _p(2,'</%s>', info.action) 166 else 167 _p(2,'<%s%s Include="%s" />', info.action, condition, fname) 168 end 169 end 170 end 171 172 173-- 174-- Write out the source files item group. 175-- 176 177 function dotnetbase.files(prj) 178 local firstcfg = project.getfirstconfig(prj) 179 180 local processfcfg = function(node) 181 -- test if all fileinfo's are going to be the same for each config. 182 local allsame = true 183 local first = nil 184 for cfg in project.eachconfig(prj) do 185 local filecfg = fileconfig.getconfig(node, cfg) 186 local info = dotnet.fileinfo(filecfg) 187 188 if first == nil then 189 first = info 190 elseif not table.equals(first, info) then 191 allsame = false 192 end 193 end 194 195 -- output to proj file. 196 if allsame then 197 dotnetbase.dofile(node, firstcfg, '') 198 else 199 for cfg in project.eachconfig(prj) do 200 dotnetbase.dofile(node, cfg, ' ' .. dotnetbase.condition(cfg)) 201 end 202 end 203 end 204 205 if project.isfsharp(prj) then 206 sorter = function(a,b) 207 verbosef('Sorting F# proj file (%s, %s), index %s < %s', a.name, b.name, a.order, b.order) 208 return a.order < b.order 209 end 210 211 table.sort(prj._.files, sorter) 212 table.foreachi(prj._.files, processfcfg) 213 else 214 local tr = project.getsourcetree(prj) 215 p.tree.traverse(tr, { 216 onleaf = processfcfg 217 }, false) 218 end 219 end 220 221 222-- 223-- Write out pre- and post-build events, if provided. 224-- 225 226 function dotnetbase.buildEvents(prj) 227 local function output(name, steps) 228 if #steps > 0 then 229 steps = os.translateCommandsAndPaths(steps, prj.basedir, prj.location) 230 steps = table.implode(steps, "", "", "\r\n") 231 _x(2,'<%sBuildEvent>%s</%sBuildEvent>', name, steps, name) 232 end 233 end 234 235 local cfg = project.getfirstconfig(prj) 236 if #cfg.prebuildcommands > 0 or #cfg.postbuildcommands > 0 then 237 _p(1,'<PropertyGroup>') 238 output("Pre", cfg.prebuildcommands) 239 output("Post", cfg.postbuildcommands) 240 _p(1,'</PropertyGroup>') 241 end 242 end 243 244 245-- 246-- Write the compiler flags for a particular configuration. 247-- 248 249 function dotnetbase.compilerProps(cfg) 250 _x(2,'<DefineConstants>%s</DefineConstants>', table.concat(cfg.defines, ";")) 251 252 _p(2,'<ErrorReport>prompt</ErrorReport>') 253 _p(2,'<WarningLevel>4</WarningLevel>') 254 255 if not dotnetbase.isNewFormatProject(cfg) then 256 dotnetbase.allowUnsafeBlocks(cfg) 257 end 258 259 if cfg.flags.FatalCompileWarnings then 260 _p(2,'<TreatWarningsAsErrors>true</TreatWarningsAsErrors>') 261 end 262 263 dotnetbase.debugCommandParameters(cfg) 264 end 265 266-- 267-- Write out the debug start parameters for MonoDevelop/Xamarin Studio. 268-- 269 270 function dotnetbase.debugCommandParameters(cfg) 271 if #cfg.debugargs > 0 then 272 _x(2,'<Commandlineparameters>%s</Commandlineparameters>', table.concat(cfg.debugargs, " ")) 273 end 274 end 275 276-- 277-- Write out the debugging and optimization flags for a configuration. 278-- 279 280 function dotnetbase.debugProps(cfg) 281 if cfg.symbols == p.ON then 282 _p(2,'<DebugSymbols>true</DebugSymbols>') 283 _p(2,'<DebugType>full</DebugType>') 284 else 285 _p(2,'<DebugType>pdbonly</DebugType>') 286 end 287 _p(2,'<Optimize>%s</Optimize>', iif(config.isOptimizedBuild(cfg), "true", "false")) 288 end 289 290 291-- 292-- Write out the target and intermediates settings for a configuration. 293-- 294 295 function dotnetbase.outputProps(cfg) 296 local outdir = vstudio.path(cfg, cfg.buildtarget.directory) 297 _x(2,'<OutputPath>%s\\</OutputPath>', outdir) 298 299 -- Want to set BaseIntermediateOutputPath because otherwise VS will create obj/ 300 -- anyway. But VS2008 throws up ominous warning if present. 301 local objdir = vstudio.path(cfg, cfg.objdir) 302 if _ACTION > "vs2008" and not dotnetbase.isNewFormatProject(cfg) then 303 _x(2,'<BaseIntermediateOutputPath>%s\\</BaseIntermediateOutputPath>', objdir) 304 _p(2,'<IntermediateOutputPath>$(BaseIntermediateOutputPath)</IntermediateOutputPath>') 305 else 306 _x(2,'<IntermediateOutputPath>%s\\</IntermediateOutputPath>', objdir) 307 end 308 end 309 310 311-- 312-- Write out the references item group. 313-- 314 315 dotnetbase.elements.references = function(prj) 316 return { 317 dotnetbase.assemblyReferences, 318 dotnetbase.nuGetReferences, 319 } 320 end 321 322 function dotnetbase.references(prj) 323 _p(1,'<ItemGroup>') 324 p.callArray(dotnetbase.elements.references, prj) 325 _p(1,'</ItemGroup>') 326 end 327 328 329-- 330-- Write the list of assembly (system, or non-sibling) references. 331-- 332 333 function dotnetbase.assemblyReferences(prj) 334 -- C# doesn't support per-configuration links (does it?) so just use 335 -- the settings from the first available config instead 336 local cfg = project.getfirstconfig(prj) 337 338 config.getlinks(cfg, "system", function(original, decorated) 339 local name = path.getname(decorated) 340 if path.getextension(name) == ".dll" then 341 name = name.sub(name, 1, -5) 342 end 343 344 if decorated:find("/", nil, true) then 345 _x(2,'<Reference Include="%s">', name) 346 local decPath, decVars = decorated:match("(.-),") 347 if not decPath then 348 decPath = decorated 349 end 350 351 _x(3,'<HintPath>%s</HintPath>', path.appendextension(path.translate(decPath), ".dll")) 352 353 if not config.isCopyLocal(prj, original, true) then 354 _p(3,"<Private>False</Private>") 355 end 356 357 _p(2,'</Reference>') 358 else 359 _x(2,'<Reference Include="%s" />', name) 360 end 361 end) 362 end 363 364 365-- 366-- This is a bit janky. To compare versions, we extract all numbers from the 367-- given string and right-pad the result with zeros. Then we can just do a 368-- lexicographical compare on the resulting strings. 369-- 370-- This is so that we can compare version strings such as "4.6" and "net451" 371-- with each other. 372-- 373 374 function dotnetbase.makeVersionComparable(version) 375 local numbers = "" 376 377 for number in version:gmatch("%d") do 378 numbers = numbers .. number 379 end 380 381 return string.format("%-10d", numbers):gsub(" ", "0") 382 end 383 384 385-- 386-- https://github.com/NuGet/NuGet.Client/blob/dev/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGetFrameworkParseTests.cs 387-- 388 389 function dotnetbase.frameworkVersionForFolder(folder) 390 -- If this exporter ever supports frameworks such as "netstandard1.3", 391 -- "sl4", "sl5", "uap10", "wp8" or "wp71", this code will need changing 392 -- to match the right folders, depending on the current framework. 393 394 -- Right now this only matches folders for the .NET Framework. 395 396 if folder:match("^net%d+$") or folder:match("^[0-9%.]+$") then 397 return dotnetbase.makeVersionComparable(folder) 398 elseif folder == "net" then 399 return dotnetbase.makeVersionComparable("0") 400 end 401 end 402 403 404-- 405-- Write the list of NuGet references. 406-- 407 408 function dotnetbase.nuGetReferences(prj) 409 if _ACTION >= "vs2010" and not vstudio.nuget2010.supportsPackageReferences(prj) then 410 for _, package in ipairs(prj.nuget) do 411 local id = vstudio.nuget2010.packageId(package) 412 local packageAPIInfo = vstudio.nuget2010.packageAPIInfo(prj, package) 413 414 local cfg = p.project.getfirstconfig(prj) 415 local action = p.action.current() 416 local targetFramework = cfg.dotnetframework or action.vstudio.targetFramework 417 418 local targetVersion = dotnetbase.makeVersionComparable(targetFramework) 419 420 -- Figure out what folder contains the files for the nearest 421 -- supported .NET Framework version. 422 423 local files = {} 424 425 local bestVersion, bestFolder 426 427 for _, file in ipairs(packageAPIInfo.packageEntries) do 428 local folder = file:match("^lib[\\/](.+)[\\/]") 429 430 if folder and path.hasextension(file, ".dll") then 431 local version = dotnetbase.frameworkVersionForFolder(folder) 432 433 if version then 434 files[folder] = files[folder] or {} 435 table.insert(files[folder], file) 436 437 if version <= targetVersion and (not bestVersion or version > bestVersion) then 438 bestVersion = version 439 bestFolder = folder 440 end 441 end 442 end 443 end 444 445 if not bestVersion then 446 p.error("NuGet package '%s' is not compatible with project '%s' .NET Framework version '%s'", id, prj.name, targetFramework) 447 end 448 449 -- Now, add references for all DLLs in that folder. 450 451 for _, file in ipairs(files[bestFolder]) do 452 -- There's some stuff missing from this include that we 453 -- can't get from the API and would need to download and 454 -- extract the package to figure out. It looks like we can 455 -- just omit it though. 456 -- 457 -- So, for example, instead of: 458 -- 459 -- <Reference Include="nunit.framework, Version=3.6.1.0, 460 -- <Culture=neutral, PublicKeyToken=2638cd05610744eb, 461 -- <processorArchitecture=MSIL"> 462 -- 463 -- We're just outputting: 464 -- 465 -- <Reference Include="nunit.framework"> 466 467 _x(2, '<Reference Include="%s">', path.getbasename(file)) 468 _x(3, '<HintPath>%s</HintPath>', vstudio.path(prj, p.filename(prj.workspace, string.format("packages\\%s.%s\\%s", id, packageAPIInfo.verbatimVersion or packageAPIInfo.version, file)))) 469 470 if config.isCopyLocal(prj, package, true) then 471 _p(3, '<Private>True</Private>') 472 else 473 _p(3, '<Private>False</Private>') 474 end 475 476 _p(2, '</Reference>') 477 end 478 end 479 end 480 end 481 482 483-- 484-- Write the list of project dependencies. 485-- 486 function dotnetbase.projectReferences(prj) 487 if not dotnetbase.isNewFormatProject(prj) then 488 _p(1,'<ItemGroup>') 489 end 490 491 local deps = project.getdependencies(prj, 'linkOnly') 492 if #deps > 0 then 493 if dotnetbase.isNewFormatProject(prj) then 494 _p(1,'<ItemGroup>') 495 end 496 497 for _, dep in ipairs(deps) do 498 local relpath = vstudio.path(prj, vstudio.projectfile(dep)) 499 _x(2,'<ProjectReference Include="%s">', relpath) 500 _p(3,'<Project>{%s}</Project>', dep.uuid) 501 _x(3,'<Name>%s</Name>', dep.name) 502 503 if not config.isCopyLocal(prj, dep.name, true) then 504 _p(3,"<Private>False</Private>") 505 end 506 507 _p(2,'</ProjectReference>') 508 end 509 510 if dotnetbase.isNewFormatProject(prj) then 511 _p(1,'</ItemGroup>') 512 end 513 end 514 515 if not dotnetbase.isNewFormatProject(prj) then 516 _p(1,'</ItemGroup>') 517 end 518 end 519 520-- 521-- Write the list of package dependencies. 522-- 523 function dotnetbase.packageReferences(prj) 524 if vstudio.nuget2010.supportsPackageReferences(prj) then 525 local hasNuget = prj.nuget and #prj.nuget>0 526 for cfg in project.eachconfig(prj) do 527 if cfg.nuget and #cfg.nuget>0 then 528 hasNuget = true 529 end 530 end 531 if hasNuget then 532 _p(1,'<ItemGroup>') 533 if prj.nuget and #prj.nuget>0 then 534 for _, package in ipairs(prj.nuget) do 535 _p(2,'<PackageReference Include="%s" Version="%s"/>', vstudio.nuget2010.packageId(package), vstudio.nuget2010.packageVersion(package)) 536 end 537 end 538 for cfg in project.eachconfig(prj) do 539 if cfg.nuget and #cfg.nuget>0 then 540 for _, package in ipairs(cfg.nuget) do 541 if prj.nuget[package]==nil then 542 _p(2,'<PackageReference Include="%s" Version="%s" %s/>', vstudio.nuget2010.packageId(package), vstudio.nuget2010.packageVersion(package), dotnetbase.condition(cfg)) 543 end 544 end 545 end 546 end 547 _p(1,'</ItemGroup>') 548 end 549 end 550 end 551 552-- 553-- Return the Visual Studio architecture identification string. The logic 554-- to select this is getting more complicated in VS2010, but I haven't 555-- tackled all the permutations yet. 556-- 557 558 function dotnetbase.arch(cfg) 559 local arch = vstudio.archFromConfig(cfg) 560 if arch == "Any CPU" then 561 arch = "AnyCPU" 562 end 563 return arch 564 end 565 566 567-- 568-- Write the PropertyGroup element for a specific configuration block. 569-- 570 571 function dotnetbase.propertyGroup(cfg) 572 p.push('<PropertyGroup %s>', dotnetbase.condition(cfg)) 573 574 local arch = dotnetbase.arch(cfg) 575 if arch ~= "AnyCPU" or _ACTION > "vs2008" then 576 p.x('<PlatformTarget>%s</PlatformTarget>', arch) 577 end 578 end 579 580 581-- 582-- Generators for individual project elements. 583-- 584 585 function dotnetbase.applicationIcon(prj) 586 if prj.icon then 587 local icon = vstudio.path(prj, prj.icon) 588 _p(1,'<PropertyGroup>') 589 _x(2,'<ApplicationIcon>%s</ApplicationIcon>', icon) 590 _p(1,'</PropertyGroup>') 591 end 592 end 593 594--------------------------------------------------------------------------- 595-- 596-- Support functions 597-- 598--------------------------------------------------------------------------- 599 600-- 601-- Format and return a Visual Studio Condition attribute. 602-- 603 604 function dotnetbase.condition(cfg) 605 local platform = vstudio.projectPlatform(cfg) 606 local arch = dotnetbase.arch(cfg) 607 return string.format('Condition=" \'$(Configuration)|$(Platform)\' == \'%s|%s\' "', platform, arch) 608 end 609 610 611-- 612-- When given a .NET Framework version, returns it formatted for NuGet. 613-- 614 615 function dotnetbase.formatNuGetFrameworkVersion(framework) 616 return "net" .. framework:gsub("%.", "") 617 end 618 619--------------------------------------------------------------------------- 620-- 621-- Handlers for individual project elements 622-- 623--------------------------------------------------------------------------- 624 625 function dotnetbase.appDesignerFolder(cfg) 626 _p(2,'<AppDesignerFolder>Properties</AppDesignerFolder>') 627 end 628 629 630 function dotnetbase.assemblyName(cfg) 631 if not dotnetbase.isNewFormatProject(cfg) --[[or cfg.assemblyname]] then 632 _p(2,'<AssemblyName>%s</AssemblyName>', cfg.buildtarget.basename) 633 end 634 end 635 636 637 function dotnetbase.commonProperties(prj) 638 if _ACTION > "vs2010" then 639 _p(1,'<Import Project="$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props" Condition="Exists(\'$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props\')" />') 640 end 641 end 642 643 644 function dotnetbase.configurationCondition(cfg) 645 _x(2,'<Configuration Condition=" \'$(Configuration)\' == \'\' ">%s</Configuration>', cfg.buildcfg) 646 end 647 648 649 function dotnetbase.fileAlignment(cfg) 650 if _ACTION >= "vs2010" and not dotnetbase.isNewFormatProject(cfg) then 651 _p(2,'<FileAlignment>512</FileAlignment>') 652 end 653 end 654 655 656 function dotnetbase.bindingRedirects(cfg) 657 if _ACTION >= "vs2015" and not dotnetbase.isNewFormatProject(cfg) then 658 _p(2, '<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>') 659 end 660 end 661 662 663 function dotnetbase.outputType(cfg) 664 _p(2,'<OutputType>%s</OutputType>', dotnet.getkind(cfg)) 665 end 666 667 668 function dotnetbase.platformCondition(cfg) 669 _p(2,'<Platform Condition=" \'$(Platform)\' == \'\' ">%s</Platform>', dotnetbase.arch(cfg.project)) 670 end 671 672 673 function dotnetbase.productVersion(cfg) 674 local action = p.action.current() 675 if action.vstudio.productVersion then 676 _p(2,'<ProductVersion>%s</ProductVersion>', action.vstudio.productVersion) 677 end 678 end 679 680 function dotnetbase.projectGuid(cfg) 681 _p(2,'<ProjectGuid>{%s}</ProjectGuid>', cfg.uuid) 682 end 683 684 685 function dotnetbase.projectTypeGuids(cfg) 686 if cfg.flags.WPF then 687 _p(2,'<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>') 688 end 689 end 690 691 692 function dotnetbase.rootNamespace(cfg) 693 if not dotnetbase.isNewFormatProject(cfg) or cfg.namespace then 694 _p(2,'<RootNamespace>%s</RootNamespace>', cfg.namespace or cfg.buildtarget.basename) 695 end 696 end 697 698 699 function dotnetbase.schemaVersion(cfg) 700 local action = p.action.current() 701 if action.vstudio.csprojSchemaVersion then 702 _p(2,'<SchemaVersion>%s</SchemaVersion>', action.vstudio.csprojSchemaVersion) 703 end 704 end 705 706 707 function dotnetbase.NoWarn(cfg) 708 if #cfg.disablewarnings > 0 then 709 local warnings = table.concat(cfg.disablewarnings, ";") 710 _p(2,'<NoWarn>%s</NoWarn>', warnings) 711 end 712 end 713 714 function dotnetbase.targetFrameworkVersion(cfg) 715 local action = p.action.current() 716 local framework = cfg.dotnetframework or action.vstudio.targetFramework 717 if framework and not dotnetbase.isNewFormatProject(cfg) then 718 _p(2,'<TargetFrameworkVersion>v%s</TargetFrameworkVersion>', framework) 719 end 720 end 721 722 function dotnetbase.csversion(cfg) 723 if cfg.csversion then 724 _p(2,'<LangVersion>%s</LangVersion>', cfg.csversion) 725 end 726 end 727 728 function dotnetbase.targetFrameworkProfile(cfg) 729 if _ACTION == "vs2010" then 730 _p(2,'<TargetFrameworkProfile>') 731 _p(2,'</TargetFrameworkProfile>') 732 end 733 end 734 735 736 function dotnetbase.xmlDeclaration() 737 if _ACTION > "vs2008" then 738 p.xmlUtf8() 739 end 740 end 741 742 function dotnetbase.isNewFormatProject(cfg) 743 local framework = cfg.dotnetframework 744 if not framework then 745 return false 746 end 747 748 if framework:find('^net') ~= nil then 749 return true 750 end 751 752 return false 753 end 754 755 function dotnetbase.netcore.targetFramework(cfg) 756 local action = p.action.current() 757 local framework = cfg.dotnetframework or action.vstudio.targetFramework 758 if framework and dotnetbase.isNewFormatProject(cfg) then 759 _p(2,'<TargetFramework>%s</TargetFramework>', framework) 760 end 761 end 762 763 function dotnetbase.netcore.enableDefaultCompileItems(cfg) 764 _p(2,'<EnableDefaultCompileItems>%s</EnableDefaultCompileItems>', iif(cfg.enableDefaultCompileItems, "true", "false")) 765 end 766 767 function dotnetbase.netcore.useWpf(cfg) 768 if cfg.flags.WPF then 769 _p(2,'<UseWpf>true</UseWpf>') 770 end 771 end 772 773 function dotnetbase.allowUnsafeBlocks(cfg) 774 if cfg.clr == "Unsafe" then 775 _p(2,'<AllowUnsafeBlocks>true</AllowUnsafeBlocks>') 776 end 777 end