Hi All and welcome to another installment of "Shouting at the Wall!", I'm your host Steve St.Jean.
On today's show we are going to shout at the wall that is Microsoft's "Decider of things to be fixed." I have no idea who this person actually is, so I'll blame the whole company. Here's the story...
Problem: You have an Application "A" that uses Class "Foo" which resides in Assembly "B". Class "Foo" implements Interface "IFoo" which resides in Assembly "C". So Application "A" holds a direct reference to Assembly "B" and Assembly "B" holds a direct reference to Assembly "C", but Application "A" does not hold any reference to Assembly "C".
When you bring all three of these projects into a Visual Studio 2005 solution and build them, the compilation runs without error, but when you run the same solution through MSBuild, you find that the build fails with an exception stating that the build cannot find a the reference to Assembly "C".
error BC30009: Reference required to assembly "C, Version=188.8.131.52, Culture=neutral, PublicKeyToken=2c72757e0bcb9887' containing the implemented interface 'IFoo'. Add one to your project.
Issue: The cause of this problem is that since Application "A" doesn't have a direct reference to Assembly "C", MSBuild cannot find the Interface "IFoo" that it needs to complete Class "Foo". What I am seeing is that MSBuild will start resolving references for Application "A"; it finds that Assembly "B" is referenced, so it reads the project file for Assembly "B" and finds where the its binary was compiled. This binary is copied into Application "A"'s \bin folder and then Application "A" is compiled. Unfortunately, MSBuild doesn't have the functionality to read Assembly "B"'s project file to find its dependencies, so we get this error. To get Application "A" to build, you need to add a reference to Assembly "C" even though none of its classes are used directly by the application.
The reason that the Visual Studio 2005 IDE can build this kind of solution is that it can figure out where Assembly "C"'s binary resides prior to compilation of Application "A". I have spoken with Microsoft Premier Support on this subject. They have stated that Visual Studio's behavior is a "side-effect" of other processing that the IDE has to do.
I asked Microsoft to fix the problem with MSBuild so that it walks the dependency tree within the Solution to find the dependencies correctly. The result would be that MSBuild behaves like the Visual Studio IDE.
Ok, now that I've laid out what the problem is, let me give you the response that Microsoft Support gave me when I asked for MSBuild to be fixed. After they spent some time looking into the issue, I was informed that they would be fixing the problem in a future release. The "fix" they gave was that they would "modify" the Visual Studio IDE to behave like MSBuild does. The VS IDE would throw the same error BC30009 in this situation.
Gripe: I am not happy with the answer that Microsoft Support passed to me from the dev team. I don't think that selecting the "easier" fix is necessarily the best way to fix this problem. My dev leads have stated to me that they don't think that having to add direct references to secondary assemblies is a good idea. The big problem is that Microsoft build a cool little feature into the VS 2005 IDE labeled "Remove unused references". After you get your build up and running, all you need to have that build come crashing down around you is to have a conscientious developer that runs this feature.
I'd prefer to see MSBuild "upgraded" to support looking through the solution's projects to find the references rather than "downgrading" the VS 2005 IDE. More than any other reason though, I believe that fixing MSBuild is the "right" thing to do. So I'd like to give a great big "DUH" to the person or persons at Microsoft that came up with this "fix". I don't think that this decision is bad enough to get an article on "The Daily WTF", but it's close.
I've attached the test solution that I sent to Microsoft Support to illustrate the issue. If you want to see what I've been complaining about, just extract it and compile it in the IDE, then create a standard Team Build for it. The VS IDE will build it but the Team Build will fail.