1

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.

Community
  • 1
  • 1
Michal Hosala
  • 5,570
  • 1
  • 22
  • 49

1 Answers1

1

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.

seva titov
  • 11,720
  • 2
  • 35
  • 54
  • Comments: if I enable building `BuildInstaller.vcxproj` for Release configuration, then the build ends up with the "Circular Dependency" error, which is expected, but the hung build in case of Installer configuration is still a mystery to me. As for the workarounds - thats exactly what I proposed to do in a [linked SO thread](http://stackoverflow.com/q/28540015/3242721), only difference being that I transformed the `BuildInstaller.vcxproj` to simple `BuildInstaller.msbuild` script. So I am glad my approach was not that ill-minded :) I'll accept the answer if nobody explains better soon. – Michal Hosala Feb 25 '15 at 23:11
  • Just FYI, I still have no idea why this is happening. Surprisingly enough, if I build the solution from command line instead of IDE, everything works well, I mean `msbuild Test.sln /p:Configuration:Installer` – Michal Hosala Mar 08 '15 at 22:33
  • If you want to get to the bottom of the problem, you should report this bug to Microsoft, because only MS VS team is able to investigate the problem and fix it. A smaller self-contained repro files would help you get their attention, and if you mention the problem only visible in IDE, it would narrow down the group to follow up. – seva titov Mar 09 '15 at 01:01
  • You read my mind, I did so [here](https://connect.microsoft.com/VisualStudio/feedback/details/1169409), feel free to upvote :) – Michal Hosala Mar 09 '15 at 08:42