MsBuild and dealing with (orphaned) target outputs

35 Views Asked by At

I'm somewhat stumped on how to deal with "outdated" msbuild output artifacts.

Basically I have written a target which creates aggregates over input files.


    <Target Name="AggregateFoos"
            Inputs="@(Foo)"
            Outputs="@(Foo->%'AggregationTargetMetadata')">
                        
        <WriteLinesToFile File="%(Foo.AggregationTargetMetadata)" Lines="@(Foo)" Overwrite="true" />

    </Target>

This is nicely processed whenever a change happens to any Foo's AggregationTargetMetadata the target aggregate file (and its former target) get correctly updated. All except when a file was the last member for an aggregate.

Basically with inputs X, Y & Z mapped X -> A , Y -> A, Z -> B changing Y -> B updates both A & Bas expected. Changing Z -> A also correctly updates A - however B forever stays in it's "old" orphaned state.

My understanding is that is the intended behavior, since B is now no longer a member (directly or transitively) of any item of the project.

This would be semi-okay-ish if the aggregates were only dynamically slipped into the build process. Sadly they may get used as design time resources for other things, so typically the aggregates would actually be project items themselves and the whole aggregation logic is only there to update the aggregate contents.

Now... How would I go about identifying "orphaned" aggregates?

I think I've come up with a solution where I can extend my aggregation to also create indicator files, do another (non incremental) Target after the aggregation and then use a custom CodeFragment Task (or even pre built Assembly based one) to check for markers where there is no source mapping...


    <Target Name="AggregateFoos"
            Inputs="@(Foo)"
            Outputs="@(Foo->%'AggregationTargetMetadata');@(Foo->$(IntermediateBuildPath)Foo\%'AggregationTargetMetadata'.foo)">
                        
        <WriteLinesToFile File="%(Foo.AggregationTargetMetadata)" Lines="@(Foo)" Overwrite="true" />

        <Touch AlwaysCreate="true" 
               Files="$(IntermediateBuildPath)Foo\%(Foo.AggregationTargetMetadata).foo" />

    </Target>


    <Target Name="FooOrphanLookup"
            AfterTargets="AggregateFoos">

        <MagicLookups CurrentFoosAndMapping="@(Foo)"
                      Markers="$(IntermediateBuildPath)Foo\**.foo" />

        <!-- MagicLookups would look through all Markers and give at least 
             a warning if there is not a Foo with a corresponding AggregationTargetMetadata -->
    </Target>

All in all, that feels quite frankensteined. Is there a simpler approach?

0

There are 0 best solutions below