在递归构建解决方案时,构建过程会挂起

时间:2015-02-24 21:13:32

标签: c++ visual-c++ visual-studio-2013 msbuild

在尝试回答this SO question时,我遇到了一个我无法解释的问题,我很感激您的意见。

设定:

  1. 包含多个C ++项目(Test.sln)的解决方案,
  2. 为您的解决方案添加一个全新的项目(BuildInstaller.vcxproj),
  3. 在文本编辑器中打开BuildInstaller.vcxproj并在关闭</Project>标记之前追加xml片段:
  4. <Target Name="Build">
      <MSBuild Projects="..\Test.sln" Properties="Configuration=Release;Platform=Win32" />
      <MSBuild Projects="..\Test.sln" Properties="Configuration=Release;Platform=x64" />
    </Target>
    
    1. 上面的代码会覆盖BuildInstaller项目的默认Build目标,每次构建项目时,它都会为Win32和x64平台构建具有Release配置的父解决方案,
    2. 要防止无限制的递归,请在Visual Studio中打开Configuration Manager并取消选中&#34; Build&#34; BuildInstaller项目的复选框,用于Debug / Release和Win32 / x64的所有组合,
    3. 然后,仍然在Configuration Manager中,创建一个新配置,例如安装程序,您应该取消选中所有其他项目的Build复选框,并仅为BuildInstaller选中它,
    4. 现在为安装程序配置构建解决方案。
    5. 我希望这个构建能够成功完成,但它只是挂起,即使不应该递归构建BuildInstaller,因为我们只是为Release配置递归构建Test.sln。

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

      我正在使用Visual Studio 2013 Ultimate。

1 个答案:

答案 0 :(得分:1)

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" />
    ...
    <!-- DO NOT ADD BuildInstaller project to prevent recursion!!! -->
</ItemGroup>

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

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

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