MsBuild item evaluation surprise

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /customers/9/2/f/appelgren.org/httpd.www/blog/wp-content/plugins/wp-syntax/wp-syntax.php on line 383 Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /customers/9/2/f/appelgren.org/httpd.www/blog/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Solved a problem with a build script last week. I had somehow caused the build to under some conditions take a very long time to start with heavy disk IO. After reviewing some recent changes I found the cause.

I had a ItemGroup that looked something like the following.

<ItemGroup Condition="'$(PathProperty)'!=''">
    <SomeItem Include="$(PathProperty)/**/*.dll"/>
</ItemGroup>

Apparently MsBuild evaluates all ItemGroups even if the condition of the group or item evaluates to false. The result is just discarded if the condition evaluates to false. So the item above included all dll files on the entire hard drive when PathProperty was not set. By trial and error I found out that the condition of Choose elements are evaluated before the items they contain.

So to speed things up I changed the above to the following.

<Choose>
    <When Condition="'$(PathProperty)'!=''">
        <ItemGroup>
            <SomeItem Include="$(PathProperty)/**/*.dll"/>
        </ItemGroup>
    </When>
</Choose>

Is this behaviour obvious to everyone else? Couldn’t find anything about it while reading the conditions documentation nor the documentation on items and properties on MSDN.