Thursday, October 23, 2008

MSBuild ItemGroup element issue

So you just moved from NAnt to MSBuild and put together the following MSBuild script to copy files (just like in my case)

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<
PropertyGroup>
<
Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<
WSPDir>.\release</WSPDir>
</
PropertyGroup>
<
ItemGroup>
<
CompiledBinaries Include=".\bin\debug\*.dll" />
<
ProjectReferences Include="$(WSPDir)\**\*.*proj"/>
</
ItemGroup>

<
Target Name="Build">
<
MSBuild Projects="@(ProjectReferences)" Targets="Build"
        Properties="Configuration=$(Configuration)">
<
Output TaskParameter="TargetOutputs" ItemName="AssembliesBuiltByChildProjects"/>
</
MSBuild>
</
Target>
<
Target Name="Release" DependsOnTargets="Build">
<
Copy SourceFiles="@(CompiledBinaries)"
DestinationFolder="$(WSPDir)"/>
</
Target>
</
Project>
 
So I have an Item defined to generate a file list from the Bin\Debug folder
 <CompiledBinaries Include=".\bin\debug\*.dll" />

And then use the Copy command to copy the dlls
 <Copy SourceFiles="@(CompiledBinaries)"
DestinationFolder="$(WSPDir)"/>

But you will find that no dlls were copied from the bin folder, reason being that 
@(CompiledBinaries) is empty. This is because the content for the CompiledBinaries item 
is generated before running the actual targets.

 


The trick is to move the item creation into a Target by using a CreateItem task. So the following will create an item on the fly when the Target is executed.

<CreateItem Include="$(WSPDir)bin\**\*.*" >
<
Output TaskParameter="Include" ItemName="CompiledBinaries"/>
</
CreateItem>

 


So here is how the final working script will look like:



<
Projectxmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <
PropertyGroup>
        <
ConfigurationCondition=" '$(Configuration)' == '' ">Debug</Configuration>
        <
WSPDir>.\release</WSPDir>
    </
PropertyGroup>
    <
ItemGroup>
        <
ProjectReferences Include="$(WSPDir)\**\*.*proj"/>
    </
ItemGroup>

    <
Target Name="Build">
        <
MSBuild Projects="@(ProjectReferences)" Targets="Build" Properties="Configuration=$(Configuration)">
            <
Output    TaskParameter="TargetOutputs" ItemName="AssembliesBuiltByChildProjects"/>
        </
MSBuild>
    </
Target>
    <
Target Name="Release" DependsOnTargets="Build">
        <
CreateItem Include="$(WSPDir)bin\**\*.dll" >
            <
Output TaskParameter="Include" ItemName="CompiledBinaries"/>
        </
CreateItem>
        <
Copy SourceFiles="@(CompiledBinaries)"
       DestinationFolder="$(WSPDir)"/>
    </
Target>
</
Project>

No comments: