tags:

views:

1359

answers:

4

What is the difference between creating an item inside a target like this:

<Target Name="DoStuff">
    <CreateItem Include="@(IntermediateAssembly)" >
        <Output TaskParameter="Include" ItemName="FileWrites"/>
    </CreateItem>
</Target>

and like this:

<Target Name="DoStuff">
    <ItemGroup>
        <FileWrites Include="@(IntermediateAssembly)" />
    </ItemGroup>
</Target>

When would you use one or the other and why?

+6  A: 

In versions of MSBuild prior to 3.5 you could not define properties or items inside of targets (like in your second example). So a task was used instead (CreateItem and CreateProperty)

If you are using ToolsVersion 3.5 then you don't need to use CreateItem anymore (though you still can if you prefer).

In the end they both create the item the same, with the same scope. Using the second syntax is more readable and setting up custom meta data is much easier (in my opinion).

NOTE: The 3.5 version of MSBuild is installed with .NET 3.5. Though you need to define ToolsVersion="3.5" in the Project tag of your MSBuild file to use 3.5 features.

In case you are wondering, I got most of this info from the book Inside the Microsoft® Build Engine: Using MSBuild and Team Foundation Build which I really liked (but am not affiliated with in any way).

Vaccano
Thank you very much, this is just what i wanted to know!I'll have to check out that book.
Cipher
Yeah that book is great, I love it :) :) :) Thanks for the rec.
Sayed Ibrahim Hashimi
+3  A: 

I dont think the answer accepted has defined the difference.

The difference is:

  • ItemGroup is evaluated when the MSBuild script is loaded.
  • CreateItem is evaluated when the Target is executed

This can lead to different values of the Item within the script.

Take the example of a Task that does something with a all the files that match "*.txt" in a directory. If your MSBuild script is loaded in visual studio, only the files that existed when VS started will be in the Item if you use ItemGroup.

If you use CreateItem - it will do a search for all *.txt files when the target is executed.

Adam
The asker indicates that both are being called from inside a target. From your answer, it looks like you are thinking in pre MSBuild 3.5 terms. (When ItemGroup could not be placed inside a target). If ItemGroup is inside a target it is just as dynamic as if it were declared via CreateItem. (ie it is evaluated when the target is run.) (See Page 51 of "Inside the Microsoft Build Engine: Using MSBuild and Team Foundation Build" for a reference (or just try it out)).
Vaccano
+7  A: 

CreateItem and CreateProperty are obsoleted in MSBuild 3.5 (though will always continue to work, of course). It was pretty obvious we needed the same familiar syntax for ItemGroup and PropertyGroup to work inside targets.

But ItemGroup inside a target has some special extra powers. It can modify items: for example, this will add true to all items in Resources list that have a metadata named Primary with value of true; only if there isn't already Copy metadata:

<ItemGroup>
  <Resources Condition=" '%(Primary)' == 'true' ">
    <Copy Condition=" '%(Copy)' == '' ">true</Copy>
  </Resources>
</ItemGroup>

One other magic power: you can now remove items from a list. This example will remove all items from the Resources list that have metadata Type with value Bitmap:

<ItemGroup>
  <Resources Condition=" '%(Type)'=='Bitmap' " Remove="@(Resources)"/>
</ItemGroup>

These magic powers only work inside at present, not outside.

For full details of this stuff, I highly recommend Sayed Hashimi's book on MSBuild. It's easily found on Amazon.

Dan -- msbuild team.

A: 

As an additional info for others passing here: The Build-Engine that contains an API to construct MSBuild projects does not support adding ItemGroups the new way to a Target. Here you WILL have to use the old-fashioned way.

flq