【问题标题】:TeamCity + artefacts + chained builds + MSBuild + csproj/dll referencing issueTeamCity + artefacts + 链式构建 + MSBuild + csproj/dll 引用问题
【发布时间】:2014-01-13 15:05:47
【问题描述】:

我正在为超大型系统(300 多个项目)编写构建/ci/deploy 流程。这是一个 C# .net 项目,我们使用 Visual Studio 进行开发 IDE 和 MSBuild(来自 psake 任务)来编译我们的解决方案。

有多个解决方案包含多个项目,更糟糕的是,一些项目被引用为 .csproj 文件,而一些被引用为 .dll。构建重构的第一步将是实现所有项目将通过 csproj 文件相互引用。这样我就可以创建一个包含所有项目的主解决方案,并使用 MSBuild 支持的并行构建,这将非常适合 CI 构建。

但对于部署构建,我想使用链式构建和人工制品依赖项。

我想象我的构建如下:
1. 搭建公共图书馆
1.1 将 .dll 作为 common.zip 存储在人工制品中
2. 使用 1.1 中的人工制品并构建 CoreProduct
2.1 将 CoreProduct 中的 .dll 存储在 artefacts 中作为 product.zip
...等等(这样还有 20 个步骤)...

问题在于 CoreProduct 的 CommonLibrary 引用为 .csproj,而这些 .csproj 文件不会作为 CoreProduct 构建存在,为什么会出现这种情况,因为 CommonLib 已经构建并且人工制品已准备好。 MSBuild 项目文件(CSPROJ 文件)包含有关需要编译的文件以及有关引用项目而不是解决方案文件的信息,因此我无法为部署系统创建单独的 .csproj 文件,开发人员将使用他们的类文件并将其添加到不同的项目文件中我将不得不管理这两个项目文件(例如 real.csproj 和 real.CI.csproj)之间的困难同步。 我可以使用 T4 模板来生成这两个文件,但这样我会从 Visual Studio 轻松添加文件。

.csproj 中的条件部分不在图片中,因为有超过 50 名开发人员并且了解到现在添加引用需要调整 .csproj 文件是不可能的 :)

我正在寻找如何解决这个问题的模式/想法

【问题讨论】:

  • +1 以清晰的方式解释整个问题

标签: visual-studio build msbuild teamcity csproj


【解决方案1】:

正如您自己已经发现的那样,这两个要求(仅项目引用 + 链式构建)相互矛盾。至少我想不出办法让他们一起玩。所以其中一个必须以某种方式改变。

第一个想法:您真的需要链式构建吗?设置需要一段时间,最后你可能还是想构建所有东西,那么为什么不默认构建所有东西呢?

如果上面的答案是“是”:假设毕竟不使用项目引用。直接使用 dll 引用是一团糟,不推荐。不过,您可以以某种方式使用 NuGet。这意味着例如 CommonLibrary 内置在一个包中,而其他构建通过 NuGet 使用该包,这意味着它仍然是一个 dll 引用,但安装是自动的。我见过人们用 TeamCity 来做这件事(因为它可以充当包服务器),但我不知道设置的细节,也不知道如何处理本地开发版本。当然,这确实意味着教您的开发团队仅使用 NuGet 添加引用。

另一种方式:您保留项目引用(耶!),但对于链式构建,您在所有项目文件上运行脚本,删除引用并将其替换为程序集引用。听起来很乱,但我也在使用这样的东西,一旦设置它就非常万无一失。在实践中,您会向 TC 添加一些构建步骤,以便获得如下构建流程:

  • 签出 CommonLibrary,构建和存储人工制品
  • 签出 CoreProduct、运行脚本、构建和存储工件
  • 检查 XYZ、运行脚本、构建和存储工件

脚本会:

  • 查找ProjectReference 项目
  • 存储Name标签的值
  • 删除ProjectReference
  • 对于上面找到的每个Name,添加一个简单的引用,如<Reference Include=name HintPath=/path/to/artefacts>
  • 保存项目文件

如果您使用 C# 和 Microsoft.Build.Construction 命名空间中的类,编写这样的程序相对容易,因为它们可以处理项目文件。或者你可以使用你喜欢的 xml 库。

编辑

回应您的评论/回答:您的构建环境似乎有点残缺。您可以花费大量时间找出解决方法等,或者您可以一劳永逸地正确修复它。根据我的经验,第一个选项会导致越来越多的问题,最后你会留下一个单一的块,即使是最轻微的变化也会导致问题的瀑布,需要更多的时间来解决所有问题。另一方面,第二个选项(例如,不依赖 SolutionDir 并将目标放在所有项目都可以访问的公共位置 - 没有不同的项目输出具有相同名称的程序集,...)现在可能需要更多时间,但是最终这将是值得的,因为您将获得一个相当干净且易于扩展的构建系统,并且您将来不会浪费更多时间。此外,如果您现在解决上述问题,您可能可以简单地使用类似我上一个解决方案的方法,并且不需要选择元素/多个项目/条件/...等:脚本创建一个全新的项目文件,仅用于链式构建,仅此而已。

【讨论】:

    【解决方案2】:

    @stijn:

    由于此消息太长,无法发表评论,因此我将其写为答案。
    感谢您的回复和您的所有建议。 正如您提到的那样,使用 NuGet 会使开发人员的环境复杂化,所以这是不可能的。 我正在使用Microsoft.Build 库将引用从 .dll 切换到 .csproj 来构建一个“主”解决方案。我喜欢你的想法,我自己也一直在考虑,导入目标时出现问题,它们依赖于MSBuild的SolutionDir属性,命名项目不一致,我们有两个不同的项目(.net版本) 和相同的 AssemblyName, ....
    我可以继续进行条件构建并重新创建新的解决方案文件,例如*.TeamCity.sln, *.Dev.sln
    我可以将条件与导入、引用、... 我可以创建一个工具来自动删除新引用并将它们添加到 Choose 部分,从 VisualStudio 删除引用已完成属性(它删除 Choose 部分中的 ProjectReference 标记),并且我的提交后工具可以检测到这些变化。由于公司的政策是所有项目都有前缀,因此我可以轻松区分哪些项目与我相关。相当大的问题还在于Microsoft.Build.Evaluation 不支持Choose 部分,所以我必须编写整个项目解析,例如XDocument.

    我仍然对这个解决方案不是 100% 满意,我仍然愿意接受建议。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-15
      • 2013-06-23
      • 1970-01-01
      • 2011-04-23
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      • 1970-01-01
      相关资源
      最近更新 更多