我有一个由五个C#项目组成的Visual Studio解决方案。其中四个项目是应用程序集,第五个是MsTest项目。程序集之间的依赖关系如下:
Model Common Ui Model Common UiCommon TestProject Common Model Ui UiCommon
应用程序分为前端(Ui)和后端(模型)程序集。这两个程序集都依赖于实用程序类库(Common),Ui程序集对另一个类库(UiCommon)具有额外的依赖性。测试项目依赖于所有其他项目。
如果我从VS2015重建TestProject,它会同时执行从Common和UiCommon开始的多线程构建(因为它们不相互依赖),依次是Model和Ui。每个项目首先执行其CoreClean MsBuild目标,然后执行CoreCompile。这很好。
如果我使用MsBuild直接调用目标Rebuild进行构建,那么它的行为完全不同,最终由于尝试构建一个无法工作的愚蠢顺序而无法构建项目。
在MsBuild下,TestProject首先在Model上执行目标CoreClean,它在Common上执行CoreClean作为子任务。 Control返回到在Ui上调用CoreClean的TestProject,之后控制再次返回到TestProject,它在UiCommon上调用CoreClean。在这个TestProject在模型上调用CoreCompile之后,它作为子任务在Common上调用CoreCompile,然后控制返回到TestProject,然后调用Ui上的CoreCompile(由于未构建UiCommon而失败),之后控制返回到TestProject,后者在UiCommon上调用CoreCompile。构建(但由于Ui程序集在UiCommon之前构建,因此构建已经失败,因此无意义。)
因此,MsBuild正在认识模型对Common和清理的依赖,并以正确的顺序构建这些项目来处理它,但是尽管该引用以完全相同的方式定义,但未能识别Ui对UiCommon的依赖性。为什么会这样?
另一件奇怪的事情是,在VS2015下重建TestProject,在清理和构建任何后续依赖项目之前,依次清理和构建每个项目。而使用MsBuild重建TestProject直接导致所有项目被清理,然后是所有正在构建的项目。为什么会发生这种情况?
根据MSDN VS2015使用MsBuild在我直接调用MsBuild时传递给MsBuild的同一项目文件上执行构建。我已经检查过在两种情况下都调用了相同的(14.0.25420.1)版本的MsBuild,但是在每种情况下构建都以完全不同的方式进行。
两个版本都使用相同的项目文件来定义项目之间的依赖关系,我没有对那些应该导致VS和MsBuild表现不同的文件做任何更改。我知道我可以覆盖Visual Studio的多线程构建行为,但我不认为这是问题的原因。我还记得,在过去,Visual Studio使用了解决方案文件中关于项目内依赖关系的信息,但是现在认为混乱已经过去,现在这些都是在项目文件中定义的。
这对我没有任何意义,有没有人知道这里发生了什么?
答案 0 :(得分:0)
我注意到Ui中的UiCommon引用是二进制引用而不是项目引用。
是的,这是问题,对于二进制引用,它不会在构建当前项目之前构建相关项目。正如你所说的其他项目有UiCommon的项目参考,所以UiCommon将在TestProject重建期间保持清洁和组合。因此,将该项目引用类型更改为项目引用。