我有一个代码生成器工具,我部分拥有,现在csproj文件可以在其中列出多个目标框架并构建所有这些,我试图弄清楚如何使MSBuild目标进行代码生成每次运行构建时,无论列出多少个目标框架,并且每个目标框架的编译都等到代码生成完成。
我目前以TargetFramework的特定值为条件。例如,Condition="'netstandard2.0' == '$(TargetFramework)'"
。
这避免了代码生成工具同时针对每个Target Framework启动,然后在进程尝试创建/更新相同文件时获取访问被拒绝错误。
然而,其他目标框架正确地尝试编译而不等待代码生成完成,并且在没有代码存在的情况下失败。
我希望每次构建项目时只生成一次代码生成,并且每个Target Framework的编译只在完成一次后才开始。
每次运行构建时都需要运行,以防输入发生变化并生成不同的代码。
注意:目前我忽略了#if FrameworkSpecificDefine
用于为代码生成器提供不同输入代码的情况,这样不同的目标框架会导致代码生成器的输出不同。目前,我正在考虑代码生成器的输出在所有目标框架中是相同且有效的。
更新:在MSBuild拆分为TargetFramework特定版本之前找到一个Target后,我可以在之前挂钩构建,我在VS中的详细构建输出中看到了这一点:
1>Target _SetBuildInnerTarget:
1>Target _ComputeTargetFrameworkItems:
1>Target DispatchToInnerBuilds:
1> Using "MSBuild" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
1> Task "MSBuild"
1> Additional Properties for project "ProjectA.csproj":
1> TargetFramework=netstandard2.0
1> Additional Properties for project "ProjectA.csproj":
1> TargetFramework=net47
然后我将目标设置为BeforeTargets="DispatchToInnerBuilds"
,然后在专门设置TargetFramework的个人构建之前运行,并且似乎完全符合我的需求。
(添加到BuildDependsOn
属性似乎不再起作用:Add a msbuild task that runs after building a .NET Core project in Visual Studio 2017 RC;我怀疑稍后会以新的csproj格式评估Microsoft.Common.targets,以及任何附加到属性的内容您在项目文件中执行的操作将被Microsoft.Common.targets覆盖。)
答案 0 :(得分:1)
在单个目标框架上,我仅使用BeforeTargets="PreBuildEvent"
:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<Target Name="GenerateVersionInfo" BeforeTargets="PreBuildEvent">
<Exec Command="your custom command" />
</Target>
</Project>
在多目标框架上,我使用BeforeTargets="DispatchToInnerBuilds"
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
</PropertyGroup>
<Target Name="GenerateVersionInfo" BeforeTargets="DispatchToInnerBuilds">
<Exec Command="your custom command" />
</Target>
</Project>
因此,我的自定义命令在每次构建之前仅执行一次。如果您使用InitialTargets
,则该命令的执行次数将不止一次!例如,如果您保存您的项目!
答案 1 :(得分:0)
虽然有些目标仅在内部版本中运行,例如当您使用BeforeTargets="BeforeBuild"
时,外部构建还定义了IsCrossTargetingBuild
变量,以指示当前正在运行的构建是外部构建,该构建将调度到内部构建,并且是调整目标的首选方式。
因此,您可以像Condition="'$(IsCrossTargetingBuild)' == 'true'"
一样调整目标,以确保目标仅针对外部版本运行。
答案 2 :(得分:0)
另一种方法是在要更改nuget文件时使用GenerateNuspec
。
打包后,您将发现Foo输出一次。