We got a great question today from an internal team at Microsoft that is working on some custom build process for their specific application:

We have a project whose output is both libraries and header files. What is the best way to return those outputs to the rest of the build process? How can we indicate they are different "types"?

Let's assume the project in question is getting called via an MSBuild task. What we want is to be able to say something like this:

<MSBuild Projects="outs.proj" Targets="Build">
     <Output ItemName="Outputs" TaskParameter="TargetOutputs"/>
</MSBuild>

TargetOutputs should contain all of the libraries and headers that were generated. But how do you tell them apart? Kieran replied and pointed out that this is an excellent example of the power of metadata.

When a task in outs.proj actually generates the output (either header or library) it also tacks on special metadata. The metadata can be anything, but in this example the headers have the “type” metadata set to “header” and the libraries have it set to “library”. The code to do this looks something like:

this.taskOutput[0].SetMetadata(“type”, “header”);

where taskOutput is an array of ITaskItem objects. The great thing about this approach is that you can combine it with batching later in your build process. Let’s say later on you want to print out the list of headers that were generated. The line in the MSBuild file would look like this:

<Message Text="Returned Headers: @(Outputs)" Condition="'%(Outputs.Type)' == 'Header'" />

The best part is that metadata will follow the outputs through the entire build process, not just at batch time. If the outputs in this scenario get passed in to some other task down the line, that task in its implementation can use the object model to query for the metadata and do interesting things.

[ Author: Neil Enns ]