Skip to content

Commit

Permalink
Split authoring vs runtime targets
Browse files Browse the repository at this point in the history
Each consuming package will use SL as a private development dependency exclusively, but gets aids via its (authoring) targets to properly pack and ship the dependencies and run-time targets.

The targets need to be included from buildTransitive targets since analyzers are always included (see dotnet/sdk#1212) and transitive (see NuGet/Home#6279), so the build properties need to be present always.
  • Loading branch information
kzu committed Aug 10, 2023
1 parent 99416ff commit 8a2910f
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 85 deletions.
7 changes: 6 additions & 1 deletion src/Package/Devlooped.SponsorLink.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
<!-- These props are intended for SponsorLink consumption by package authors -->
<Project>

<PropertyGroup>
<SponsorLinkTargets>$(MSBuildThisFileDirectory)Devlooped.SponsorLink.targets</SponsorLinkTargets>
<!-- SL package root directory -->
<SponsorLinkRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..'))</SponsorLinkRoot>

<!-- Consuming packages can use this property to pack and ship this required targets file -->
<SponsorLinkTargets>$(SponsorLinkRoot)\tools\Devlooped.SponsorLink.targets</SponsorLinkTargets>
</PropertyGroup>

</Project>
88 changes: 11 additions & 77 deletions src/Package/Devlooped.SponsorLink.targets
Original file line number Diff line number Diff line change
@@ -1,98 +1,32 @@
<!-- These targets are intended for SponsorLink consumption by package authors,
to simplify packing and distribution. It's not used by end users of the
sponsorable package. -->
<Project>

<PropertyGroup>
<BuildingInsideVisualStudio>false</BuildingInsideVisualStudio>
<BuildingInsideVisualStudio Condition="$(IDEA_INITIAL_DIRECTORY) != '' or $(RESHARPER_FUS_BUILD) != '' or $(RESHARPER_FUS_SESSION) != ''">true</BuildingInsideVisualStudio>
<!-- Analyzer projects using DebugRoslynComponent launch profile and IsRoslynComponent can
set this property to true in the launched project so that SponsorLink does not skip the
checks even if DesignTimeBuild is true. -->
<DebugSponsorLink Condition="'$(DebugSponsorLink)' == ''" />
</PropertyGroup>

<ItemGroup>
<!-- By adding these items in .targets, we make it harder to break from tweaks in the project file -->
<CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="SourceItemType" />
<CompilerVisibleItemMetadata Include="Analyzer" MetadataName="NuGetPackageId" />

<CompilerVisibleProperty Include="DesignTimeBuild" />
<CompilerVisibleProperty Include="BuildingInsideVisualStudio" />
<CompilerVisibleProperty Include="MSBuildProjectFullPath" />

<CompilerVisibleProperty Include="DebugSponsorLink" />
</ItemGroup>

<Target Name="CollectSponsorLinkReference" BeforeTargets="GenerateMSBuildEditorConfigFileShouldRun">
<ItemGroup>
<AdditionalFiles Include="@(Analyzer)" SourceItemType="Analyzer" />
<AdditionalFiles Include="$(ProjectAssetsFile)" SourceItemType="SponsorLinkInput" />
<AdditionalFiles Include="$(MSBuildProjectFullPath)" SourceItemType="SponsorLinkInput" />
</ItemGroup>
</Target>

<Target Name="CollectSponsorLinkMessages" AfterTargets="CoreCompile">
<!-- SponsorLink is typically consumed from a netstandard2.0 analyzer project, which by default won't copy-local
any of its runtime dependencies. But in order to properly load the analyzer when debugging as a roslyn component,
all dependencies need to exist alongside the analyzer project, so we need CopyLocal behavior always for SL. -->
<Target Name="CopyLocalSponsorLink" AfterTargets="ResolvePackageAssets" DependsOnTargets="ResolvePackageAssets">
<ItemGroup>
<SponsorLinkMessage Include="obj/SponsorLink/**/*.txt" />
<ReferenceCopyLocalPaths Include="@(RuntimeCopyLocalItems -> WithMetadataValue('NuGetPackageId', 'Devlooped.SponsorLink'))" />
</ItemGroup>
</Target>

<Target Name="CleanSponsorLinkMessages" AfterTargets="Clean" DependsOnTargets="CollectSponsorLinkMessages">
<Delete Files="@(SponsorLinkMessage)" />
</Target>

<Target Name="SponsorLinkMessages" AfterTargets="CoreCompile"
Condition="'$(BuildingInsideVisualStudio)' == 'true' and '$(DesignTimeBuild)' != 'true'"
Inputs="@(SponsorLinkMessage)" Outputs="%(SponsorLinkMessage.Identity)-BATCH">
<PropertyGroup>
<SponsorLinkFilename>%(SponsorLinkMessage.Filename)%(SponsorLinkMessage.Extension)</SponsorLinkFilename>
<SponsorLinkDiagnosticId>$(SponsorLinkFilename.Substring(0, 4))</SponsorLinkDiagnosticId>
<SponsorLinkNoWarn>false</SponsorLinkNoWarn>
<SponsorLinkNoWarn Condition="$(NoWarn.Contains('$(SponsorLinkDiagnosticId)'))">true</SponsorLinkNoWarn>
<SponsorLinkMessageImportance>normal</SponsorLinkMessageImportance>
<SponsorLinkMessageImportance Condition="$(SponsorLinkFilename.Contains('.low.'))">low</SponsorLinkMessageImportance>
<SponsorLinkMessageImportance Condition="$(SponsorLinkFilename.Contains('.high.'))">high</SponsorLinkMessageImportance>
</PropertyGroup>

<!-- We always read info since we want the thanks to be seen :) -->
<ReadLinesFromFile File="@(SponsorLinkMessage)" Condition="$(SponsorLinkNoWarn) or $(SponsorLinkFilename.Contains('.Info.'))">
<Output TaskParameter="Lines" ItemName="SponsorLinkMessageLine"/>
</ReadLinesFromFile>

<!-- 🙏 Please, instead of disabling SponsorLink, consider supporting the ongoing development of
the projects you depend on. This helps keep the community healthy and supports your fellow developers
make a living too. There is no minimum amount to sponsor, and you can cancel at any time.
It's available everywhere in the world, and you can sponsor anonymously if you prefer too!
Learn more at https://github.com/sponsors.
-->
<Error Text="@(SponsorLinkMessageLine, '')" Condition="$(SponsorLinkNoWarn) and $(SponsorLinkFilename.Contains('.Error.'))" />

<!-- 🙏 Please, instead of disabling SponsorLink, consider supporting the ongoing development of
the projects you depend on. This helps keep the community healthy and supports your fellow developers
make a living too. There is no minimum amount to sponsor, and you can cancel at any time.
It's available everywhere in the world, and you can sponsor anonymously if you prefer too!
Learn more at https://github.com/sponsors.
-->
<Warning Text="@(SponsorLinkMessageLine, '')" Condition="$(SponsorLinkNoWarn) and $(SponsorLinkFilename.Contains('.Warning.'))" />

<!-- Always show info, since otherwise it's typically not visible anywhere, and we want the Thanks to be seen :) -->
<Message Text="@(SponsorLinkMessageLine, '')" Importance="normal" Condition="$(SponsorLinkFilename.Contains('.Info.'))" />
</Target>

<Target Name="SponsorLinkPackDefaults"
BeforeTargets="InferPackageContents;GetPackageContents"
Inputs="@(PackageReference -> WithMetadataValue('Identity', 'Devlooped.SponsorLink'))"
Outputs="|%(PackageReference.Identity)|">
<ItemGroup>
<!-- NOTE: this will take care of packing SL dependencies automatically due to PrivateAssets=all
TODO: do the equivalent for SDK Pack too. -->
<PackageReference Condition="'%(PackageReference.PrivateAssets)' == ''"
PrivateAssets="all" />
</ItemGroup>
</Target>

<Target Name="AddSponsorLinkPackageContents" BeforeTargets="GetPackageContents">
<ItemGroup>
<PackageFile Include="$(MSBuildThisFileDirectory)Devlooped.SponsorLink.targets"
PackagePath="build/Devlooped.SponsorLink.targets" />
<PackageFile Include="$(MSBuildThisFileDirectory)Devlooped.SponsorLink.targets"
PackagePath="buildTransitive/Devlooped.SponsorLink.targets" />
<PackageFile Include="$(SponsorLinkTargets)" PackFolder="buildTransitive" />
</ItemGroup>
</Target>

Expand Down
5 changes: 2 additions & 3 deletions src/Package/Package.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

<ItemGroup>
<PackageFile Include="*.props;*.targets" PackagePath="build/%(Filename)%(Extension)" />
<None Update="tools\Devlooped.SponsorLink.targets" Pack="true" />
</ItemGroup>

<Target Name="Obfuscate" AfterTargets="Build" DependsOnTargets="Build" Condition="'$(Configuration)' == 'Release' and '$(dotnet-nugetize)' == ''">
Expand All @@ -58,9 +59,7 @@
<PackageFile Include="$(Obfuscated)\$(TargetFileName)" PackFolder="lib" />
<PackageFile Include="@(SatelliteDllsProjectOutputGroupOutput -> '%(FullPath)')" PackFolder="lib" />
<!-- Moved to target to avoid a broken link in the solution explorer to lib\net462 folder -->
<PackageFile Include="lib\net462\System.Net.Http.WinHttpHandler.dll"
PackageReference="System.Net.Http.WinHttpHandler"
PackFolder="lib" />
<PackageFile Include="lib\net462\System.Net.Http.WinHttpHandler.dll" PackageReference="System.Net.Http.WinHttpHandler" PackFolder="lib" />
</ItemGroup>
</Target>

Expand Down
4 changes: 2 additions & 2 deletions src/Package/SponsorLink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,15 +274,15 @@ void CheckAndReport(CompilationAnalysisContext context, BuildInfo info)
return options.TryGetValue("build_metadata.AdditionalFiles.SourceItemType", out var itemType) &&
itemType == "Analyzer" &&
// Filter analyzer items that actually have an originating NuGetPackageId metadata
options.TryGetValue("build_metadata.Analyzer.NuGetPackageId", out var packageId);
options.TryGetValue("build_metadata.AdditionalFiles.NuGetPackageId", out var packageId);
})
// Adding this since we check for the file write time... Is this needed?
.Where(x => File.Exists(x.Path))
.Select((x, c) => new
{
x.Path,
PackageId = context.Options.AnalyzerConfigOptionsProvider.GetOptions(x)
.TryGetValue("build_metadata.Analyzer.NuGetPackageId", out var packageId) ?
.TryGetValue("build_metadata.AdditionalFiles.NuGetPackageId", out var packageId) ?
packageId : ""
})
.Where(x => x.PackageId == settings.PackageId)
Expand Down
5 changes: 3 additions & 2 deletions src/Package/SponsorLinkSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public static SponsorLinkSettings Create(string sponsorable, string product)
public static SponsorLinkSettings Create(string sponsorable, string product,
string? packageId = default,
string? diagnosticsIdPrefix = default,
int pauseMin = 0, int
pauseMax = DefaultMaxPause) => Create(sponsorable, product,
int pauseMin = 0,
int pauseMax = DefaultMaxPause) => Create(sponsorable, product,
packageId: packageId,
diagnosticsIdPrefix: diagnosticsIdPrefix,
version: default,
Expand Down Expand Up @@ -154,4 +154,5 @@ public static SponsorLinkSettings Create(string sponsorable, string product,
internal int PauseMax { get; private set; }
internal DateTime? InstallTime { get; set; }
internal int? QuietDays { get; private set; }
internal bool Transitive { get; private set; }
}
106 changes: 106 additions & 0 deletions src/Package/tools/Devlooped.SponsorLink.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<!-- These targets are included by sponsorable packages that integrate
SponsorLink checks. It's used by end users of the sponsorable package/product. -->
<Project>

<PropertyGroup>
<BuildingInsideVisualStudio>false</BuildingInsideVisualStudio>
<BuildingInsideVisualStudio Condition="$(IDEA_INITIAL_DIRECTORY) != '' or $(RESHARPER_FUS_BUILD) != '' or $(RESHARPER_FUS_SESSION) != ''">true</BuildingInsideVisualStudio>
<!-- Analyzer projects using DebugRoslynComponent launch profile and IsRoslynComponent can
set this property to true in the launched project so that SponsorLink does not skip the
checks even if DesignTimeBuild is true. -->
<DebugSponsorLink Condition="'$(DebugSponsorLink)' == ''" />
</PropertyGroup>

<ItemGroup>
<!-- By adding these items in .targets, we make it harder to break from tweaks in the project file -->
<CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="SourceItemType" />
<CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="NuGetPackageId" />
<CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="ParentPackage" />

<CompilerVisibleProperty Include="DesignTimeBuild" />
<CompilerVisibleProperty Include="BuildingInsideVisualStudio" />
<CompilerVisibleProperty Include="MSBuildProjectFullPath" />

<CompilerVisibleProperty Include="DebugSponsorLink" />
</ItemGroup>

<Target Name="CollectPackageDependencies"
Condition="'$(UsingMicrosoftNETSdk)' == 'true'"
BeforeTargets="GenerateMSBuildEditorConfigFileShouldRun"
DependsOnTargets="RunResolvePackageDependencies" />

<Target Name="CollectSponsorLinkReference"
BeforeTargets="GenerateMSBuildEditorConfigFileShouldRun"
DependsOnTargets="CollectPackageDependencies"
Inputs="@(SponsorablePackageId)"
Outputs="|%(SponsorablePackageId.Identity)|">

<PropertyGroup>
<SponsorablePackageId>%(SponsorablePackageId.Identity)</SponsorablePackageId>
</PropertyGroup>

<ItemGroup>
<!-- Used to determine InstallTime for quiet days calculation -->
<AdditionalFiles Include="@(Analyzer -> WithMetadataValue('NuGetPackageId', '$(SponsorablePackageId)'))"
SourceItemType="Analyzer" NuGetPackageId="%(Analyzer.NuGetPackageId)" />

<SponsorablePackageDependencies Include="@(PackageDependencies)"
Condition="$([MSBuild]::ValueOrDefault('%(PackageDependencies.Identity)', '').StartsWith('$(SponsorablePackageId)/'))" />

<!-- Used to determine if the reference is top-level or transitive, via the ParentPackage metadata -->
<AdditionalFiles Include="@(SponsorablePackageDependencies)"
SourceItemType="PackageDependencies"
SourceIdentity="$(SponsorablePackageId)" />
</ItemGroup>

</Target>

<Target Name="CollectSponsorLinkMessages" AfterTargets="CoreCompile">
<ItemGroup>
<SponsorLinkMessage Include="obj/SponsorLink/**/*.txt" />
</ItemGroup>
</Target>

<Target Name="CleanSponsorLinkMessages" AfterTargets="Clean" DependsOnTargets="CollectSponsorLinkMessages">
<Delete Files="@(SponsorLinkMessage)" />
</Target>

<Target Name="SponsorLinkMessages" AfterTargets="CoreCompile"
Condition="'$(BuildingInsideVisualStudio)' == 'true' and '$(DesignTimeBuild)' != 'true'"
Inputs="@(SponsorLinkMessage)" Outputs="%(SponsorLinkMessage.Identity)-BATCH">
<PropertyGroup>
<SponsorLinkFilename>%(SponsorLinkMessage.Filename)%(SponsorLinkMessage.Extension)</SponsorLinkFilename>
<SponsorLinkDiagnosticId>$(SponsorLinkFilename.Substring(0, 4))</SponsorLinkDiagnosticId>
<SponsorLinkNoWarn>false</SponsorLinkNoWarn>
<SponsorLinkNoWarn Condition="$(NoWarn.Contains('$(SponsorLinkDiagnosticId)'))">true</SponsorLinkNoWarn>
<SponsorLinkMessageImportance>normal</SponsorLinkMessageImportance>
<SponsorLinkMessageImportance Condition="$(SponsorLinkFilename.Contains('.low.'))">low</SponsorLinkMessageImportance>
<SponsorLinkMessageImportance Condition="$(SponsorLinkFilename.Contains('.high.'))">high</SponsorLinkMessageImportance>
</PropertyGroup>

<!-- We always read info since we want the thanks to be seen :) -->
<ReadLinesFromFile File="@(SponsorLinkMessage)" Condition="$(SponsorLinkNoWarn) or $(SponsorLinkFilename.Contains('.Info.'))">
<Output TaskParameter="Lines" ItemName="SponsorLinkMessageLine"/>
</ReadLinesFromFile>

<!-- 🙏 Please, instead of disabling SponsorLink, consider supporting the ongoing development of
the projects you depend on. This helps keep the community healthy and supports your fellow developers
make a living too. There is no minimum amount to sponsor, and you can cancel at any time.
It's available everywhere in the world, and you can sponsor anonymously if you prefer too!
Learn more at https://github.com/sponsors.
-->
<Error Text="@(SponsorLinkMessageLine, '')" Condition="$(SponsorLinkNoWarn) and $(SponsorLinkFilename.Contains('.Error.'))" />

<!-- 🙏 Please, instead of disabling SponsorLink, consider supporting the ongoing development of
the projects you depend on. This helps keep the community healthy and supports your fellow developers
make a living too. There is no minimum amount to sponsor, and you can cancel at any time.
It's available everywhere in the world, and you can sponsor anonymously if you prefer too!
Learn more at https://github.com/sponsors.
-->
<Warning Text="@(SponsorLinkMessageLine, '')" Condition="$(SponsorLinkNoWarn) and $(SponsorLinkFilename.Contains('.Warning.'))" />

<!-- Always show info, since otherwise it's typically not visible anywhere, and we want the Thanks to be seen :) -->
<Message Text="@(SponsorLinkMessageLine, '')" Importance="normal" Condition="$(SponsorLinkFilename.Contains('.Info.'))" />
</Target>

</Project>

0 comments on commit 8a2910f

Please sign in to comment.