1
votes

I have an msbuild script that performs some copy operations. It actually does a whole boat load of copies and other things, including messages, deletes, removedir, its own ItemGroup sections, etc.

I need to duplicate this target but only 1%-ish of its XML is different. At the moment, it's just adding 1 additional task. I don't want to copy & paste the whole target, I'd rather set up a common target to execute the tasks common to both, and put the specialized additions in a separate target. More or less I just want msbuild to copy/paste the contents of the XML into each section for me, behaviorally.

Here is an example:

<Target Name="Copy Stuff">
        <Copy SourceFiles="@(FILES_STUFF1)"   DestinationFolder="$(BASE_DIR)\stuff1"/>
        <Copy SourceFiles="@(FILES_STUFF2)"   DestinationFolder="$(BASE_DIR)\stuff2"/>
        <Copy SourceFiles="@(FILES_STUFF3)"   DestinationFolder="$(BASE_DIR)\stuff3"/>
</Target>

I then need to create a 2nd target that only adds 1 extra Copy:

<Target Name="Copy Stuff More">
        <Copy SourceFiles="@(FILES_STUFF1)"   DestinationFolder="$(BASE_DIR)\stuff1"/>
        <Copy SourceFiles="@(FILES_STUFF2)"   DestinationFolder="$(BASE_DIR)\stuff2"/>
        <Copy SourceFiles="@(FILES_STUFF3)"   DestinationFolder="$(BASE_DIR)\stuff3"/>
        <Copy SourceFiles="@(FILES_STUFF4)"   DestinationFolder="$(BASE_DIR)\stuff4"/>
</Target>

How can I centralize the duplicated XML pieces? I read a little about msbuild batching but it makes absolutely zero sense to me. I am not confident it will solve my problem. All of the examples of it I've seen have been for Message logs, but I'm doing far more than that.

2

2 Answers

1
votes

You don't really need any batching here, instead you can just make one target depend on the other, see Target documentation. This will invoke the dependent target before the actual target:

<Target Name="Copy Stuff">
        <Copy SourceFiles="@(FILES_STUFF1)" DestinationFolder="$(BASE_DIR)\stuff1"/>
        <Copy SourceFiles="@(FILES_STUFF2)" DestinationFolder="$(BASE_DIR)\stuff2"/>
        <Copy SourceFiles="@(FILES_STUFF3)" DestinationFolder="$(BASE_DIR)\stuff3"/>
</Target>

<Target Name="Copy Stuff More" DependsOnTargets="Copy Stuff">
        <Copy SourceFiles="@(FILES_STUFF4)" DestinationFolder="$(BASE_DIR)\stuff4"/>
</Target>
1
votes

Create a target file and use Import to import target in your project file.

Your target file is something like this:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <MyTargetDependsOn>
        </MyTargetDependsOn>
    </PropertyGroup>
    <Target Name="MyTarget" Condition="$(MyTargetCondition)" DependsOnTargets="$(MyTargetDependsOn)">
        <Copy SourceFiles="@(FILES_STUFF1)"   DestinationFolder="$(BASE_DIR)\stuff1"/>
        <Copy SourceFiles="@(FILES_STUFF2)"   DestinationFolder="$(BASE_DIR)\stuff2"/>
        <Copy SourceFiles="@(FILES_STUFF3)"   DestinationFolder="$(BASE_DIR)\stuff3"/>
    </Target>
</Project>

Your project file or you secondary target file is something like this:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Import Project="MyTarget.targets"/>
    <PropertyGroup>
        <MyTargetDependsOn>
            $(MyTargetDependsOn);
            MyTargetHook
        </MyTargetDependsOn>
    </PropertyGroup>
    <Target Name="MyTargetHook">
        <Copy SourceFiles="@(FILES_STUFF4)"   DestinationFolder="$(BASE_DIR)\stuff4"/>
    </Target>
</Project>