构建过程在递归构建解决方案时挂起 [英] Build process hangs when recursively building solution

查看:221
本文介绍了构建过程在递归构建解决方案时挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试回答此SO问题时,我遇到了一个我无法解释的问题,非常感谢您的意见。 / p>

设置


  1. C ++项目(Test.sln),

  2. 在您的解决方案中添加一个全新项目(BuildInstaller.vcxproj),

  3. 在文本中打开BuildInstaller.vcxproj编辑器并在关闭< / Project> 标签之前附加以下xml片段:



< pre class =lang-msbuild prettyprint-override> < Target Name =Build>
< MSBuild Projects =.. \Test.slnProperties =Configuration = Release; Platform = Win32/>
< MSBuild Projects =.. \Test.slnProperties =Configuration = Release; Platform = x64/>
< / Target>




  1. 上述代码覆盖默认 Build BuildInstaller项目的目标,并且每次正在构建项目时,它都为Win32和x64平台的发布配置构建父解决方案,

  2. 无界递归,在Visual Studio中打开配置管理器,并为所有Debug / Release和Win32 / x64组合取消选中BuildInstaller项目的Build复选框,

  3. 新配置,例如安装程序,您应该取消选中所有其他项目的生成复选框,并保留选中BuildInstaller,

  4. 现在构建您的解决方案安装程序配置。

我希望这个构建成功完成,但它只是挂起,即使BuildInstaller不应该递归构建,因为我们递归地构建Test.sln只为Release配置。 p>

我不是问这是一个好的方法或如何解决它,我只是好奇为什么构建挂起。将输出窗口的详细程度设置为Diagnostic对我没有帮助。



我使用Visual Studio 2013 Ultimate。

解决方案

MSBuild对项目中的递归有一个内部保护。通常你的构建将失败,错误MSB4006在一种情况下如果在构建图中发现任何类型的循环依赖。也就是说,如果我猜猜可能导致挂起,如果它与递归相关,我会倾向于.sln文件的一边。原因是MSBuild处理.sln文件的方式是相当奇怪的。任何时候遇到.sln文件,它会将其转换为实际MSBuild引擎可以理解的中间表示。该中间表示没有与项目文件类似的任何标识符,因此如果.sln在循环中,循环依赖检测逻辑可能无法正常工作。



为了解决你的特殊问题,有几种方法。最简单的方法是从Test.sln中删除BuildInstaller.vcxproj。第二个是修改BuildInstaller.vcxproj如下:



首先,创建一个ItemGroup,填充来自解决方案的所有项目:

 < ItemGroup> 
< AllMyProjects Include =.. \Proj1\Proj1.vcxproj/>
< AllMyProjects Include =.. \Proj2\Proj2.vcxproj/>
...
<! - 不要添加BuildInstaller项目以防止递归! - >
< / ItemGroup>

然后为每个配置构建项目:

 < Target Name =Build> 
< MSBuild Projects =@ AllMyProjectsProperties =Configuration = Release; Platform = Win32/>
< MSBuild Projects =@ AllMyProjectsProperties =Configuration = Release; Platform = x64/>
< / Target>

第二种方法的缺点是必须记住保持项目列表之间同步。 sln和您的安装程序项目。


While trying to answer this SO question I encountered an issue which I cannot explain and would appreciate your input on.

Setup:

  1. Have solution consisting of several C++ projects (Test.sln),
  2. Add a brand new project to your solution (BuildInstaller.vcxproj),
  3. Open BuildInstaller.vcxproj in text editor and append following xml fragment right before closing </Project> tag:

<Target Name="Build">
  <MSBuild Projects="..\Test.sln" Properties="Configuration=Release;Platform=Win32" />
  <MSBuild Projects="..\Test.sln" Properties="Configuration=Release;Platform=x64" />
</Target>

  1. Above code overrides default Build target of the BuildInstaller project and everytime the project is being built, it builds its parent solution with Release configuration for both Win32 and x64 platforms,
  2. To prevent unbounded recursion, open Configuration Manager in Visual Studio and uncheck "Build" checkbox for BuildInstaller project for all combinations of Debug/Release and Win32/x64,
  3. Then, still in Configuration Manager, create a new configuration, e.g. Installer for which you should uncheck all the other project's Build checkbox and leave it checked for BuildInstaller only,
  4. Now build your solution for Installer configuration.

I would expect this build to finish successfully, but it simply hangs, even though BuildInstaller should not be built recursively as we are recursively building the Test.sln only for Release configuration.

I am not asking whether this is a good approach or how to work around it, I am just curious why the build hangs. Setting output window verbosity to Diagnostic was of no help to me.

I am using Visual Studio 2013 Ultimate.

解决方案

MSBuild has an internal protection about recursion in the projects. Normally your build will fail with error MSB4006 in a case if any sort of circular dependency is discovered in the build graph. That said, if I were to guess what might have caused the hang, and if it is related to recursion, I would have inclined on the side of .sln files. The reason is that the way MSBuild treats .sln files is quite peculiar. Any time it encounters .sln file, it converts it to intermediate representation that actual MSBuild engine can understand. That intermediate representation does not have any identifier similar to the project file, thus the circular dependency detection logic might not work correctly if .sln is in the loop.

To solve your particular problem, there are couple of ways. The easiest one is to remove BuildInstaller.vcxproj from Test.sln. The second is to modify BuildInstaller.vcxproj as follows:

First, create an ItemGroup, populated with all projects from the solution:

<ItemGroup>
    <AllMyProjects Include="..\Proj1\Proj1.vcxproj" />
    <AllMyProjects Include="..\Proj2\Proj2.vcxproj" />
    ...
    <!-- DO NOT ADD BuildInstaller project to prevent recursion!!! -->
</ItemGroup>

Then build the projects for every configuration:

<Target Name="Build">
    <MSBuild Projects="@AllMyProjects" Properties="Configuration=Release;Platform=Win32" />
    <MSBuild Projects="@AllMyProjects" Properties="Configuration=Release;Platform=x64" />
</Target>

The downside of the second approach is that you have to remember to maintain list of projects in sync between .sln and your installer project.

这篇关于构建过程在递归构建解决方案时挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆