maui icon indicating copy to clipboard operation
maui copied to clipboard

Assembly load error in Android app referencing another project referencing a DLL assembly

Open ist-22 opened this issue 2 years ago • 8 comments

Description

If a MAUI Android project has a reference to a .NET Standard project in the same solution; and the .NET Standard project has a reference to a .NET Standard assembly, calling a code that eventually calls a code in the assembly fails to load the assembly.

Steps to Reproduce

  1. Create a new MAUI solution and project.
  2. Add a .NET Standard project to the solution.
  3. Add a .NET Standard assembly reference to this project created in Step 2.
  4. Add a method to the .NET Standard project (created in Step 2) that calls something in the referenced (in Step 3) assembly.
  5. Add a project reference to the MAUI app that was created in Step 1 that references to the project created in Step 2.
  6. Call the method that was created in step 4.

i.e. The reference chain: MAUI csproj --> .NET Std. csproj --> .NET Std. DLL

Link to public reproduction project repository

https://github.com/ist-22/10154-repro app has a project reference to lib1 lib1 has an assembly reference to lib2 (so lib2 needs to be compiled first)

Version with bug

6.0.400

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 11

Did you find any workaround?

Add the .NET Standard assembly reference also to the MAUI app project. In the repository uncomment lines 14..18 in app/app.csproj -- this adds an assembly reference to lib2 in app

Relevant log output

No response

ist-22 avatar Sep 15 '22 21:09 ist-22

Hi @ist-22. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md

This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Sep 16 '22 01:09 ghost

Are you sure this is a MAUI (The UI Framework) issue, or an issue with whatever device you're trying to target? Did you try doing this with a dotnet new android app?

drasticactions avatar Sep 16 '22 01:09 drasticactions

I don't think it's a device/target issue (if this implies architecture) since adding a reference to the assembly in the top MAUI app can act as a workaround.

However, you are right about the MAUI/UI framework question and pointing to the Android project. Yes the issue happens in a project created with dotnet new android, too; so I guess it's not MAUI specific and maybe more related to Xamarin.Android?

ist-22 avatar Sep 16 '22 09:09 ist-22

Could you please attach a project that exhibits this scenario?

jonpryor avatar Sep 26 '22 14:09 jonpryor

Hi @ist-22. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md

This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Sep 26 '22 14:09 ghost

@jonpryor -- Updated the issue description with the repo link

ist-22 avatar Sep 29 '22 18:09 ist-22

@jonpryor @jonathanpeppers thoughts?

PureWeen avatar Oct 27 '22 18:10 PureWeen

Does this problem go away if you use net6.0 class libraries (with no platform, vanilla net6.0) instead of netstandard?

jonathanpeppers avatar Oct 28 '22 16:10 jonathanpeppers

I have same issue with dynamic assembly loading..

michalss avatar Nov 03 '22 07:11 michalss

Does this problem go away if you use net6.0 class libraries (with no platform, vanilla net6.0) instead of netstandard?

@jonathanpeppers No, still happens.

ist-22 avatar Nov 03 '22 10:11 ist-22

Can you update the repro? https://github.com/ist-22/10154-repro

jonathanpeppers avatar Nov 03 '22 13:11 jonathanpeppers

Hi @ist-22. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Nov 18 '22 15:11 ghost

@jonathanpeppers -- repro updated.

ist-22 avatar Nov 22 '22 09:11 ist-22

Should we move this to the Android repo? Does this happen with iOS or Windows? Or even a plain old net7.0 console app?

mattleibow avatar Dec 01 '22 19:12 mattleibow

It doesn't happen with a Windows or console app -- can't test iOS.

ist-22 avatar Dec 01 '22 22:12 ist-22

In VS Windows, the above repro doesn't even build for me, unless I change lib1.csproj:

<Reference Include="lib2">
  <HintPath>..\lib2\bin\$(Configuration)\net7.0\lib2.dll</HintPath>
</Reference>

To this instead:

<ItemGroup>
  <ProjectReference Include="..\lib2\lib2.csproj" />
</ItemGroup>

If you have a <Reference/> to a random .dll file, the .NET SDK does not go "locate" this file and bring it to the top-level project (application project). I would use <ProjectReference> instead of <Reference> in this case, as the .NET SDK supports this. I suspect you'd have the same issue build a .NET 7 self-contained console app -- mobile apps are always self-contained.

If you are hitting this situation with a NuGet package, we can make suggestions on what to do there. Let me know, thanks!

jonathanpeppers avatar Dec 12 '22 15:12 jonathanpeppers

@jonathanpeppers The scenario in this issue is about a case where the user doesn't have access to the source code of the external library (i.e. lib2 in the repro), so adding a project reference is really not an option.

I guess your build failed since lib2 hadn't been built first (this was in the original message but sorry if it wasn't clear enough). The source code of lib2 in the repro is not very relevant to the issue itself and it is only there so that someone who runs the repro doesn't have to call a random DLL.

As I mentioned, this problem doesn't happen with a Windows or console app, also (as long as lib2 has been compiled) IntelliSense is also fine. In all cases (Windows, console and even Android) lib2.dll is copied into bin so I suspect it somehow is not packed into the APK properly.

ist-22 avatar Dec 13 '22 09:12 ist-22

@ist-22 does the same problem happen in a console app? You would publish it such as dotnet publish --self-contained -r win-x64, for example, and I bet that lib2.dll won't be in the build output. You would get a crash at runtime that the assembly isn't found. There isn't any logic in the .NET SDK that loads assemblies and automatically finds references.

So your options are:

  1. Make a NuGet package, and put lib2.dll alongside lib1.dll.
  2. Reference lib2.dll from the application project.

Does that make sense? Let me know if I missed something here.

jonathanpeppers avatar Dec 13 '22 14:12 jonathanpeppers

Here is another case we saw the same behavior in the .NET SDK: https://github.com/dotnet/maui/issues/11364#issuecomment-1322605802

jonathanpeppers avatar Dec 13 '22 14:12 jonathanpeppers

@jonathanpeppers it does not happen in a console or Windows app, and lib2.dll is always (even in Android) in the build output. What I can't verify (and suspect where the problem) is that whether it is packed into the APK or not.

Also:

  1. If I run dotnet publish --self-contained -r win-x64 I can still see lib2.dll under win-x64\publish and it doesn't crash when run,
  2. Separately, the scenario works fine in a Xamarin.Forms project (i.e. no crash/assembly error).

I appreciate the options/workarounds (I believe the second one is what I suggested as a workaround in my original message) but considering that it works fine with other project types, it makes me think that the expected behaviour is that assembly references inside referenced projects should be OK.

ist-22 avatar Dec 13 '22 21:12 ist-22

Can you share the console app you made? Is it on a branch of the original repro? Thanks.

jonathanpeppers avatar Dec 13 '22 22:12 jonathanpeppers

Repro updated; cmd is the new console app project. Reference chain is: cmd -- (proj. ref.) --> lib1 -- (bin. ref.) --> lib2. If you run below, lib2 is copied into cmd's publish output.

dotnet build lib2 dotnet publish cmd --self-contained -r win-x64

ist-22 avatar Dec 13 '22 23:12 ist-22

Ok, I tracked this down to:

https://github.com/dotnet/msbuild/blob/a2490dd3f78cce4abc8f9e6f1b5268437332818f/src/Tasks/Microsoft.Common.CurrentVersion.targets#L2322

In the console app we see:

image

But in the Android app we see:

image

Putting this in app.csproj (main Android app) also works around the issue:

<PropertyGroup>
  <_ResolveReferenceDependencies>true</_ResolveReferenceDependencies>
</PropertyGroup>

Still figuring out what these settings are for, and how we can fix this.

jonathanpeppers avatar Dec 15 '22 17:12 jonathanpeppers

It appears we need this change in Microsoft.Android.Sdk.AssemblyResolution.targets:

   <Target Name="_ComputeFilesToPublishForRuntimeIdentifiers"
-      DependsOnTargets="_FixupIntermediateAssembly;ResolveReferences;ComputeFilesToPublish;$(_RunAotMaybe)"
+      DependsOnTargets="BuildOnlySettings;_FixupIntermediateAssembly;ResolveReferences;ComputeFilesToPublish;$(_RunAotMaybe)"
       Returns="@(ResolvedFileToPublish)">

The BuildOnlySettings target sets $(BuildingProject) to true, preventing $(_FindDependencies) from being set to false.

I need to write a regression test for this, but will have a PR shortly.

jonathanpeppers avatar Dec 15 '22 17:12 jonathanpeppers

The first attempt to fix this in xamarin/xamarin-android/main didn't work out. (It caused a different issue) Reopening to look into this further.

jonathanpeppers avatar Jan 22 '23 19:01 jonathanpeppers