您在哪里放置所有解决方案级别(全局)任务?在一个专门用于此目的的空白项目?

时间:2012-10-23 07:43:08

标签: c# visual-studio-2010 msbuild

当有人构建我的解决方案时,我想要运行多个任务,具体取决于解决方案配置:

  • 在发布配置中,为整个解决方案运行Doxygen(doxygen.exe ....)
  • 在调试和发布配置中,为整个解决方案运行StyleCop(调用StyleCop目标)
  • 在调试配置中,为整个解决方案(fxcop.exe ...)
  • 运行FxCop
  • 以及其他

这些都是解决方案级别(全局)任务,因此将它放在每个项目文件中都没有意义。这似乎是一个常见的问题,所以你如何应对呢?

我想我可以创建一个空项目,确保每个其他项目都依赖于它并将所有解决方案级别的任务放在那里......?

5 个答案:

答案 0 :(得分:3)

我更喜欢将这些任务放在.targets文件中,并从我的主项目中引用它们(大致是那些不生成库的项目)。我也可以在.targets文件中创建Target,它将组合常见任务的子集。这样,我的一些项目可以方便地运行sharedtask1sharedtask2,而其他项目则运行sharedtask1sharedtask3,因为我只添加DependsOnTargets="Shared12"和{{1 (显然,我会尝试选择描述性名称)。

这些文章对组织msbuild任务有一些很好的建议:

Best Practices For Creating Reliable Builds, Part 1

Best Practices For Creating Reliable Builds, Part 2

修改

仅运行一些任务一次使用增量版本,如上面第二篇文章所述:

  • 在我上面暗示的常见.targets文件中,创建一个任务,将所有文件作为输入,将一些虚拟标记文件作为输出。
  • 让该任务执行您感兴趣的实际工作更新标记文件。
  • 让所有项目都依赖于新创建的任务

构建解决方案时,第一个项目将启动上述任务,任务将输出一个标记文件,只要您的输入文件没有针对构建的其余部分进行更改,该任务就会赢得'再跑一次。 现在,缺点是

  • 如果您的构建导致在此过程中生成或更改文件,则任务将多次运行
  • 即使您只构建单个项目,任务也会运行。如果您要生成文档,这实际上可能是“正确”的行为。如果你想避免这种情况,我认为你必须对你的msbuild文件进行微调,但我得到的印象是你要避免这种情况。
  • 任务将在构建之前运行,因此任何依赖于待构建版本的程序集的任务都将失败

要解决上一个问题,您必须放弃从VS构建,而是使用命令行中的msbuild.exe调用自定义任务,该任务将构建解决方案,然后按顺序执行一个或多个自定义任务。我意识到这可能不是您正在寻找的开发人员体验。

答案 1 :(得分:3)

这个问题假设你希望每次都能建立一切,实际上我并没有发现这种情况。目前我正在与之合作的团队对构建时间非常敏感。

因此,我建议你认为构建不是一件事,而是有几种口味。有“它构建了吗?”构建,我将构建选择(仅当前项目)映射到一个键,直到我开始使用reshaper。对于没有进行单元测试的人(包括那些开发不可测试的ui变化的人),有一个“让我们测试它构建”,如果当然还有“Everything and the kitchen sink build”,其中文档,stylecop和任何其他指标都可以获得。

出于这个原因,我建议使用构建服务器。将您的其他目标放在一边,并在完成所有其他工作后使用它们。我建议TeamCity的预测试提交功能是一种很好的方法,可以让您的团队测试他们不会破坏并构建覆盖范围减少等故障情况。

另外,如果您在开发时搜索更快速的构建,那么我建议使用NCrunch,它具有高度优化的构建过程,可在大约一秒钟内编辑文件或ContinuousTests。

答案 2 :(得分:3)

最简单的方法是创建一个名为“Build.csproj”的空项目。将其置于解决方案中并使其依赖于所有其他项目。然后,对于简单的任务,您可以使用post-build事件来运行工具。如果您需要更高级,可以修改项目的Build目标。

有一些很好的事情:

  1. 设置和理解简单易行。
  2. 由于您将其他项目设置为启动项,因此通常不会干扰调试。
  3. 您可以创建忽略项目的配置。
  4. 假设您坚持发布构建事件,它允许VS集成而不会发出警告。

答案 3 :(得分:1)

也许我错过了什么,但为什么不创建一个解决方案文件夹,其中包含在所选目标上执行构建后续任务的各种脚本,并从项目的后期构建事件中调用它们?即。

  • PostBuildScripts(解决方案文件夹)
    • FxCop.Debug.Target
    • FxCop.Release.Target
    • StyleCop.Release.Target
    • StyleCop.Release.Target
    • Doxygen.Debug.Target
    • Doxygen.Release.Target
    • Others.Release.Target
    • Others.Release.Target

...等......

这些脚本调用以针对目标构建类型运行后续任务;如果你实际上不想针对某种构建类型运行它,只需将其留空即可。

项目中的后期构建:

/ PostBuildScripts / FxCop的$(ConfigurationName).TARGET

/ PostBuildScripts / Doxygen的$(ConfigurationName).TARGET

/ PostBuildScripts /了StyleCop $(ConfigurationName).TARGET

/ PostBuildScripts /其他$(ConfigurationName).TARGET

...等......

答案 4 :(得分:1)

在我们的解决方案中,我们将这些构建操作放在我们的启动项目中,因为我们不希望将它放在每个项目中,而我们正在运行的项目引用所有其他项目。因此,在完成所有其他项目之后,将在该项目的后期构建操作上运行所有操作。