I have a Target
which I want to run once if none of the files in my ItemGroup
exist.
<ItemGroup>
<Foo Include="a.txt;b.txt;c.txt" />
</ItemGroup>
<Target Name="Bar" Condition="?">
My question is what is what to put in the '?'.
You can use another Target to go through the file list (what Targets are good at!) and leave a result in a Property. Make a wrapper Target that is dependent on the tester Target and on Bar. Bar has a condition that uses the mechanism set by the first target.
Note that the global property set within a task is not seen until that task has finished, so the idiom is to wrap the thing producing the result and the thing consuming the result as dependents of an empty task.
I think you need to also make the tester a dependency of Bar as well, to make sure it gets the order correct.
Something like this:
<Target Name="TestLoop" Outputs="%(Foo.Identity)">
<PropertyGroup>
<Tested Condition="Exists(%(Foo.Identity))">Present</Tested>
</PropertyGroup>
</Target>
After TestLoop is triggered, the Property Tested will be set to "Present" if and only if at least one of the files is present. That is, it codes a looping logical OR.
Now if you use this as a dependency:
<Target Name="Wrapper" DependsOnTargets="TestLoop;Bar" />
then you can have Bar look at the state left by TestLoop. Assuming they are executed in the correct order, not in parallel! To ensure that, also make TestLoop a prerequisite for Bar, and the build engine will determine the needed sequence and know not to try doing Bar until after TestLoop is done.
Oh, and Wrapper is the target to ask for. As described above, if you ask for Bar directly it will not see the property update (I think). So you might name them to make the Wrapper the exposed Bar, and your Bar an internal Bar_helper.