mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-17 05:11:13 +08:00
Fix source-generator package delivery and preview restore (Roslyn packaging) (#4041)
## Failure The source-generator projects disabled normal build-output packing without adding their analyzer assemblies and private runtime closure back to the NuGet payload. Debug and Release packages also shared IDs, and both preview workflows passed the unsupported `--configuration` option to `dotnet restore`. ## Fix - Package each generator and its private runtime closure under `analyzers/dotnet/cs`, excluding Roslyn host assemblies and package dependencies. - Preserve Roslyn compile references for project-reference test consumers. - Give Debug generator packages `.Debug` IDs. - Validate package contents and clean net10 consumers in both preview pipelines. - Remove invalid restore configuration arguments from both preview workflows. ## Reference - Roslyn analyzer packaging and MSBuild restore semantics; no normative OPC UA change. - Split from #4021. ## Tests - `Opc.Ua.SourceGeneration.Tests`: 68 passed on net10.0 and 68 on net48. - `Opc.Ua.SourceGeneration.Stack.Tests`: 90 passed on net10.0 and 87 on net48. - Generated `preview-pack.slnx` and restored it with `--disable-parallel`. - Packed both Release generators with `--no-build`; package-content checks and two clean net10 consumer builds passed with zero warnings/errors. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -89,7 +89,6 @@ jobs:
|
||||
inputs:
|
||||
command: restore
|
||||
projects: 'preview-pack.slnx'
|
||||
arguments: '--configuration ${{parameters.config}}'
|
||||
restoreArguments: '--disable-parallel'
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: Build ${{parameters.config}}
|
||||
@@ -121,6 +120,12 @@ jobs:
|
||||
configuration: ${{parameters.config}}
|
||||
configurationToPack: ${{parameters.config}}
|
||||
nobuild: true
|
||||
- task: PowerShell@2
|
||||
displayName: Validate source generator packages
|
||||
condition: and(succeeded(), eq('${{parameters.config}}', 'Release'))
|
||||
inputs:
|
||||
filePath: '.azurepipelines/validate-source-generator-packages.ps1'
|
||||
arguments: '-PackageDirectory "$(Build.ArtifactStagingDirectory)"'
|
||||
- task: NuGetCommand@2
|
||||
displayName: Pack Nuget Legacy Preview
|
||||
condition: and(succeeded(), and(eq('${{parameters.config}}', 'Release'), ne(variables['NBGV_PublicRelease'], 'True')))
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Validates the source-generator NuGet payloads and builds clean consumers.
|
||||
|
||||
.PARAMETER PackageDirectory
|
||||
Directory containing the packed source-generator NuGet packages.
|
||||
#>
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $PackageDirectory
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Assert-Condition
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[bool] $Condition,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $Message
|
||||
)
|
||||
|
||||
if (-not $Condition)
|
||||
{
|
||||
throw $Message
|
||||
}
|
||||
}
|
||||
|
||||
function Get-PackageInfo
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $PackageId
|
||||
)
|
||||
|
||||
$packagePattern = "^$([Regex]::Escape($PackageId))\.(?<version>[0-9].+)\.nupkg$"
|
||||
$packages = @(Get-ChildItem -Path $PackageDirectory -Filter "$PackageId*.nupkg" -File -Recurse |
|
||||
Where-Object { $_.Name -notlike "*.snupkg" -and $_.Name -match $packagePattern })
|
||||
|
||||
Assert-Condition ($packages.Count -gt 0) "Package '$PackageId' was not found in '$PackageDirectory'."
|
||||
Assert-Condition (
|
||||
$packages.Count -eq 1
|
||||
) "Expected exactly one package '$PackageId' in '$PackageDirectory'; found $($packages.Count)."
|
||||
$package = $packages[0]
|
||||
|
||||
$archive = [IO.Compression.ZipFile]::OpenRead($package.FullName)
|
||||
try
|
||||
{
|
||||
$entries = @($archive.Entries | ForEach-Object FullName)
|
||||
$nuspecEntries = @($archive.Entries |
|
||||
Where-Object { $_.FullName.EndsWith(".nuspec", [StringComparison]::OrdinalIgnoreCase) })
|
||||
Assert-Condition (
|
||||
$nuspecEntries.Count -eq 1
|
||||
) "Package '$($package.Name)' must contain exactly one nuspec."
|
||||
$nuspecEntry = $nuspecEntries[0]
|
||||
|
||||
$reader = [IO.StreamReader]::new($nuspecEntry.Open())
|
||||
try
|
||||
{
|
||||
[xml] $nuspec = $reader.ReadToEnd()
|
||||
}
|
||||
finally
|
||||
{
|
||||
$reader.Dispose()
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
$archive.Dispose()
|
||||
}
|
||||
|
||||
[PSCustomObject] @{
|
||||
Id = $PackageId
|
||||
Path = $package.FullName
|
||||
Version = [string] $nuspec.package.metadata.version
|
||||
Entries = $entries
|
||||
Dependencies = @($nuspec.SelectNodes("//*[local-name()='dependency']"))
|
||||
}
|
||||
}
|
||||
|
||||
function Test-PackageContents
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[PSCustomObject] $Package,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $GeneratorAssembly
|
||||
)
|
||||
|
||||
$analyzerPath = "analyzers/dotnet/cs/"
|
||||
$requiredAssemblies = @(
|
||||
$GeneratorAssembly,
|
||||
"Opc.Ua.SourceGeneration.Core.dll",
|
||||
"Opc.Ua.Types.dll",
|
||||
"SourceGenerator.Foundations.Contracts.dll",
|
||||
"SourceGenerator.Foundations.Windows.dll"
|
||||
)
|
||||
|
||||
foreach ($assembly in $requiredAssemblies)
|
||||
{
|
||||
Assert-Condition (
|
||||
$Package.Entries -contains "$analyzerPath$assembly"
|
||||
) "Package '$($Package.Id)' is missing '$analyzerPath$assembly'."
|
||||
}
|
||||
|
||||
$dllEntries = @($Package.Entries |
|
||||
Where-Object { $_.EndsWith(".dll", [StringComparison]::OrdinalIgnoreCase) })
|
||||
Assert-Condition ($dllEntries.Count -gt 0) "Package '$($Package.Id)' contains no assemblies."
|
||||
Assert-Condition (
|
||||
@($dllEntries | Where-Object { -not $_.StartsWith(
|
||||
$analyzerPath,
|
||||
[StringComparison]::OrdinalIgnoreCase) }).Count -eq 0
|
||||
) "Package '$($Package.Id)' contains assemblies outside '$analyzerPath'."
|
||||
Assert-Condition (
|
||||
@($dllEntries | Where-Object {
|
||||
[IO.Path]::GetFileName($_).StartsWith(
|
||||
"Microsoft.CodeAnalysis",
|
||||
[StringComparison]::OrdinalIgnoreCase)
|
||||
}).Count -eq 0
|
||||
) "Package '$($Package.Id)' must not ship Microsoft.CodeAnalysis host assemblies."
|
||||
Assert-Condition (
|
||||
$Package.Dependencies.Count -eq 0
|
||||
) "Package '$($Package.Id)' must carry its analyzer runtime closure privately."
|
||||
}
|
||||
|
||||
function Invoke-DotNet
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string[]] $Arguments
|
||||
)
|
||||
|
||||
& dotnet @Arguments
|
||||
if ($LASTEXITCODE -ne 0)
|
||||
{
|
||||
throw "dotnet $($Arguments -join ' ') failed with exit code $LASTEXITCODE."
|
||||
}
|
||||
}
|
||||
|
||||
function Get-MSBuildProperty
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $ProjectPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $Configuration,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $PropertyName
|
||||
)
|
||||
|
||||
$output = & dotnet msbuild $ProjectPath `
|
||||
"-getProperty:$PropertyName" `
|
||||
"-p:Configuration=$Configuration" `
|
||||
-nologo
|
||||
if ($LASTEXITCODE -ne 0)
|
||||
{
|
||||
throw "Could not read MSBuild property '$PropertyName' from '$ProjectPath'."
|
||||
}
|
||||
|
||||
return [string]($output |
|
||||
Where-Object { -not [string]::IsNullOrWhiteSpace($_) } |
|
||||
Select-Object -Last 1).Trim()
|
||||
}
|
||||
|
||||
function Test-ConfigurationPackageIds
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $ProjectPath
|
||||
)
|
||||
|
||||
$releaseId = Get-MSBuildProperty $ProjectPath "Release" "PackageId"
|
||||
$debugId = Get-MSBuildProperty $ProjectPath "Debug" "PackageId"
|
||||
Assert-Condition (
|
||||
$debugId -eq "$releaseId.Debug"
|
||||
) "Debug package '$debugId' must use the release ID '$releaseId' with a '.Debug' suffix."
|
||||
}
|
||||
|
||||
function Test-CleanConsumer
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[PSCustomObject] $Package,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $ValidationRoot
|
||||
)
|
||||
|
||||
$consumerName = $Package.Id.Split(".")[-1]
|
||||
$consumerDirectory = Join-Path $ValidationRoot $consumerName
|
||||
New-Item -ItemType Directory -Path $consumerDirectory | Out-Null
|
||||
$projectPath = Join-Path $consumerDirectory "$consumerName.csproj"
|
||||
$expectedDiagnosticSuppression = if ($Package.Id.EndsWith(
|
||||
".Stack",
|
||||
[StringComparison]::Ordinal))
|
||||
{
|
||||
" <NoWarn>STACKGEN001</NoWarn>"
|
||||
}
|
||||
else
|
||||
{
|
||||
""
|
||||
}
|
||||
@"
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
$expectedDiagnosticSuppression
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="$($Package.Id)" Version="$($Package.Version)"
|
||||
PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
"@ | Set-Content -Path $projectPath -Encoding utf8
|
||||
@"
|
||||
namespace SourceGeneratorConsumer;
|
||||
|
||||
public static class ConsumerMarker
|
||||
{
|
||||
public static int Value => 42;
|
||||
}
|
||||
"@ | Set-Content -Path (Join-Path $consumerDirectory "ConsumerMarker.cs") -Encoding utf8
|
||||
|
||||
$nugetConfig = Join-Path $ValidationRoot "NuGet.Config"
|
||||
$packagesPath = Join-Path $ValidationRoot "packages"
|
||||
Invoke-DotNet @(
|
||||
"restore",
|
||||
$projectPath,
|
||||
"--configfile",
|
||||
$nugetConfig,
|
||||
"--packages",
|
||||
$packagesPath,
|
||||
"--nologo"
|
||||
)
|
||||
Invoke-DotNet @(
|
||||
"build",
|
||||
$projectPath,
|
||||
"--configuration",
|
||||
"Release",
|
||||
"--no-restore",
|
||||
"--nologo"
|
||||
)
|
||||
}
|
||||
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
|
||||
$resolvedPackageDirectory = (Resolve-Path $PackageDirectory).Path
|
||||
$PackageDirectory = $resolvedPackageDirectory
|
||||
$repoRoot = Split-Path $PSScriptRoot -Parent
|
||||
$validationRoot = Join-Path (Join-Path $repoRoot "artifacts") "source-generator-consumer"
|
||||
Test-ConfigurationPackageIds (
|
||||
Join-Path $repoRoot "tools\Opc.Ua.SourceGeneration\Opc.Ua.SourceGeneration.csproj")
|
||||
Test-ConfigurationPackageIds (
|
||||
Join-Path $repoRoot "tools\Opc.Ua.SourceGeneration.Stack\Opc.Ua.SourceGeneration.Stack.csproj")
|
||||
$modelPackage = Get-PackageInfo "OPCFoundation.NetStandard.Opc.Ua.SourceGeneration"
|
||||
$stackPackage = Get-PackageInfo "OPCFoundation.NetStandard.Opc.Ua.SourceGeneration.Stack"
|
||||
|
||||
Test-PackageContents $modelPackage "Opc.Ua.SourceGeneration.dll"
|
||||
Test-PackageContents $stackPackage "Opc.Ua.SourceGeneration.Stack.dll"
|
||||
|
||||
Remove-Item -Path $validationRoot -Recurse -Force -ErrorAction SilentlyContinue
|
||||
New-Item -ItemType Directory -Path $validationRoot | Out-Null
|
||||
try
|
||||
{
|
||||
"<Project />" | Set-Content -Path (Join-Path $validationRoot "Directory.Build.props") -Encoding utf8
|
||||
"<Project />" | Set-Content -Path (Join-Path $validationRoot "Directory.Build.targets") -Encoding utf8
|
||||
@"
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
"@ | Set-Content -Path (Join-Path $validationRoot "Directory.Packages.props") -Encoding utf8
|
||||
$escapedPackageDirectory = [System.Security.SecurityElement]::Escape($PackageDirectory)
|
||||
@"
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="source-generator-packages" value="$escapedPackageDirectory" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
"@ | Set-Content -Path (Join-Path $validationRoot "NuGet.Config") -Encoding utf8
|
||||
|
||||
Test-CleanConsumer $modelPackage $validationRoot
|
||||
Test-CleanConsumer $stackPackage $validationRoot
|
||||
}
|
||||
finally
|
||||
{
|
||||
Remove-Item -Path $validationRoot -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
Write-Host "Validated source-generator package contents and clean consumers."
|
||||
@@ -119,7 +119,6 @@ jobs:
|
||||
shell: pwsh
|
||||
run: |
|
||||
dotnet restore 'preview-pack.slnx' `
|
||||
--configuration Release `
|
||||
--disable-parallel
|
||||
|
||||
- name: Build (with optional strong-name signing)
|
||||
@@ -186,6 +185,12 @@ jobs:
|
||||
--configuration Release `
|
||||
--output "$env:ARTIFACTS_DIR"
|
||||
|
||||
- name: Validate source generator packages
|
||||
shell: pwsh
|
||||
run: |
|
||||
./.azurepipelines/validate-source-generator-packages.ps1 `
|
||||
-PackageDirectory "$env:ARTIFACTS_DIR"
|
||||
|
||||
- name: Pack NuGet Legacy (nuget/*.nuspec, version from PACK_MODE)
|
||||
shell: pwsh
|
||||
# Scoped to nuget/ - the MigrationAnalyzer nuspec at tools/Opc.Ua.MigrationAnalyzer/
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<IncludeBuildOutput>false</IncludeBuildOutput>
|
||||
<AssemblyName>$(AssemblyPrefix).SourceGeneration.Stack</AssemblyName>
|
||||
<RootNamespace>Opc.Ua.SourceGeneration</RootNamespace>
|
||||
<Description>OPC UA source generation Library</Description>
|
||||
@@ -20,6 +19,9 @@
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<NoPackageAnalysis>true</NoPackageAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<PackageId>$(PackageId).Debug</PackageId>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<AssemblySearchPath_UseOutDir>true</AssemblySearchPath_UseOutDir>
|
||||
@@ -32,12 +34,13 @@
|
||||
<InternalsVisibleTo Include="Opc.Ua.SourceGeneration.Stack.Tests"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- Keep Roslyn compile assets transitive for project-reference test consumers.
|
||||
SourceGeneratorPackaging.targets suppresses package dependencies and host DLL payloads. -->
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
|
||||
<PackageReference Include="SourceGenerator.Foundations" >
|
||||
<!-- Make private asset because assembly name comparer symbol conflict in test -->
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<OutputItemType>Analzyer</OutputItemType>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
<OutputItemType>Analyzer</OutputItemType>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -56,4 +59,5 @@
|
||||
<ItemGroup>
|
||||
<None Include="NugetREADME.md" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
<Import Project="..\Opc.Ua.SourceGeneration\SourceGeneratorPackaging.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<IncludeBuildOutput>false</IncludeBuildOutput>
|
||||
<AssemblyName>$(AssemblyPrefix).SourceGeneration</AssemblyName>
|
||||
<RootNamespace>Opc.Ua.SourceGeneration</RootNamespace>
|
||||
<Description>OPC UA source generation Library</Description>
|
||||
@@ -20,6 +19,9 @@
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<NoPackageAnalysis>true</NoPackageAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<PackageId>$(PackageId).Debug</PackageId>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<AssemblySearchPath_UseOutDir>true</AssemblySearchPath_UseOutDir>
|
||||
@@ -32,12 +34,13 @@
|
||||
<InternalsVisibleTo Include="Opc.Ua.SourceGeneration.Tests"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- Keep Roslyn compile assets transitive for project-reference test consumers.
|
||||
SourceGeneratorPackaging.targets suppresses package dependencies and host DLL payloads. -->
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
|
||||
<PackageReference Include="SourceGenerator.Foundations">
|
||||
<!-- Make private asset because assembly name comparer symbol conflict in test -->
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<OutputItemType>Analzyer</OutputItemType>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
<OutputItemType>Analyzer</OutputItemType>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -54,5 +57,5 @@
|
||||
<ItemGroup>
|
||||
<None Include="NugetREADME.md" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
<Import Project="SourceGeneratorPackaging.targets" />
|
||||
</Project>
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<IncludeBuildOutput>false</IncludeBuildOutput>
|
||||
<!-- The analyzer payload is custom package content, so no build-output symbol package is produced. -->
|
||||
<IncludeSymbols>false</IncludeSymbols>
|
||||
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
|
||||
<DevelopmentDependency>true</DevelopmentDependency>
|
||||
<TargetsForTfmSpecificContentInPackage>
|
||||
$(TargetsForTfmSpecificContentInPackage);IncludeSourceGeneratorRuntimeAssets
|
||||
</TargetsForTfmSpecificContentInPackage>
|
||||
<IncludeSourceGeneratorRuntimeAssetsDependsOn Condition="'$(NoBuild)' != 'true'">
|
||||
Compile;CopyFilesToOutputDirectory;ResolveReferences
|
||||
</IncludeSourceGeneratorRuntimeAssetsDependsOn>
|
||||
</PropertyGroup>
|
||||
<Target Name="IncludeSourceGeneratorRuntimeAssets"
|
||||
DependsOnTargets="$(IncludeSourceGeneratorRuntimeAssetsDependsOn)">
|
||||
<ItemGroup>
|
||||
<_SourceGeneratorRuntimeAsset Include="@(ReferenceCopyLocalPaths)"
|
||||
Condition="'$(NoBuild)' != 'true' AND
|
||||
'%(ReferenceCopyLocalPaths.Extension)' == '.dll' AND
|
||||
!$([System.String]::Copy('%(Filename)').StartsWith('Microsoft.CodeAnalysis')) AND
|
||||
'%(ReferenceCopyLocalPaths.NuGetPackageId)' != 'Microsoft.CodeAnalysis.Common' AND
|
||||
'%(ReferenceCopyLocalPaths.NuGetPackageId)' != 'Microsoft.CodeAnalysis.CSharp' AND
|
||||
'%(ReferenceCopyLocalPaths.NuGetPackageId)' != 'Microsoft.CodeAnalysis.Workspaces.Common' AND
|
||||
'%(ReferenceCopyLocalPaths.NuGetPackageId)' != 'Microsoft.CodeAnalysis.CSharp.Workspaces'" />
|
||||
<!-- Preview no-build packaging reuses the closure copied by the preceding solution build. -->
|
||||
<_SourceGeneratorRuntimeAsset Include="$(TargetDir)*.dll"
|
||||
Exclude="$(TargetPath);$(TargetDir)Microsoft.CodeAnalysis*.dll"
|
||||
Condition="'$(NoBuild)' == 'true'" />
|
||||
<TfmSpecificPackageFile Include="$(TargetPath)">
|
||||
<PackagePath>analyzers/dotnet/cs/$(TargetFileName)</PackagePath>
|
||||
</TfmSpecificPackageFile>
|
||||
<TfmSpecificPackageFile Include="@(_SourceGeneratorRuntimeAsset)">
|
||||
<PackagePath>analyzers/dotnet/cs/%(_SourceGeneratorRuntimeAsset.Filename)%(_SourceGeneratorRuntimeAsset.Extension)</PackagePath>
|
||||
</TfmSpecificPackageFile>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user