Gotcha: MSBuild nested loops (double batching)
I admit I didn’t get it on my first, quick, reading of “Inside the Microsoft Build Engine: Using MSBuild and Team Foundation Build” that MSBuild batching is somewhat counter-intuitive.
I needed to have a nested loop in my script, like this pseudo code:
foreach (solution in solutionItemGroup) {
foreach (configuration in solution.Configurations) {
build solution's package using configuration
}
}
It turned out that a naive solution doesn’t work: two different ItemGroup in the same Task are interpreted by MSBuild, like the following pseudo code:
foreach (solution in solutionItemGroup) {
build solution's package using configuration
}
foreach (configuration in solution.Configurations) {
build solution's package using configuration
}
The solution I found is to work at the target level using a local property, an MSBuild 3.5 feature. MSBuild creates a first batch for the property, the outer loop, the a second, nested batch for the task at hand; some real code may better explain this.
<Target Name="DeployToLocalServer" DependsOnTargets="MyResolveSolutionPaths">
<PropertyGroup>
<CurrentConfiguration>%(ConfigurationToBuild.FlavorToBuild)</CurrentConfiguration>
</PropertyGroup>
<MSBuild Projects="%(LocalSolutionToBuild.RootDir)%(LocalSolutionToBuild.Directory)%(LocalSolutionToBuild.Filename).Deployment.proj"
Targets="Deploy"
Properties="Configuration=$(CurrentConfiguration);OutDir=$(OutDir)"
StopOnFirstFailure="$(StopOnFirstFailure)"
ContinueOnError="false"
Condition="'%(LocalSolutionToBuild.Deploy)'=='true'"
/>
</Target>
The CurrentConfiguration property batches (loops) on the ConfigurationToBuild; this property is used in the MSBuild task as a simple value ($ sign), and the interpreter over all its possible values before evaluating the batches in the task.
Happy Building!
Comments
Anonymous
January 13, 2011
This approach does not seem to work for me (in TFS 2010). Here I have outlined an approach which does work kennyknecht.blogspot.com/.../nested-itemgroups-in-msbuild.htmlAnonymous
July 22, 2014
So if we have a project with 4 Release Configurations and 3 Debug configurations, that loop is supposed to do for each Release and Debug. Can you please provide more detailed example? Thanks