.NET Framework Developer Center >
.NET Development Forums
>
MSBuild
>
Duplicated files are copied to the target directory
Duplicated files are copied to the target directory
- 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
- 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>
.........- Marked As Answer byFeng ChenModeratorTuesday, June 03, 2008 6:34 AM
All Replies
- 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>
.........- Marked As Answer byFeng ChenModeratorTuesday, June 03, 2008 6:34 AM
- 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 - 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?


