.NET Framework Developer Center > .NET Development Forums > MSBuild > Duplicated files are copied to the target directory
Ask a questionAsk a question
 

AnswerDuplicated files are copied to the target directory

  • Tuesday, May 22, 2007 9:57 AMGeorgeUsesMSBuild Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I have one project that includes binary file (native dll) intended to be copied to the target directory. This file has "Copy to Output Directory = Copy if newer". This project is used by a lot of other projects. During full build I get tens of messages like:

    Copying file from "<absolute file path>" to "bin\Debug\<file name>".
    Copying file from "<absolute file path>" to "bin\Debug\<file name>".
    Copying file from "<absolute file path>" to "bin\Debug\<file name>".
    Copying file from "<absolute file path>" to "bin\Debug\<file name>".

    .....................

    it copies the same file to the same place many times for each project that directly or indirectly references the project. This requires a lot of time and I had to fix Microsoft.Common.targets. This is what I ended up with:

    <!--
    ============================================================
    _CopyOutOfDateSourceItemsToOutputDirectory

    Copy files that have the CopyToOutputDirectory attribute set to 'PreserveNewest'.
    ============================================================
    -->
    <Target
    Name="_CopyOutOfDateSourceItemsToOutputDirectory"
    Condition=" '@(_SourceItemsToCopyToOutputDirectory)' != '' "
    Inputs="@(_SourceItemsToCopyToOutputDirectory)"
    Outputs="@(_SourceItemsToCopyToOutputDirectory->'$(OutDir)%(TargetPath)')">

    <!-- Remove duplicates. -->
    <RemoveDuplicates Inputs="@(_SourceItemsToCopyToOutputDirectory)">
    <Output TaskParameter="Filtered" ItemName="_SourceItemsToCopyToOutputDirectoryFiltered"/>
    </RemoveDuplicates>

    <!--
    Not using SkipUnchangedFiles="true" because the application may want to change
    one of these files and not have an incremental build replace it.
    -->
    <Copy
    SourceFiles = "@(_SourceItemsToCopyToOutputDirectoryFiltered)"
    DestinationFiles = "@(_SourceItemsToCopyToOutputDirectoryFiltered->'$(OutDir)%(TargetPath)')">

    <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>

    </Copy>

    </Target>

    <!--
    ============================================================
    _CopyOutOfDateSourceItemsToOutputDirectoryAlways

    Copy files that have the CopyToOutputDirectory attribute set to 'Always'.
    ============================================================
    -->
    <Target
    Name="_CopyOutOfDateSourceItemsToOutputDirectoryAlways"
    Condition=" '@(_SourceItemsToCopyToOutputDirectoryAlways)' != '' ">

    <!-- Remove duplicates. -->
    <RemoveDuplicates Inputs="@(_SourceItemsToCopyToOutputDirectoryAlways)">
    <Output TaskParameter="Filtered" ItemName="_SourceItemsToCopyToOutputDirectoryAlwaysFiltered"/>
    </RemoveDuplicates>

    <!--
    Not using SkipUnchangedFiles="true" because the application may want to change
    one of these files and not have an incremental build replace it.
    -->
    <Copy
    SourceFiles = "@(_SourceItemsToCopyToOutputDirectoryAlwaysFiltered)"
    DestinationFiles = "@(_SourceItemsToCopyToOutputDirectoryAlwaysFiltered->'$(OutDir)%(TargetPath)')">

    <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>

    </Copy>

    </Target>


    Is it supposed to be a defect?

Answers

  • Tuesday, May 22, 2007 1:41 PMGeorgeUsesMSBuild Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    This solution even better because it reduces memory consumption

        <Target
            Name="GetCopyToOutputDirectoryItems"
            Outputs="@(AllItemsFullPathWithTargetPath)"
            DependsOnTargets="AssignTargetPaths;_SplitProjectReferencesByFileExistence">

            <!-- Get items from child projects first. -->
            <MSBuild
                Projects="@(_MSBuildProjectReferenceExistent)"
                Targets="GetCopyToOutputDirectoryItems"
                Properties="%(_MSBuildProjectReferenceExistent.SetConfiguration); %(_MSBuildProjectReferenceExistent.SetPlatform)"
                Condition="'@(_MSBuildProjectReferenceExistent)'!=''">

                <Output TaskParameter="TargetOutputs" ItemName="_AllChildProjectItemsWithTargetPathNotFiltered"/>

            </MSBuild>

            <!-- Remove duplicates. -->
            <RemoveDuplicates Inputs="@(_AllChildProjectItemsWithTargetPathNotFiltered)">
                <Output TaskParameter="Filtered" ItemName="_AllChildProjectItemsWithTargetPath"/>
            </RemoveDuplicates>

            <!-- Target outputs must be full paths because they will be consumed by a different project. -->
            <CreateItem
                Include="@(_AllChildProjectItemsWithTargetPath->'%(FullPath)')"
                Condition="'%(_AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(_AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"
                    >
                <Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
                <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
                        Condition="'%(_AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
                <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
                        Condition="'%(_AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
            </CreateItem>
    .........

All Replies

  • Tuesday, May 22, 2007 1:41 PMGeorgeUsesMSBuild Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    This solution even better because it reduces memory consumption

        <Target
            Name="GetCopyToOutputDirectoryItems"
            Outputs="@(AllItemsFullPathWithTargetPath)"
            DependsOnTargets="AssignTargetPaths;_SplitProjectReferencesByFileExistence">

            <!-- Get items from child projects first. -->
            <MSBuild
                Projects="@(_MSBuildProjectReferenceExistent)"
                Targets="GetCopyToOutputDirectoryItems"
                Properties="%(_MSBuildProjectReferenceExistent.SetConfiguration); %(_MSBuildProjectReferenceExistent.SetPlatform)"
                Condition="'@(_MSBuildProjectReferenceExistent)'!=''">

                <Output TaskParameter="TargetOutputs" ItemName="_AllChildProjectItemsWithTargetPathNotFiltered"/>

            </MSBuild>

            <!-- Remove duplicates. -->
            <RemoveDuplicates Inputs="@(_AllChildProjectItemsWithTargetPathNotFiltered)">
                <Output TaskParameter="Filtered" ItemName="_AllChildProjectItemsWithTargetPath"/>
            </RemoveDuplicates>

            <!-- Target outputs must be full paths because they will be consumed by a different project. -->
            <CreateItem
                Include="@(_AllChildProjectItemsWithTargetPath->'%(FullPath)')"
                Condition="'%(_AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(_AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"
                    >
                <Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
                <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
                        Condition="'%(_AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
                <Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
                        Condition="'%(_AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
            </CreateItem>
    .........

  • Tuesday, June 03, 2008 6:28 AMArcJeremy Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I encounted the same problem and George's solution resolves it. 

    Not sure but it sounds like a MSBUILD bug and hope to hear voice from MS about this.


    ArcJeremy
    • Edited byArcJeremy Wednesday, June 04, 2008 8:42 AMclear
    • Edited byArcJeremy Wednesday, June 04, 2008 8:45 AMclear
    •  
  • Monday, May 04, 2009 10:14 PMLou Machado Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I've got the same issue and I'm on VS 2008 SP1 using TeamBuild.  Anyone put in a bug for this and had a response from Microsoft?