如何在TargetFrameworks标签中每个框架运行一次的目标之前,使MSBuild目标仅运行一次而不是一次? [英] How to make an MSBuild Target that only runs once instead of once, before Targets that run once per framework in the TargetFrameworks tag?

查看:170
本文介绍了如何在TargetFrameworks标签中每个框架运行一次的目标之前,使MSBuild目标仅运行一次而不是一次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个我部分拥有的代码生成器工具,现在csproj文件可以列出其中的多个Target Framework并构建所有这些内容,我试图找出如何使MSBuild Target进行代码生成的方法每次列出的构建只运行一次,无论列出了多少个目标框架,并且每个目标框架的编译都将等到代码生成完成为止。



I目前,它取决于TargetFramework的特定值。例如, Condition ='netstandard2.0'=='$(TargetFramework)'



此避免同时为每个目标框架启动代码生成工具,然后避免在进程尝试创建/更新相同文件时出现访问被拒绝的错误。



但是,其他Target Framework可以尝试在不等待代码生成完成的情况下进行编译,而在没有该代码存在的情况下失败。



我想生成代码每次生成一个项目仅发生一次,并且每个Target Framework的编译仅在完成后才开始。



每次运行构建时都需要运行,



注意:目前,我忽略了 #if FrameworkSpecificDefine 用于为代码生成器提供不同的输入代码,从而使不同的Target Framework导致不同的输出从代码生成器放入。现在,我正在考虑代码生成器的输出在所有目标框架中都是相同且有效的。



更新:在MSBuild拆分为TargetFramework特定版本之前发生的Target,然后可以在之前将其挂钩,我在VS中的详细版本输出中看到了这一点:

  1>目标_SetBuildInnerTarget:
1>目标_ComputeTargetFrameworkItems:
1>目标DispatchToInnerBuilds:
1>使用程序集 Microsoft.Build.Tasks.Core,版本= 15.1.0.0,文化=中性,PublicKeyToken = b03f5f7f11d50a3a中的 MSBuild任务。
1>任务 MSBuild
1>项目 ProjectA.csproj的其他属性:
1> TargetFramework = netstandard2.0
1>项目 ProjectA.csproj的其他属性:
1> TargetFramework = net47

然后我将目标设置为 BeforeTargets = DispatchToInnerBuilds ,它会在专门设置TargetFramework的单个版本之前运行,并且似乎完全满足了我的需求。



(添加到 BuildDependsOn 属性似乎不再起作用:添加在Visual Studio 2017 RC中构建.NET Core项目后运行的msbuild任务;我怀疑稍后会评估Microsoft.Common.targets

解决方案

以新的csproj格式,以及在项目文件中所做的任何附加添加都将被Microsoft.Common.targets覆盖。)

解决方案

单个目标框架上,我只使用 BeforeTargets = PreBuildEvent

 < Project Sdk = M icrosoft.NET.Sdk> 
< PropertyGroup>
< TargetFramework> netstandard2.0< / TargetFramework>
< / PropertyGroup>
< Target Name = GenerateVersionInfo BeforeTargets = PreBuildEvent>
< Exec Command =您的自定义命令 />
< / Target>
< / Project> 多目标框架上的

我使用 BeforeTargets = DispatchToInnerBuilds

 < Project Sdk = Microsoft.NET .SDK 
< PropertyGroup>
< TargetFrameworks> netstandard2.0; net461< / TargetFrameworks>
< / PropertyGroup>
< Target Name = GenerateVersionInfo BeforeTargets = DispatchToInnerBuilds>
< Exec Command =您的自定义命令 />
< / Target>
< / Project>

因此,我的自定义命令在每次构建之前仅执行一次。如果您使用 InitialTargets ,则该命令的执行次数将超过一次!例如,如果您保存您的项目!


I have a code generator tool that I partially own, and now that csproj files can list multiple Target Frameworks in them and building builds all of them, I am trying to figure out how to make an MSBuild Target to do the code generation only once per running the build, no matter how many Target Frameworks are listed, and have the compiling for each of the Target Frameworks wait until the code generation has completed.

I currently have it conditional on a specific value of TargetFramework. For example, Condition="'netstandard2.0' == '$(TargetFramework)'".

This avoids the code generation tool being kicked off for each Target Framework at the same time and then getting access denied errors as the processes try to create/update the same files.

However, the other Target Frameworks go right to trying to compile without waiting for the code generation to complete, and fail without that code existing.

I would like to have my code generation happen only once each time a project is built and have the compiling for each Target Framework only begin once that has finished.

It needs to run each time a build is run, in case the inputs have changed and it generates different code.

Note: For the moment I am ignoring a case where #if FrameworkSpecificDefine is used to have different input code to the code generator, such that different Target Frameworks causes different output from the code generator. For now, I am considering the output of the code generator to be the same and valid across all Target Frameworks.

Update: After looking for a Target that happens before MSBuild splits into TargetFramework specific builds, that I could then hook to build before, I see this in Detailed Build Output in 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

I then set my target as BeforeTargets="DispatchToInnerBuilds" and it runs before the individual builds that set TargetFramework specifically and seems to meet my needs exactly.

(Adding to the BuildDependsOn property doesn't seem to work any longer: Add a msbuild task that runs after building a .NET Core project in Visual Studio 2017 RC; I suspect that Microsoft.Common.targets gets evaluated later in the new csproj format, and any appending to properties that you do in the project file are overwritten by Microsoft.Common.targets.)

解决方案

On single target framework I only use 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>

on multi target frameworks I use 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>

So my custom command is only exeuted once before every build. If you use InitialTargets, the command is executed more often than only once! For example if you save your project!

这篇关于如何在TargetFrameworks标签中每个框架运行一次的目标之前,使MSBuild目标仅运行一次而不是一次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆