microsoft / CsWinRT

C# language projection for the Windows Runtime
MIT License
550 stars 106 forks source link

Modify interop project to prevent winmd leaking from component project #756

Open angelazhangmsft opened 3 years ago

angelazhangmsft commented 3 years ago

Describe the bug

Referencing a C#/WinRT interop project from a .NET 5 app raises a NETSDK1130 error. This is because the component winmd flows through from the C++/WinRT component project. The project referencing structure is .NET 5 app -> .NET 5 library interop project -> C++/WinRT component.

Look into whether C#/WinRT can fix this either by:

  1. Setting the implementation dll as an output in addition to the projection dll for the interop project. Then in the interop project, authors would set <PrivateAssets>all</PrivateAssets> on the project reference to the C++/WinRT component. Caveat is the component might have multiple binaries
  2. Modifying cswinrt NuGet targets. Cswinrt needs to influence reference resolution before project references kick in - binlog would show cross-reference target evaluation and the hook for that change. Referring to the CsWinRTRemoveWinMDReferences target here: https://github.com/microsoft/CsWinRT/blob/d361800d2cf6a46d2c7d276126a09bab1d8bc1c4/nuget/Microsoft.Windows.CsWinRT.targets#L47

To Reproduce

  1. Build the Net5ProjectionSample without generating a NuGet package
  2. Add ConsoleAppSample to the sample solution and add a project reference to the interop project, SimpleMathProjection

Here's an example - https://github.com/angelazhangmsft/ProjectionProject

Expected behavior

WinMD doesn't flow through but implementation dll does.

Additional context Current workaround for consuming interop project by project reference is to add cswinrt NuGet reference in app

angelazhangmsft commented 3 years ago

May be fixed if NETSDK1130 is resolved

angelazhangmsft commented 3 years ago

Possible way to fix this is to have the interop project add metadata to the TargetPath item it returns with the name of the WinMD that the interop project is wrapping. Then we could add logic so that the consuming project could filter out the transitive WinMD reference that it gets, similar to how we are removing WinMD references with WinRT.Host.dll as the implementation

Corillian commented 2 years ago

Just ran into this. It's my first time using CsWinRT and it's the second 6+ month old bug I've run into.

angelazhangmsft commented 2 years ago

@Corillian - unfortunately we haven't been able to investigate this further yet. As a workaround, you can add a package reference to Microsoft.Windows.CsWinRT in your app to avoid the NETSDK1130 error.

Depending on your scenario, you might also want to take a look at the recent embedded support which allows you to compile projection/runtime sources into your app or library for self-contained usage of WinRT types.

Corillian commented 2 years ago

I saw that in the earlier discussion, it worked, thanks for following up! While the future of WinUI3 sounds promising, lots of great things on the roadmap, it looks like it was released 6-12 months prematurely. Typically, the thing you guys (Microsoft) do best is toolchain support, but everything around WinUI3, including WinUI3 itself, seems to be pretty rough at the moment. Working with it is a bit frustrating.

Scottj1s commented 2 years ago

@ocalvo has demonstrated that this works: <PrivateAssets>build</PrivateAssets>