The ResolveAssemblies
task hits "error XA2002: Can not resolve reference" if a NuGet <dependency/>
from a .nuspec file uses exclude="Compile"
#2674
Labels
Area: App+Library Build
Issues when building Library projects or Application projects.
bug
Component does not function as intended.
Milestone
The original motivation for this investigation was #2534. That exact example of the problem was resolved another way in the Xamarin.Android version included with Visual Studio 2019 Preview 2. (The problematic System.Memory NuGet package was already scheduled to be imported into the Mono base class libraries, so the latest Xamarin.Android now provides its own System.Memory.dll facade assembly, circumventing the NuGet package problem. On top of that, the latest System.Memory NuGet package version 4.5.2 switched away from using the problematic
exclude="Compile"
attribute in the .nuspec file.)But the general problem remains, and it could affect other NuGet packages in the future if the usage of reference assemblies in NuGet packages becomes more common.
Steps to Reproduce
Unzip the attached test case.
Change directory in a Developer Command Prompt into the NugetExcludeCompile\AndroidApp1 directory.
Attempt to build the project, restoring the custom NuGet packages along the way:
Expected Behavior
The project builds successfully. Also, building the
SignAndroidPackage
target should produce an APK that includes the full (not the reference assembly) version of NetStandardLibrary1.dll. That way, when the app runs on device or emulator, thenew NetStandardLibrary2.Class1 ()
statement will complete without error.The included NetCoreConsoleApp1 and NetFrameworkConsoleApp1 projects demonstrate the expected behavior.
Actual Behavior
The build fails during the
ResolveAssemblies
task:Investigation
The problem is that
ResolveAssemblies
does not look up the NetStandardLibrary1.dll dependency of NetStandardLibrary2.dll using theruntime
entry from the obj\project.assets.json file. This isn't a problem for most NuGet packages because thecompile
entry in obj\project.assets.json causes the assembly dependency to be included directly in theFilteredAssemblies
item. But with this test case, the NuGet restore process has correctly set thecompile
entry to the_._
placeholder value:Why is the
_._
placeholder value correct?It is correct because NetStandardLibrary2\Contoso.Test.NetStandardLibrary2.nuspec file uses the
exclude="Compile"
attribute to specify that Contoso.Test.NetStandardLibrary1 is not a compile dependency for projects consuming Contoso.Test.NetStandardLibrary2:Is it valid for the .nuspec file to use
exclude="Compile"
for Contoso.Test.NetStandardLibrary1?I believe so, yes. The
Csc
task does not require NetStandardLibrary1.dll to build AndroidApp1 successfully. (TheCsc
task completes successfully during step 3 of the steps to reproduce.) It therefore seems acceptable or even appropriate for the .nuspec file from NetStandardLibrary2 to specify that the NetStandardLibrary1.dll assembly is not required for compilation.Potential Fixes
Based on the story up to this point, it seems that the special handling of reference assemblies in
ResolveAssemblies
might need to be extended so that it not only looks up and adds theruntime
assembly for each reference assembly, but also looks up any correspondingdependencies
entries in the obj\project.assets.json lock file and adds theruntime
assemblies for each of those dependencies too.Another question to consider might be how .NET Framework console projects determine which assemblies to copy into the output bin directory for
PackageReference
items. That mechanism successfully copies NetStandardLibrary1.dll to the bin directory. Could that mechanism be re-used for Xamarin.Android, or does theResolveAssemblies
task do some other special things that are unique to Xamarin.Android? (From a quick look atResolveAssemblies
, I see that one thing that might require special handling is .mdb files.)Version Information
Visual Studio 2019 Preview
Xamarin.Android SDK 9.1.103.8 (HEAD/9a258c43)
Log File
msbuild.binlog
Steps to Modify the Custom NuGet Packages
Modifying the custom NuGet packages is slightly unusual compared to normal app and library builds, so here are the steps for that in case they might come in handy.
Delete the *.nuget.* and project.assets.json files from the obj directory of the AndroidApp1 project (or delete the whole obj directory).
Delete any cached copies of the NuGet packages from %USERPROFILE%\.nuget\packages. Otherwise, the NuGet restore process will use the cached copies.
In a Developer Command Prompt, change directory into NetStandardLibrary2 (for example).
Build the
Pack
target, supplying the .nuspec file in theNuspecFile
property:Repeat step 3 of the steps to reproduce to restore the NuGet packages into the AndroidApp1 project and build it.
The text was updated successfully, but these errors were encountered: