MSBuild 3.5 Tips and a Small MSBuild 4.0 Wish List

Earlier this week, I spent some quality time porting a moderately complicated build over to MSBUILD 3.5, the version that comes with Visual Studio 2008. There are numerous new features in MSBUILD 3.5 that are quite interesting, especially the wonderful AdditionalProperties and Properties child elements on ItemGroup elements for MSBuild tasks. Now you can create your ItemGroup elements with custom settings

In the following example section of a bigger build file, I’ve got a debugger project that has to be built platform specific since the CLR debugger cannot handle debugging across bitness levels. By adding the AdditionalProperties child element to the DebuggerProjects property group, sets the platform. The BuildDebuggers task, as shown below, is now much easier to understand because you don’t need six different MSBuild tasks calls to build all the combinations. While you will not need this new feature every day, it can simplify your build scripts when you do need it.

<ItemGroup>
<
DebuggerProjects
Include=..DbgDbg-x64.csproj>
<
AdditionalProperties>Platform=x64</AdditionalProperties>
</
DebuggerProjects>
<
DebuggerProjects
Include=..DbgDbg-IA64.csproj>
<
AdditionalProperties>Platform=Itanium</AdditionalProperties>
</
DebuggerProjects>
<
DebuggerProjects
Include=..DbgDbg-x86.csproj>
<
AdditionalProperties>Platform=x86</AdditionalProperties>
</
DebuggerProjects>
</
ItemGroup>
. . .

<Target
Name=BuildDebuggers>

<MSBuild
Projects=@(DebuggerProjects)
             StopOnFirstFailure=true
             Properties=Configuration=Release
             Targets=build

BuildInParallel=true/>
<
MSBuild
Projects=@(DebuggerProjects)
             StopOnFirstFailure=true
             Properties=Configuration=Debug
             Targets=build

BuildInParallel=true/>
</
Target>

. . .

What I was most interested in taking advantage of building projects in parallel. The project I was porting over really didn’t need the parallel builds, but it will be growing much larger so anything I could do to speed up the overall build time down the road would be great. The good news is that it’s quite easy to get your projects set up to use. The big thing I found is that the MSBuild engine can run the actual individual builds in differing orders between runs. That’s not a bad problem, but you need to be aware of it.

Just flipping the /maxcpucount switch on the MSBuild command line enables multiple build support. However, you’ll probably find that your build doesn’t work like I did. The single process version of MSBuild we’ve all been using executes the tasks in top to bottom order. If you have a project or step that others depend on, we all know to use the DependsOnTarget attribute on the subsequent Target elements. That becomes even more important with parallel builds. That attribute is how you ensure the exact order of the Targets gets built. You’ll also want to be explicit about using the BuildInParallel attribute on the MSBuild task itself. In my case, I have a custom MSBuild task that’s part of my build that’s also used later by the build script itself:

<Target
Name=BuildTasksTarget>
<
MSBuild
Projects=@(BuildTaskProjects)
           Properties=Configuration=Debug
           StopOnFirstFailure=true
           Targets=build
           BuildInParallel=false
           UnloadProjectsOnCompletion=true/>
</
Target>

In the MSBuild task for my custom MSBuild task, I specifically set BuildInParallel to false so this Target would be built and the task would wait on the task to complete before continuing.

<

p style=”background:white”>  <Target
Name=BuildAllCode
DependsOnTargets=BuildTasksTarget>
<
MSBuild
Projects=@(CommonProjects);
@(SomeMoreProjects);
@(EvenMoreProjects);
@(WayMoreProjects);

             StopOnFirstFailure=true
             Properties=Configuration=Release
             Targets=build

BuildInParallel=true/>
<
MSBuild
Projects=@(CommonProjects);
@(SomeMoreProjects);
@(EvenMoreProjects);
@(WayMoreProjects);
“”
             StopOnFirstFailure=true
             Properties=Configuration=Debug
             Targets=build

BuildInParallel=true/>
</
Target>

The BuildAllCode Target tells MSBuild to let fly with the magic of parallel builds for both the debug and release builds by setting BuildInParallel to true. In all the other Target elements, I carefully use the DependsOnTargets attribute to ensure I had the various Targets truly spaced in the proper order. Note that to use the BuildInParallel attribute, you’ll have to set the ToolsVersion attribute on the top level Project element to “3.5.”

As an avid MSBuild user, I’m hoping that version 4.0 will finally offer two key features that I think are missing. The first is a simple switch that will evaluate the project file, but not actually build anything. Being forced to execute all the build actions in a project ever time to test it gets very old, very fast. NMAKE has had the /D and /P switches for approximately six eons in Internet time. While you can throw in MessageTasks to do some tracing, MSBuild is still going to require you build everything. I almost shudder to turn on the /verbosity:diagnostic switch to see what my MSBuild scripts are doing. It’s a classic case of way too much tracing with almost zero benefit. We desperately need this “what does MSBuild think it’s going to do” option to make it easier to see exactly what our scripts will execute so we can quickly debug our scripts. There’s nothing more frustrating than waiting for a twenty minute build script to execute over and over and over.

Since I’m on the subject of wishes, what would be even better would be an MSBuild debugger! I really can’t see why we can’t “step” through an MSBuild script like we can with dynamically generated .NET code or batch files (with my beloved 4NT command shell). The Visual Studio/.NET Teams are finished with Visual Studio 2008 so they have to be thinking about features for the next version. Of course, I have no idea how complicated the code is in MSBuild so it’s easy for me to request. However, all we really need to do is to step through the targets themselves. The “variables” window would show the ItemGroups and Properties valid at that target. If those ItemGroups/Properties contains files, the values for each file would be their file time so we could see what MSBuild was determining was the valid reason for invoking that target. By providing us a debugger for MSBuild files, those of us using Team Foundation System and TeamBuild would have a hugely easier time of getting those correct as well. Maybe if we all start requesting an MSBuild debugger over and over we can get it on the feature list!

Stay Informed

Sign up for the latest blogs, events, and insights.

We deliver solutions that accelerate the value of Azure.
Ready to experience the full power of Microsoft Azure?

Atmosera is thrilled to announce that we have been named GitHub AI Partner of the Year.

X