-
Notifications
You must be signed in to change notification settings - Fork 140
Description
Describe the Bug
The Source Build Reference Package generator does not explicitly specify the value of the LibPath parameter of the cci-based GenAPI and AssemblyReference parameter of the roslyn-based GenAPI (== "Paths to assembly references or their underlying directories for a specific target framework in the package.").
As a result, the value from the variable @(ReferencePathWithRefAssemblies) is taken and it contains the assembly references of the target framework with which the SBRP tool is built. Currently it is set to net6.0 so we use the assembly references of the net6.0 target framework to resolve references for all TFMs.
NuGet package
--- netstandard1.0
--- netstandard2.0
--- net461
Steps to Reproduce
This affects he reference assembly generation and the nice example is the system.collections.immutable package of version 5.0.0 .
./generate.sh --pkg microsoft.codeanalysis.csharp,4.0.1 --genapi-backend roslyn
The class Builder implements the System.Collections.IList interfaces and the GenAPI cannot resolve symbols for the interface and cannot generate the indexed property correctly.
- object? IList.Item { get { throw null; } set { } }
+ object? IList.this[int index] { get { throw null; } set { } }+/- 30 cases.
Other Information
Message from @ViktorHofer:
The problem is that GenAPI is invoked stand-alone (either the MSBuild or the CLI version) and hence there is no access to an input assembly's reference assemblies. I see two options to fix this:There are different ways to solve that:
- Add a heuristic that fetches all dependent NuGet packages, and use NuGet APIs to choose the right assemblies per TFM. Add another heuristic that fetches the TargetFramework targeting pack:
- Microsoft.NETCore.App.Ref for .NETCoreApp tfms
- Microsoft.NetFramework.ReferenceAssemblies for .NETFramework tfms
- NETStandard.Library for netstandard2.0
- NETStandard.Library.Ref for netstandard2.1
- Generate a project wrapper with the TFMs that the package supports and add a PackageReference to the package. That project then has access to all the reference assemblies automatically as NuGet and the SDK handle the fetching and best compatible asset heuristic for you.
I would definitely choose №2 as №1 is quite fragile and requires ton more code to get it right. №2 also allows that wrapper project to packagereference the Microsoft.DotNet.GenAPI.Task package which means that it will handle the GenAPI invocation automatically.
If you want to experiment with №2, I would start with the following (unsure what's already handled by the existing SRBP tool). I assume that the NuGet package to convert is the input to the SRBP tool:
- Crack open the NuGet packages and fetch all TargetFramework values from it (that's easily doable with NuGet APIs. Take a look at Microsoft.DotNet.PackageValidation.Package.cs in dotnet/sdk).
- Write a project wrapper file (template with variable substitution for the TargetFrameworks) similar to this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$$TargetFrameworks$$</TargetFrameworks><
!-- GenAPI properties to enable and configure it. -->
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.DotNet.GenApi.Task" Version="..." PrivateAssets="all" />
<PackageReference Include="PackageToLookAt" Version="..." />
</ItemGroup>
<Target Name="CoreBuild"
DependsOnTargets="GenAPIGenerateReferenceAssemblySource">
...
</Target>
</Project>- Invoke the GenAPI target and build the project: dotnet build /t:GenAPIGenerateReferenceAssemblySource. Devil's in the details here but with some adjustments in GenAPI, that should work.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status