28
votes

I have a large solution with more than 100 projects (C++, Managed C++, C#) and many of them depends on each others.

I have a TeamCity server and I want build this solution there.

When I build solution in VisualStudio everything goes fine, but with TeamCity I have a CS0006 error. I know why that so - TeamCity uses MSBuild 4 to build solutions, but there is a known bug in MSBuild 4 - it ignores build order and build projects from solutions in order it wants. Because of this behavior if you have:

Project A
Project B which has reference to A

MSBuild can build these project in such order:

1. B
2. A

The easiest solution is to set BuildProjectReferences=true (which is default) and all referenced project will be builded automatically. But I can't use this approach because not all referenced project in this solution, and I can't build projects from another solution.

Here is another fix for this problem - use ConfigurationManager and disable all projects, which shouldn't build, but it works only in VisualStudio - MSBuild ignores that and builds all referenced projects.

The problem is to restore build order which I can see in VisualStudio in window ProjectBuildOrder which is not true if I use MSBuild directly from Console.

4
This is a pretty general question, can you be more specific? Does it build in visual studio?Ritch Melton
No, I use JetBrains TeamCity server, which uses MSBuild. If I run build from VisualStudio everything fine.igofed
Could you be more specific -- how to fix what? Do you want to fix your pre-build events or fix a build when you disable building project references?seva titov
I'm familiar with TeamCity. Are you referencing the solution file in its configuration? What is the actual build error? It seems like you are assuming some sort of 'known problem', but AFAIK all this stuff pretty much just works, unless you are doing something esoteric. 100 projects isn't horrible, I've had ~350 building under CI.Ritch Melton
I updated question and tried to be more specificigofed

4 Answers

29
votes

See Incorrect solution build ordering when using MSBuild.exe at The Visual Studio Blog:

Follow this principle: do not use dependencies expressed in the solution file at all! Better to express dependencies in the file that has the dependency: put a project reference in the project, instead. In our example, that would be a project reference from B to C.

You may not have done that before because you didn’t want to reference the target of the project reference, but merely order the build. However, in 4.0 you can create a project reference that only orders the build without adding a reference. It would look like this – note the metadata element, and all this is inside an <ItemGroup> tag of course:

<ProjectReference Include="foo.csproj">
    <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>

Note that you have to add the child element with a text editor — Visual Studio can add a project reference, but doesn’t expose UI for this metadata.

I can tidy up by removing the dependency in the solution file as well – removing now-unnecessary lines like this — your GUID will be different, but use the VS dialog and it will do the job...

7
votes

I had a problem much like this. It manifested itself in the solution, by requiring two builds before successfully building the entire solution.

As it turns out, I had accidentally added a Reference and not a ProjectReference (look for this in the .sln file), meaning VS/MSBuild would require and look for the referenced library file, but be completely unaware of how to build it if it was missing. Eventually the build process would come around to the project with the referenced library, building it and making it available for the next build attempt.

Depending on your dependency tree and the particular mood of the MS toolchain, this could turn up as a sporadic error, and thus be a bitch to debug.

Short version: Make sure references to projects inside the solution are listed as ProjectReference and not just Reference. Do this by adding the reference on the Solution tab instead of browsing and picking the DLL file.

7
votes

The solution above didn't quite work for me when trying to build a .Net Standard project that depended on the output from a .Net Core project. I had to add an additional "SkipGetTargetFrameworkProperties" in order to get the solution to build in VS2017 and MSBuild.

<ProjectReference Include="foo.csproj">
    <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
    <SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
</ProjectReference>
0
votes

Nothing mentioned above did not help for me. The aolution I used was to build the sln few times, passing /t:1stproject.csproj in the first run, then /t:2ndproject and at the end the sln without /t to comlete the rest of the solution.