我在我的项目中添加自定义.tt
模板生成目标,以便在CoreBuild
之前运行,并且似乎有两种方法:
<Project...>
<Target Name="TransformOnBuild" AfterTargets="BeforeBuild">
</Project>
和
<Project...>
<Target Name="TransformOnBuild" BeforeTargets="CoreBuild">
</Project>
如果我的目标应该在我的项目构建之前运行,因为项目依赖于它,那么使用后者会更好吗?我已经看到前者曾经做过像生成文本模板这样的事情,但这似乎是一种不可靠的方法,因为它可能会在CoreBuild
之后运行,这为时已晚。或者,为什么AfterTargets="BeforeBuild"
仍然可以保证在核心构建之前运行?
我也见过BeforeTargets="BeforeBuild"
甚至会更早建立。这是放置`.tt文本生成目标的更好的地方吗?
答案 0 :(得分:4)
更新2
基于documentation from Microsoft:
这是目标构建顺序
以下是您问题的答案:
如果我的目标应该在我的项目构建之前运行,因为项目依赖它,那么使用后者会更好吗?
或者有什么理由为什么AfterTargets =&#34; BeforeBuild&#34;仍然保证在核心构建之前运行?
我还看过 BeforeTargets =&#34; BeforeBuild&#34; ,它们甚至会更早建立。这是放置`.tt文本生成目标的更好的地方吗?
在CoreBuild之前运行目标?
> there appear to be 2 ways of doing it.
There are more options to achieve this. Please review below.
为此,您应该使用特定的内置目标(BeforeBuild或AfterBuild)。这是Microsoft在使用依赖于Microsoft.Common.targets的项目时safely extend the build process提供的机制
如果在CoreBuild之前只有一个目标要运行,则可以执行以下操作:
<Target Name="BeforeBuild">
<!-- add your tasks here -->
</Target>
如果在CoreBuild之前要运行多个目标,则可以定义一个属性,其中包含需要按所需执行顺序调用的所有目标:
<PropertyGroup>
<BeforeBuildDependsOn>
CustomTarget1;
CustomTarget2;
CustomTarget3
</BeforeBuildDependsOn>
</PropertyGroup>
<Target Name="BeforeBuild" DependsOnTargets="$(BeforeBuildDependsOn)"/>
<强>更新强>
基于@stijn提供的片段:
AfterTargets =&#34; BeforeBuild&#34;将插入/执行自定义目标,如下所示:(取决于BeforeBuild
<BuildDependsOn>
BeforeBuild;
|-> Custom Target
CoreBuild;
AfterBuild
</BuildDependsOn>
BeforeTargets =&#34; CoreBuild&#34; 将插入/执行此类自定义(取决于CoreBuild):
<BuildDependsOn>
BeforeBuild;
|-> Custom Target
CoreBuild;
AfterBuild
</BuildDependsOn>
所以&#34;模板生成目标&#34;将在同一个地方执行(在 BeforeBuild 和 CoreBuild 之间,但是根据不同的目标,这就是为什么要使用的适当的目标应该是 BeforeBuild 内联或依赖。
现在关于第三方问题评论,BeforeBuild / AfterBuild目标是针对最终用户的,第三方提供商应该实现他们的脚本而不影响基本工作流程。这些是第三方应该使用的一些选项,以避免破坏常规流程:
将此视为基础:
<PropertyGroup>
<BuildDependsOn>
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
<Target Name="Build" DependsOnTargets="$(BuildDependsOn)"/>
选项1:这将在BeforeBuild之前注入您的自定义第三方脚本,而不会影响默认的BuildDependsOn序列,这仍然允许最终用户不使用BeforeBuild目标。
<PropertyGroup>
<BuildDependsOn>
MyCustomThirdParty;
$(BuildDependsOn);
</BuildDependsOn>
</PropertyGroup>
<PropertyGroup>
<MyCustomThirdPartyDependsOn>
BeforeMyCustomThirdParty;
CustomStep1;
CustomStep2;
CustomStep1;
AfterMyCustomThirdParty
</MyCustomThirdPartyDependsOn>
</PropertyGroup>
<Target Name="MyCustomThirdParty" DependsOnTargets="$(MyCustomThirdPartyDependsOn)"/>
选项2:如果需要在 BeforeBuild 目标之后执行第三方脚本,可以这样做:
<PropertyGroup>
<BuildDependsOn>
BeforeBuild;
MyCustomThirdParty;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
注意:为了使其正常工作,您必须在Microsoft.CSharp.targets导入后添加PropertyGroup和目标。
通过这种方式,您可以使用多个第三方脚本来完成一般工作流程。
根据具体情况,您显然可以使用这些选项的组合。但是你应该遵循这些一般规则:
当您使用默认的visual studio生成的构建脚本(像.csproj,.vbproj等项目)时,应该考虑这些。如果您正在为其他语言或目的实现自己的脚本,可以在任何地方使用BeforeTargets和AfterTargets,但为什么不遵循基于现有脚本的良好实践?
答案 1 :(得分:3)
从Microsoft.Common.CurrentVersion.targets开始,Build目标基本上是:
<BuildDependsOn>
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
<Target Name="Build" DependsOnTargets="$(BuildDependsOn)"/>
<PropertyGroup>
<CoreBuildDependsOn>
PrepareForBuild;
PreBuildEvent;
...
Compile;
...
PostBuildEvent
</CoreBuildDependsOn>
</PropertyGroup>
<Target Name="CoreBuild" DependsOnTargets="$(CoreBuildDependsOn)">
因此使用BeforeTargets="CoreBuild"
确实会在CoreBuild之前运行,但之后所有它的依赖目标都会运行,所以之后所有实际的构建步骤。这通常不是您想要的,而是如果您想在编译之前运行某些内容,请使用BeforeTargets="PrepareForBuild"
或AfterTargets="BeforeBuild"
或甚至BeforeTargets="BeforeBuild"
。
答案 2 :(得分:3)
在@ stjin的答案的基础上,一个好的解决方案似乎正在使用
BeforeTargets="CoreCompile" DependsOnTargets="PrepareForBuild"
这就是.net sdk(.net核心/标准项目的新风格csproj)is doing for automatic AssemblyInfo.cs generation。
它使用以下注释来解释原因:
请注意,这必须在每次调用CoreCompile之前运行 确保所有编译器运行都看到生成的程序集信息。那里 至少有一个涉及调用CoreCompile的Xaml的场景 没有其他潜在的钩子,如Compile或CoreBuild等,所以 我们直接挂钩到CoreCompile。此外,我们必须在之后运行 PrepareForBuild以确保中间目录已经存在 创建
请注意&#34;中间目录&#34; (在这种情况下为obj/[TargetFramework]
)是输出.cs
文件放在这种情况下的位置,也可能是您想要做的。