1

I have a custom project system, that uses the standard net sdk targets. During the build, I produce an extra zip file. I'd like this extra file to be included in an output group, so that when I query my projects output groups (from vs) it shows up.

My project file looks like this:

<Project Sdk="Microsoft.NET.Sdk"> 
 ... stuff
  <ItemGroup>
    <PackageReference Include="DnnVsProjectSystem.BuildTools" Version="0.0.5">
      <PrivateAssets>All</PrivateAssets>
    </PackageReference>
  </ItemGroup>
  <Import Project="$(CustomProjectExtensionsPath)DnnVsProjectSystem.targets"/>
</Project>

Notice, I am using the "sdk" attribute, which is a fairly new feature of msbuild.

The PackageReference that you see, is a nuget package that imports a .props and a .targets which augment the build with some custom build tasks. These are the ones that produce the zip file.

I have drilled into the net sdk targets and found this:

<Target Name="AllProjectOutputGroups" DependsOnTargets="&#xD;&#xA;            BuiltProjectOutputGroup;&#xD;&#xA;            DebugSymbolsProjectOutputGroup;&#xD;&#xA;            DocumentationProjectOutputGroup;&#xD;&#xA;            SatelliteDllsProjectOutputGroup;&#xD;&#xA;            SourceFilesProjectOutputGroup;&#xD;&#xA;            ContentFilesProjectOutputGroup;&#xD;&#xA;            SGenFilesOutputGroup" />
  <!--
    This is the key output for the BuiltProjectOutputGroup and is meant to be read directly from the IDE.
    Reading an item is faster than invoking a target.
    -->
  <ItemGroup Condition=" '$(OutputType)' != 'winmdobj' ">
    <BuiltProjectOutputGroupKeyOutput Include="@(IntermediateAssembly->'%(FullPath)')">
      <IsKeyOutput>true</IsKeyOutput>
      <FinalOutputPath>$(TargetPath)</FinalOutputPath>
      <TargetPath>$(TargetFileName)</TargetPath>
      <COM2REG Condition="'$(RegisterForComInterop)'=='true' and '$(OutputType)'=='library'">true</COM2REG>
    </BuiltProjectOutputGroupKeyOutput>
  </ItemGroup>
  <ItemGroup Condition=" '$(OutputType)' == 'winmdobj' ">
    <WinMDExpOutputWindowsMetadataFileItem Include="$(_IntermediateWindowsMetadataPath)" Condition="'$(_IntermediateWindowsMetadataPath)' != ''" />
    <BuiltProjectOutputGroupKeyOutput Include="@(WinMDExpOutputWindowsMetadataFileItem->'%(FullPath)')">
      <IsKeyOutput>true</IsKeyOutput>
      <FinalOutputPath>$(TargetPath)</FinalOutputPath>
      <TargetPath>$(TargetFileName)</TargetPath>
    </BuiltProjectOutputGroupKeyOutput>
  </ItemGroup>

This appears to be the target that is called by VS, when it wants information about output groups.

The problem is, i am not sure how I can get my item included in one of those output groups, as If i just add the item to the item group, in my own targets - my targets are irrelevent at this point, as they are not included in this dependency chain.

I also can't override any of the targets, because, as i'm using the sdk attribute, it looks like the sdk targets will always be imported last, overwriting anything that I declare.

Any guidance much appreciated.

Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467
Darrell
  • 1,905
  • 23
  • 31
  • I think your title should be '... in *BuiltProjectOutputGroupKeyOutput*', not *BuiltProjectOutputGroup*. The latter is a Target. Maybe look up it's code (and from the other dependencies) as well: some targets use a property for their DependOnTargets so you can set the property to one of your targets and then you're set. – stijn Apr 08 '17 at 16:23
  • Thanks @stijn, I eventually got there, I found that the content output group target uses a property for its dependson, so I managed to add my target to that. – Darrell Apr 08 '17 at 21:23

1 Answers1

1

If your only concern is to hook into the target or its dependency chain, I suggest using msbuild's BeforeTargets functionality:

<Target Name="IncludeMyCustomOutputGroup" BeforeTargets="AllProjectOutputGroups" DependsOnTargets="ResolveMyCustomPropertiesAndItems">
  <ItemGroup>
    <!-- Assuming @(MyCustomOutput) items are generated by your ResolveMyCustomPropertiesAndItems target, or just add anything else -->
    <BuiltProjectOutputGroupKeyOutput Include="@(MyCustomOutput->'%(FullPath)')">
      <IsKeyOutput>true</IsKeyOutput>
      <FinalOutputPath>$(TargetPath)</FinalOutputPath>
      <TargetPath>$(TargetFileName)</TargetPath>
    </BuiltProjectOutputGroupKeyOutput>
  </ItemGroup>
</Target>
Martin Ullrich
  • 94,744
  • 25
  • 252
  • 217
  • Thanks, I managed to find an alternative way, but i'll accept this answer! – Darrell Apr 08 '17 at 21:28
  • - and the alternative way, involved discovering that certain output group targets have a corrseponding "dependson" property. You can hook into them by overriding this depends on property with one that includes your own target, and then in that target, you can include additional items in that output group. For example, the Content Output group uses this mechanism. Not sure if they all do, however if they didn't, then pretty sure your answer would still work. – Darrell Apr 08 '17 at 21:33