Skip to content

Commit f985d3f

Browse files
committed
Dynamically Pack MVVM SourceGen project outputs
Previously, static output path to the MVVM SourceGen assembly was used to pack the MVVM project. This leads to error when OutputPath was updated dynamically when testing or in forks. So, here, we'll update the build so that the SourceGen build outputs will be dynamically packed.
1 parent 2eb009b commit f985d3f

File tree

3 files changed

+71
-9
lines changed

3 files changed

+71
-9
lines changed

CommunityToolkit.Mvvm.SourceGenerators/CommunityToolkit.Mvvm.SourceGenerators.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@
2626
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" PrivateAssets="All" Pack="false" />
2727
</ItemGroup>
2828

29+
<Import Project="$(BuildToolsDirectory)Community.Toolkit.GetBuildOutputs.targets" />
30+
2931
</Project>

CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.csproj

+22-9
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,33 @@
5050
</ItemGroup>
5151

5252
<!-- Source generator project reference for packing -->
53-
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
53+
<ItemGroup>
5454
<ProjectReference Include="..\CommunityToolkit.Mvvm.SourceGenerators\CommunityToolkit.Mvvm.SourceGenerators.csproj"
5555
ReferenceOutputAssembly="false" />
5656
</ItemGroup>
5757

58+
<!-- Use 'GenerateNuspecDependsOn' extensibility point to include build assets into our package -->
59+
<PropertyGroup>
60+
<GenerateNuspecDependsOn>GetSourceGenBuildOutputs</GenerateNuspecDependsOn>
61+
</PropertyGroup>
62+
5863
<!--
59-
Pack the source generator to the right package folder.
60-
TODO: Find a way to get the analyzer project's build output path,
61-
and include using NuGet Pack's extensibility target points.
64+
Pack the source generator build outputs to the correct package folder for it to be used as an analyzer.
65+
The following target uses 'GenerateNuspecDependsOn' extensibility point to pack the build assets
66+
by using our custom 'GetBuildOutputs' target imported within the target project.
6267
-->
63-
<ItemGroup Label="Package">
64-
<None Include="..\CommunityToolkit.Mvvm.SourceGenerators\bin\$(Configuration)\netstandard2.0\CommunityToolkit.Mvvm.SourceGenerators.dll"
65-
PackagePath="analyzers\dotnet\roslyn4.0\cs"
66-
Pack="true" Visible="false" />
67-
</ItemGroup>
68+
<Target Name="GetSourceGenBuildOutputs" AfterTargets="_CalculateInputsOutputsForPack">
69+
<MSBuild
70+
Projects="@(ProjectReference->WithMetadataValue('ReferenceOutputAssembly', 'false'))"
71+
Targets="GetBuildOutputs">
72+
<Output TaskParameter="TargetOutputs" ItemName="SourceGenBuildOutput" />
73+
</MSBuild>
74+
<ItemGroup>
75+
<!-- Include SourceGen Build Outputs in the package -->
76+
<_PackageFiles Include="@(SourceGenBuildOutput)" PackagePath="analyzers\dotnet\roslyn4.0\cs" />
77+
<!-- Use the 'FinalOutputPath' metadata to mark the inputs thus enabling incremental builds -->
78+
<NuGetPackInput Include="@(SourceGenBuildOutput->'%(FinalOutputPath)')" />
79+
</ItemGroup>
80+
</Target>
6881

6982
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<Project>
2+
3+
<!-- We depend on these Common Targets that gathers various Build Outputs of the included project -->
4+
<PropertyGroup>
5+
<_GetBuildOutputsDependsOn>BuiltProjectOutputGroup;DocumentationProjectOutputGroup</_GetBuildOutputsDependsOn>
6+
<_GetBuildOutputsDependsOn Condition="'$(IncludeSymbols)' != 'false'">$(_GetBuildOutputsDependsOn);DebugSymbolsProjectOutputGroup</_GetBuildOutputsDependsOn>
7+
<_GetBuildOutputsDependsOn Condition="'$(IncludeSatelliteAssemblies)' != 'false'">$(_GetBuildOutputsDependsOn);SatelliteDllsProjectOutputGroup</_GetBuildOutputsDependsOn>
8+
</PropertyGroup>
9+
10+
<!-- Check for 'TargetFramework' input before proceeding. -->
11+
<Target Name="_CheckTargetFrameworkInput"
12+
DependsOnTargets="_CheckForInvalidConfigurationAndPlatform"
13+
Condition="'$(TargetFramework)' == ''">
14+
<Error Code="NCTDEV01" Text="The 'GetBuildOutputsPerTarget' target is meant to output the build items per 'TargetFramework'. Please call the target with a non-empty 'TargetFramework'."/>
15+
</Target>
16+
17+
<!--
18+
Gathers various Build Outputs from included Project per 'TargetFramework'.
19+
This target is called in by the 'GetBuildOutputs' target to combine build outputs from all 'TargetFrameworks'.
20+
-->
21+
<Target Name="GetBuildOutputsPerTarget"
22+
DependsOnTargets="_CheckTargetFrameworkInput;$(_GetBuildOutputsDependsOn)"
23+
Returns="@(BuildOutputPerTarget)">
24+
<ItemGroup>
25+
<BuildOutputPerTarget Include="@(BuiltProjectOutputGroupOutput);@(DocumentationProjectOutputGroupOutput)"/>
26+
<BuildOutputPerTarget Include="@(DebugSymbolsProjectOutputGroupOutput)" Condition="'$(IncludeSymbols)' != 'false'"/>
27+
<BuildOutputPerTarget Include="@(SatelliteDllsProjectOutputGroupOutput)" Condition="'$(IncludeSatelliteAssemblies)' != 'false'"/>
28+
<BuildOutputPerTarget Update="@(BuildOutputPerTarget)" TargetFramework="$(TargetFramework)"/>
29+
</ItemGroup>
30+
</Target>
31+
32+
<!--
33+
Gathers various Build Outputs from this Project across 'TargetFrameworks'.
34+
This target is called in the parent project to pack into a package.
35+
-->
36+
<Target Name="GetBuildOutputs"
37+
DependsOnTargets="_GetTargetFrameworksOutput"
38+
Returns="@(BuildOutput)">
39+
<MSBuild
40+
Projects="$(MSBuildProjectFullPath)"
41+
Targets="GetBuildOutputsPerTarget"
42+
Properties="TargetFramework=%(_TargetFrameworks.Identity)">
43+
<Output TaskParameter="TargetOutputs" ItemName="BuildOutput" />
44+
</MSBuild>
45+
</Target>
46+
47+
</Project>

0 commit comments

Comments
 (0)