【问题标题】:MsBuild builds projects in different order to Visual Studio 2015, and failsMsBuild 以与 Visual Studio 2015 不同的顺序构建项目,但失败
【发布时间】:2016-12-16 23:29:58
【问题描述】:

我有一个由五个 C# 项目组成的 Visual Studio 解决方案。其中四个项目是应用程序程序集,第五个是 MsTest 项目。程序集之间的依赖关系如下:

模型 常见的 用户界面 模型 常见的 通用 测试项目 常见的 模型 用户界面 UiCommon

应用程序分为前端 (Ui) 和后端 (Model) 程序集。这两个程序集都依赖于一个实用程序类库 (Common),而 Ui 程序集对另一个类库 (UiCommon) 有额外的依赖关系。测试项目依赖于所有其他项目。

如果我从 VS2015 重建 TestProject,它会同时从 Common 和 UiCommon 开始执行多线程构建(因为它们不相互依赖),然后依次是 Model,最后是 Ui。每个项目首先执行其 CoreClean MsBuild 目标,然后执行 CoreCompile。这很好用。

如果我改为使用 MsBuild 直接调用目标 Rebuild 进行构建,那么它的行为将完全不同,最终由于尝试以不可能工作的愚蠢顺序构建项目而无法构建项目。

在 MsBuild 下,TestProject 首先在 Model 上执行目标 CoreClean,后者在 Common 上执行 CoreClean 作为子任务。控制返回到调用 Ui 上的 CoreClean 的 TestProject,然后控制再次返回到调用 UiCommon 上的 CoreClean 的 TestProject。在此 TestProject 在 Model 上调用 CoreCompile 之后,它作为子任务在 Common 上调用 CoreCompile,然后控制返回到 TestProject,然后在 Ui 上调用 CoreCompile(由于未构建 UiCommon 而失败),之后控制返回到 TestProject,它在 UiCommon 上调用 CoreCompile构建(但这毫无意义,因为在 UiCommon 之前构建了 Ui 程序集,构建已经失败)。

因此,MsBuild 正在识别 Model 对 Common 的依赖,并以正确的顺序清理和构建这些项目以处理该问题,但未能识别 Ui 对 UiCommon 的依赖,尽管该引用以完全相同的方式定义。为什么会这样?

另外一件奇怪的事情是,在 VS2015 下重建 TestProject,每个项目在清理和构建任何后续依赖项目之前依次清理和构建。而使用 MsBuild 直接重建 TestProject 会导致所有项目被清理,然后是所有项目被构建。为什么会发生这种情况?

根据 MSDN VS2015 使用 MsBuild 在我直接调用 MsBuild 时传递给 MsBuild 的同一个项目文件上执行构建。我检查过在这两种情况下都调用了相同 (14.0.25420.1) 版本的 MsBuild,但在每种情况下构建以完全不同的方式进行。

两个版本都使用相同的项目文件来定义项目之间的依赖关系,我没有对那些应该导致 VS 和 MsBuild 行为不同的文件进行任何更改。我知道我可以覆盖 Visual Studio 的多线程构建行为,但我认为这不是问题的原因。我还记得过去 Visual Studio 使用了解决方案文件中有关项目内依赖关系的信息,但我认为现在一切都已经过去了,而现在这些都是在项目文件中定义的。

这对我来说没有任何意义,请问有人知道这里发生了什么吗?

【问题讨论】:

  • VS 和 msbuild.exe 命令行工具使用相同的构建引擎。所以应该没有区别——但是有不同的默认值——VS默认构建多线程,而命令行工具默认为单线程构建。在命令行上使用选项 /m 来运行多线程构建。但是,即使可以进行构建,也无法解决问题的根本原因。您可能有一些不考虑项目依赖性的自定义目标。我的建议是打开 msbuild 日志并仔细检查 msbuild.log。
  • 另一个常见问题,除了错误编写的自定义目标外,还有两个或多个项目使用相同的输出文件或相同的 obj 文件夹。确保项目的输出是分开的。 MSBuild 通过文件时间戳跟踪依赖关系,这意味着如果两个项目共享相同的输出,则只构建一个,跳过另一个。
  • @Neutrino >>每个项目首先执行其 CoreClean MsBuild 目标,然后执行 CoreCompile 你是怎么做到的?在构建目标之前更改 DefaultTargets 或指定?
  • 这就是重点。我什至不这样做。尽管我在 Visual Studio 中使用了 Rebuild All 命令并将 RebuildAll 目标传递给 MsBuild,但 MsBuild 本身的做法却有所不同。我不知道为什么它的行为完全不同。
  • @Neutrino,您是如何使用 MSBuild 运行解决方案的?您能否分享有关 MSbuild 错误的屏幕截图?像我在这里遇到的这个案例:stackoverflow.com/questions/38736860/…,你添加所有的解决方案平台吗?

标签: c# visual-studio visual-studio-2015 msbuild


【解决方案1】:

我注意到 Ui 中的 UiCommon 引用是二进制引用而不是项目引用。

是的,这就是问题所在,对于二进制引用,它不会在构建当前项目之前构建相关项目。正如您所说,其他项目有对 UiCommon 的项目引用,因此 UiCommon 将在 TestProject 重建期间清理并合并。因此,将该项目引用类型更改为项目引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-01
    • 2020-12-06
    • 2014-08-18
    • 2017-12-05
    • 2012-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多