Simon
Simon

Reputation: 34840

how to add files to a projects output files from an MSBuild Task

Given an MSBuild Task that runs in AfterTargets="AfterCompile" and produces some files how do you get those files to be included in the current projects output so that the files will be copied to the bin directory of any projects referencing that project?

Upvotes: 2

Views: 1698

Answers (2)

RobV8R
RobV8R

Reputation: 1076

Thank you, Kirill. That was an excellent answer and it helped me when trying to copy ETW manifest files from a different project's output. Below is the final output.

Since I've simply expanded upon Kirill's answer, I do not expect this answer to be accepted. I post this here in the hope it helps someone else.

<Target Name="IncludeEtwFilesInOutput"
        BeforeTargets="GetCopyToOutputDirectoryItems">

    <PropertyGroup>
        <EtwManifestFile>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)$(OutDir)\My.etwManifest.man'))</EtwManifestFile>
        <EtwResourceFile>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)$(OutDir)\My.etwManifest.dll'))</EtwResourceFile>
    </PropertyGroup>

    <ItemGroup>
        <AllItemsFullPathWithTargetPath Include="$(EtwManifestFile)">
            <TargetPath>My.etwManifest.man</TargetPath>
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </AllItemsFullPathWithTargetPath>
        
        <AllItemsFullPathWithTargetPath Include="$(EtwResourceFile)">
            <TargetPath>My.etwManifest.dll</TargetPath>
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </AllItemsFullPathWithTargetPath>
    </ItemGroup>
</Target>

Upvotes: 1

Kirill Osenkov
Kirill Osenkov

Reputation: 8976

I have no guarantees that this is the right solution but it seems to work:

<Target Name="MyTarget" AfterTargets="AfterCompile">
  <PropertyGroup>
    <MyInput>D:\1.txt</MyInput>
    <MyOutput>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)$(OutDir)\1.txt'))</MyOutput>
  </PropertyGroup>
  <Copy SourceFiles="$(MyInput)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="true" />
  <ItemGroup>
    <AllItemsFullPathWithTargetPath Include="$(MyOutput)">
      <TargetPath>1.txt</TargetPath>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </AllItemsFullPathWithTargetPath>
  </ItemGroup>
</Target>

The relevant logic is here: http://sourceroslyn.io/#MSBuildTarget=GetCopyToOutputDirectoryItems http://sourceroslyn.io/#MSBuildItem=AllItemsFullPathWithTargetPath

Basically we rely on the fact that to determine the list of files to copy from dependent projects MSBuild calls the GetCopyToOutputDirectoryItems target of the dependent projects and uses its output (which is AllItemsFullPathWithTargetPath).

By adding ourselves to AllItemsFullPathWithTargetPath at the last minute we get picked up when a dependent project calls us.

Upvotes: 2

Related Questions