我应该如何构建我的MSBuild脚本

Mat*_*ias 3 msbuild

最近,我开始学习MSBuild,以便为本地和服务器构建(CI,Nightly,Weekly)灵活构建脚本.根据我的经验,我知道构建脚本可能非常尴尬.即使在我公司的某些指导下,了解所有目标以及它们如何协同工作也是一件痛苦的事.当然,这是一个长期的过程:你需要一些东西,你没有足够的时间,你开始变得懒散和凌乱.但我问自己,我怎么能构建一个MSBuild脚本以便于扩展和可读性?特别是目标DependsOnTargets,BeforeTargets,AfterTargets之间的三个关系,有用的射击自己的脚.

Say*_*imi 7

在我的MSBuild Book中,我有一个基于如何在MSBuild中创建可重用元素的部分,如果您感兴趣的话.我会在这里给出一些评论.这个内容与书的内容不同.

在创建MSBuild文件时,您应该小心隔离内容方式.为了解释这一点,让我们来看看托管VS项目如何开箱即用(这是可重用元素的一个很好的模型).

当您创建C#/ VB项目时,您将获得.csproj文件,此.csproj文件主要包含Properties和Items.您将无法在该文件中找到单个目标.这些文件包含了哪些将获得内置(与涉及建立一些设置一起).在项目文件的底部,您将找到一个import语句.这在进口带来如何构建项目.

导入的文件包括:

  • Microsoft.CSharp/VisualBasic中/ FSharp.targets
  • Microsoft.common.targets

在这种情况下,Microsoft.common.targets定义了所有托管语言的整体构建过程.然后Microsoft.CSharp.targets(或其他lang特定的.targets文件之一)填补了如何调用特定语言特定工具的空白.

DependsOnTargets与Before/AfterTargets相关

在你上面的回答中,你说" 我建议避免使用DependsOnTargets,除非真的有必要,例如两个 ".我不同意这一点.以下是我对DependsOnTargets与Before/AfterTargets的看法.

使用DependsOnTargets时

  • 当您尝试创建要执行的目标的工作流时
  • 当目标在没有其他目标首先执行的情况下不起作用
  • 当您需要根据所需操作在特定步骤注入不同目标时

使用Before/AfterTargets时

  • 当您不拥有目标所在的文件时,它没有可以扩展的DependsOnTargets属性
  • 您希望目标在特定目标之前/之后执行,无论它何时执行

为了梳理差异,有点考虑网络项目.对于Web项目,.csproj/.vbproj有两个工作流程:

  1. 建立
  2. 发布

如果我想在Build目标之前将目标添加到要执行的目标列表中,我可以仅为发布方案动态更新BuildDependsOn属性.您不能使用Before/AfterTargets执行此操作.

在理想世界中,每个目标都具有以下wrt DependsOnTargets.

  • 所有目标都有一个DependsOnTargets属性,该属性由属性提供
  • 每个DependsOnTargets始终将现有值预先添加到属性定义中

例如

<MyTargetDependsOn>
    $(MyTargetDependsOn);
    Target1;
    Target2
</MyTargetDependsOn>
Run Code Online (Sandbox Code Playgroud)

不幸的是,许多目标都没有遵循这种模式,所以DependsOnTargets在很多情况下都已经死了.

当我创作MSBuild脚本时,我总是使用DependsOnTargets,除非有一个坚实的理由我应该选择使用Before/AfterTargets.我觉得(我对设计的真正原因没有任何见解,因为我当时没有与微软合作)之前/之后实际创建的目标是允许用户注入要在目标之前/之后执行的目标拥有,创作者没有使用上面的模式.