首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在CoreBuild之前运行目标?

在CoreBuild之前运行目标?
EN

Stack Overflow用户
提问于 2017-05-18 09:32:00
回答 3查看 4.4K关注 0票数 5

我正在向我的项目中添加一个自定义.tt模板生成目标,以便在CoreBuild之前运行,其中有两种方法:

代码语言:javascript
运行
复制
<Project...>
    <Target Name="TransformOnBuild" AfterTargets="BeforeBuild">
</Project>

代码语言:javascript
运行
复制
<Project...>
    <Target Name="TransformOnBuild" BeforeTargets="CoreBuild">
</Project>

如果我的目标应该在我的项目构建之前运行,因为项目依赖于它,那么对我来说使用后者更好吗?我见过前者曾经做过像生成文本模板这样的事情,但是这似乎是一种不可靠的方法,因为它可能会在CoreBuild之后运行,这太迟了。或者有什么原因可以解释为什么在核心构建之前仍然保证运行AfterTargets="BeforeBuild"呢?

我还看到了BeforeTargets="BeforeBuild",它将在更早的时候构建。这是放置`.tt文本生成目标的更好地方吗?

EN

回答 3

Stack Overflow用户

发布于 2017-05-18 11:13:36

在@stjin回答的基础上,一个好的解决方案似乎正在使用

代码语言:javascript
运行
复制
BeforeTargets="CoreCompile" DependsOnTargets="PrepareForBuild"

这就是.net sdk (用于.net核心/标准项目的新风格的csproj ) 是用于自动生成AssemblyInfo.cs的

它使用以下注释来解释原因:

注意,这必须在每次调用CoreCompile之前运行,以确保所有编译器运行时都能看到生成的程序集信息。至少有一种涉及Xaml的场景,其中调用CoreCompile时没有其他潜在的钩子,如编译或CoreBuild等,因此我们直接连接到CoreCompile。此外,我们必须在PrepareForBuild之后运行,以确保创建了中间目录。

请注意,“中间目录”(在本例中为obj/[TargetFramework])是将输出.cs文件放在这里的地方,这也可能是您想要做的。

票数 9
EN

Stack Overflow用户

发布于 2017-05-18 15:52:15

更新2

基于Microsoft提供的文档

这是目标构建顺序

  1. 运行InitialTargets目标。
  2. 运行由/target开关在命令行上指定的目标。如果在命令行中没有指定目标,则运行DefaultTargets目标。如果两者都不存在,则第一个遇到的目标将被运行。
  3. 评估目标的条件属性。如果条件属性存在并计算为false,则目标不会被执行,并且不会对构建产生进一步的影响。
  4. 在执行目标之前,它的DependsOnTargets目标将运行.
  5. 在执行目标之前,在属性中列出目标的任何目标都会运行.
  6. 在执行目标之前,对其输入属性和输出属性进行比较。如果MSBuild确定任何输出文件相对于相应的输入文件都是过时的,那么MSBuild将执行目标。否则,MSBuild跳过目标。
  7. 在执行或跳过目标之后,将运行在AfterTargets属性中列出该目标的任何目标。

以下是你的问题的答案:

如果我的目标应该在我的项目构建之前运行,因为该项目依赖它,那么使用后者更好吗?

  • 不是,因为CoreBuild的所有依赖项都将在模板生成目标之前执行,这将为时已晚。

还是AfterTargets="BeforeBuild“仍然保证在核心构建之前运行的原因?

  • AfterTargets="BeforeBuild“保证您的目标将按时执行,因为它将在所有CoreBuild依赖项之前执行。

我还看到了BeforeTargets="BeforeBuild" ,它将在更早的时候构建。这是放置`.tt文本生成目标的更好地方吗?

  • 在这两种情况下,AfterTargets=" BeforeBuild“或BeforeTargets="BeforeBuild”都将在所有CoreBuild依赖项之前执行,但是在这两种情况下,根据在BeforeBuild中执行的内容,仍然存在影响模板生成目标的结果的风险。如果您控制了这些选项,您可以安全地使用这些选项中的任何一个。

在CoreBuild?之前运行目标

代码语言:javascript
运行
复制
> 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提供的机制。

如果在CoreBuild之前只有一个目标要运行,则可以这样做:

代码语言:javascript
运行
复制
<Target Name="BeforeBuild">
    <!-- add your tasks here -->
</Target>

如果要在CoreBuild之前运行多个目标,则可以定义一个属性,其中包含需要按所需执行顺序调用的所有目标:

代码语言:javascript
运行
复制
<PropertyGroup>
    <BeforeBuildDependsOn>
      CustomTarget1;
      CustomTarget2;
      CustomTarget3
    </BeforeBuildDependsOn>
</PropertyGroup>

<Target Name="BeforeBuild" DependsOnTargets="$(BeforeBuildDependsOn)"/>

更新:

基于@stijn提供的片段:

AfterTargets=" BeforeBuild“将插入/执行如下自定义目标:(取决于BeforeBuild)

代码语言:javascript
运行
复制
<BuildDependsOn>
  BeforeBuild;
       |-> Custom Target


  CoreBuild;
  AfterBuild
</BuildDependsOn>

BeforeTargets="CoreBuild“将像这样插入/执行自定义(取决于CoreBuild):

代码语言:javascript
运行
复制
<BuildDependsOn>
  BeforeBuild;


       |-> Custom Target
  CoreBuild;
  AfterBuild
</BuildDependsOn>

因此,“模板生成目标”将在相同的位置(在BeforeBuild和CoreBuild之间)执行,但取决于不同的目标,这就是为什么要使用的A固有目标应该是BeforeBuild内联或依赖项。

现在关于第三方问题的评论,BeforeBuild/AfterBuild目标是针对最终用户的,第三方提供者应该在不影响基本工作流程的情况下实现他们的脚本。以下是第三方应该使用的一些选项,以避免打破常规流:

考虑到这一点为基础:

代码语言:javascript
运行
复制
<PropertyGroup>
    <BuildDependsOn>
      BeforeBuild;
      CoreBuild;
      AfterBuild
    </BuildDependsOn>
</PropertyGroup>

<Target Name="Build" DependsOnTargets="$(BuildDependsOn)"/>

选项1: --这将在BeforeBuild之前注入您的自定义第三方脚本,而不会影响默认的BuildDependsOn序列,这仍然允许最终用户不使用BeforeBuild目标。

代码语言:javascript
运行
复制
<PropertyGroup>
    <BuildDependsOn>
      MyCustomThirdParty;
      $(BuildDependsOn);
    </BuildDependsOn>
</PropertyGroup>

<PropertyGroup>
    <MyCustomThirdPartyDependsOn>
      BeforeMyCustomThirdParty;
      CustomStep1;
      CustomStep2;
      CustomStep1;
      AfterMyCustomThirdParty
    </MyCustomThirdPartyDependsOn>
</PropertyGroup>

<Target Name="MyCustomThirdParty" DependsOnTargets="$(MyCustomThirdPartyDependsOn)"/>

选项2:如果需要在BeforeBuild目标之后执行第三方脚本,可以这样做:

代码语言:javascript
运行
复制
<PropertyGroup>
    <BuildDependsOn>
      BeforeBuild;
      MyCustomThirdParty;
      CoreBuild;
      AfterBuild
    </BuildDependsOn>
</PropertyGroup>

注意:为了使其正常工作,必须在PropertyGroup导入之后添加Microsoft.CSharp.targets和目标。

这样,您将能够使用多个第三方脚本,尊重一般的工作流程。

显然,您可以根据情况使用这些选项的组合。但你应该遵循以下一般规则:

  1. 尊重默认工作流(BeforeBuild、CoreBuild、AfterBuild)。
  2. 包含第三方脚本的前/后目标,允许最终用户在第三方脚本执行之前或之后注入任何内容。

在使用默认的visual生成的构建脚本(如.csproj、.vbproj等项目)时,应该考虑这些因素。如果您正在为其他语言或目的实现您自己的脚本,您可以在任何地方使用BeforeTargets和AfterTargets,但是为什么不遵循基于现有脚本的良好实践呢?

票数 4
EN

Stack Overflow用户

发布于 2017-05-18 10:37:55

在Microsoft.Common.CurrentVersion.targets中,构建目标基本上是:

代码语言:javascript
运行
复制
<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"

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44043918

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档