Does MSBuild resolve project to project references when building a solution? - visual-studio

MSDN docs Visual Studio Integration (MSBuild) state:
Building Solutions
Within Visual Studio, the solution file and project build ordering are
controlled by Visual Studio itself. When building a solution with
msbuild.exe on the command line, MSBuild parses the solution file and
orders the project builds. In both cases the projects are built
individually in dependency order, and project to project references
are not traversed. In contrast, when individual projects are built
with msbuild.exe, project to project references are traversed.
With my Visual Studio 2010, when building a .sln file with MSBuild from the command line, project to project references are all built, regardless whether they occur in the solution.
What did I miss here? Or are the docs plain wrong?

You are correct that msbuild.exe will sort out all project references whether or not they are part of the solution in contrast to building within Visual Studio 2010/2012/2013/2015 (and possibly later versions) where you will get a build failure if a referenced project is not part of the solution or built beforehand.
In short, yes, the documentation seems a bit off.

You can ignore the build of project to project reference by running msbuild Solution.sln /t:ProjectName /p:BuildProjectReferences=false this explain the sentence in msdn.

Related

Visual Studio build successful, MSBuild fails

I am trying to clean and rebuild a solution file with multiple projects from the command line using MSBUILD. For some reason my build fails (about 10% of the built projects fail) and I get multiple errors which all look like:
error CS0234: The type or namespace name 'foo' does not exist in the namespace 'bar' (are you missing an assembly reference?)
Now if I clean and rebuild the same solution file from Visual Studio 2010 with the exact same configurations it will build successfully with no errors.
Is there a difference in the setup or configuration of MSBuild from Visual Studio that needs to be changed that I am not aware of?
I just had to deal with this issue and it turns out that msbuild likes to move built binaries into the binaries\release directory and reference those instead of the projects themselves when it builds things. After building it copies the files to this directory. This explains why it works in visual studio and not msbuild (I'm currently using TFS 1010).
In my case I had an old binary version of a dll being referenced by a project that was being built after the one that should have generated the correct file. The old one (binary) was overwriting the new one (built from source) as the solution referencing the binary one was being built later in the build.
I assume there's a difference in how the project is built, because Visual Studio does not run MSBuild, as it rather hosts the build engine itself.
This was answered here.
However, I've had similar problem.
In my case the project referenced an external library, which was placed in the project's child directory, unluckily named "packages".
After running MSBuild the folder's content was deleted, supposedly to be downloaded again by Nuget.
The obvious solution was to rename the folder and it worked.
Summary: Set Debug/Release mode in Visual Studio to the same settings as MSBuild to check for compilation errors.
I encountered the same problem:
Tried deleting all "bin" and "obj" folders.
Made sure all related projects are indeed being referenced and not just liked to compiled dlls. ex. Project B references A. Remove A from solution. Then add again. B would then reference A but via compiled dll only. Remove reference and re-add the project.
Finally switched to "Release" in Visual Studio. Turns out I had conditional compilation in some code (eg. #if DEBUG). So what was running in MSBuild and Visual Studio were actually different hence the error "The type or namespace name 'foo' does not exist in the namespace 'bar' (are you missing an assembly reference?)"
Try checking the paths to the references that MSBuild can't find in the non-building library's project file. Sometimes when you use VS or ReSharper to automatically add a reference for you the path ends up being to the \obj directory. VS seems able to cope with this, but MSBuild not so much.
For me the problem was that the some projects in the solution were not included in the build configuration for the solution. Those projects were dependencies for the projects in the build configuration, so all the projects in the solution failed.
After marking the dependcies projects with build in the solution configuration the msbuild ran successfully.
My issue was found in the solution file.
Remove all lines which reference 'ANY' for CPU and leave the 64 bit ones in.
In my case I had one PCL referencing another PCL with different targets. Visual Studio showed me a warning in the references list of the first library, but compiled the solution, whereas MSBUILD refused to compile. I fixed the problem by retargeting the PCL. Hope this helps somebody.
See my answer here.
Basically - Try running msbuild in a new cmd window everytime as a temporary workaround.
I was facing a similar issue. But after spending a lot of time, I finally came up with a solution (that performs similar to VS)
Use the following command to build your solution
"msbuild.exe project.sln /restore /t:Build /p:Configuration="Release";RunCodeAnalysis=False;RestorePackagesConfig=true”

VS2010/MSBuild 4.0 building external projects

It seems that since VS2010 and MSBuild 4.0, VisualStudio and MSBuild are able to resolve and build project references that are not located within the solution.
Let us create an example to be more concrete. Create a solution called Solution1 with a C# project named A and another project called B. In project B, add a reference to project A. Now create a new solution called Solution2 and click "Add Existing project" and select Project B. There is a warning that can be seen in Solution Explorer and the Warning List.
The trick is that even with "warning as error" we are able to build Solution2.sln. Actually, project A is found
and built by Visual Studio or MSBuild. Let us verify this by opening a VS2010/VS2012 command line and execute the following commands:
msbuild <dirPathToSolution1> Solution1.sln /t:clean **cleaning up solution1 with project A"
msbuild <dirPathToSolution1> Solution2.sln /t:build
ProjectA is effectively built and worse: the warning mentioned above is not even raised there. With previous versions of Visual Studio such situation could not happen (I have tested it with msbuild 3.5 and VS2008).
However, in our situation we would like to prevent such things. Indeed, we have a large source repository with several solutions and many committers. We are reorganizing our dependencies aiming finally to the extraction of smaller repositories. Meanwhile, we do not want developers to add hidden project dependencies without seeing it. We would like to allow only project references "inside" a solution, leaving other dependencies to assembly references.
So the question is "Is there a way, to prevent such solution such as Solution2 to build ?". Ideally, it should not compile with both VS2012 and MSBuild. However a solution involving only the MSBuild command line would do thanks to our Continous Integration.
edit I checked Microsoft.Common.Targets and there does not seem any way to achieve what you want. Either project references are built, or they are not (this is for instance influenced by the BuildProjectReferences flag of my original answer). There is no way to build them selectively depending on which solution they are in unless I'm missing something - which is mainly because project references are set on the project level, not on the solution level: in your project file there is an MsBuild ItemGroup named ProjectReferences and that is used. (Actually this makes some sense: if you ask MsBuild to build projectB.csproj, and B says it references A, then no solution comes into play and you could expect it to build A, after all you are referencing it).
Now as I understand it, you want to prohibit referencing across directories whose structure happens to be represented by solutions. If that is the case, and you really need this, you could probably get away with a tool that parses the MsBuild log and looks for lines like
Project "somedir\projectB.csproj" (2) is building "someOtherDir\projectA.csproj" (3) ...
then extract the directory info from it and make the tool raise an error when they do not match. Then incorporate the tool in your CI server and feed it with the msbuild log files.
original answer
Try with /p:BuildProjectReferences=false on the command line. As the name suggests it will disable building of referenced projects. When building solution1, this should not be a problem since projectA will be built anyway as it is in the solution. However when building solution2, it won't build projectA and you'll get a build error.

Projects dependencies between C# and C++ project, build order

If both project Alpha and project Beta are C# projects, we can set that Beta depends on Alpha and this results to following build order: 1) Alpha; 2) Beta
If project Alpha is C++ project, we cannot add reference from project Alpha to Beta because Visual Studio 2010 does not allow this. Actually we can hack csproj file with notepad, but it doesn't help. Bu we can right click on solution, choose Project Dependencies and say that Beta depends on Alpha.
Problem: MSBuild does not honor dependencies set in sln file and builds projects in wrong order - 1) Beta; 2) Alpha. Note, that Visual Studio honors build order.
How we can set build order for MSBuild between C# and C++ projects within same solution?
Try adding your C++ project reference to the C# project after cleaning the solution. This works for me, although I stumbled on this "workaround" by pure chance.
To me it looks as if Visual Studio is checking the build product of the referenced project, and when it notices the incompatibility it will refuse to add the reference. If, however, the build product is not around to check (because you cleaned the solution), Visual Studio happily adds the reference.
I tested the resulting solution both in Visual Studio and on our TFS build server (which AFAIK uses MSBuild) and build dependencies were evaluated correctly in both cases.
In your question you also mention that manually editing the .csproj file didn't help. I cannot confirm this. I was able to add the following reference and again got a positive build result:
<ProjectReference Include="..\Foo\Foo.vcxproj">
<Name>Foo</Name>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<Private>False</Private>
</ProjectReference>
I am adding the ReferenceOutputAssembly element because this blogs.msdn.com article suggests it. In my experience, though, the build also works without the element. The article is still worth reading because it explains why MSBuild does not honor dependencies defined in the solution.
For completeness sake: I am running Visual Studio 2010, Version 10.0.40219.1 SP1Rel.

MSBuild output vs Visual Studio output against a COM interop

I am attempting to a get a isolated build environment setup in my dev team.
The problem that I am presently hitting is a DotNet project which has a reference to a VB6 COM assembly.
The COM assembly is registered on the build system, but when I run msbuild against the sln I get the following error:
error MSB3303: Could not resolve COM reference "f630637a-718a-41c7-9c52-41f934dc4625" version 3.2. Object reference not set to an instance of an object.
The GUID for this assembly is correct, and if I load the solution up in Visual Studio it builds fine and generates Interop.* assemblies as required.
I do not wish to have the Visual Studio build as a requirement in the build steps.
How can I get msbuild from the command line to build the Interop assemblies the same as VS?
It appears that msbuild does not follow the project dependencies the same way as the IDE - as per this question
If I build the specific project that was failing before building the entire solution everything is good.

Creating a custom project type for Visual Studio to build Borland C++ Builder projects into Visual Studio

I want to start the develop of a custom project type for Visual Studio that builds a BPR project with Visual Studio.
I need some hints to beginning with this project. Where can I find a template for this type of projects?
My target is to remove the Borland C++Builder's ugly and unstable interface from the development process and work enterely from Visual Studio.
Edit: Oops, I didn't really see that you're about to create a new project type for C++ Builder files. In that case, you have to build a language package. The Visual Studio Extensibility site should get you started. Also have a look at this more specific link.
I'll leave my old answer here for reference, because it might help people who just want to build C++Builder projects without creating a whole new project type :)
You didn't specify the version of Visual Studio, but I'll assume a recent one. In Visual Studio 8 and 9, most project files (all popular ones except Visual C++) are actually MSBuild files and can therefore be built by MSBuild. You can add a simple command line task (Exec) to build your bpr on the command line, or you can create a custom task for this (if you don't find one already available - the search terms should be MSBuild and custom task). This way, both Visual Studio and MSBuild can build anything you like. If you don't have an MSBuild file to start with or want to dive into developing a task, the MSBuild project template for Visual Studio will help you.
Oh, and other than that, if you don't actually need C++Builder things, you might as well export the BPR as a solution (or create a new solution and add the files).
Integrating C++Builder projects into a build process should be a lot easier with C++Builder 2007 or 2009 as both use MSBuild as build system. But then, I think that upgrading to a recent version of C++Builder solves your problem the other way :)

Resources