# System.IO.Packaging not resolved correctly #1154

Closed
opened this Issue Jan 3, 2018 · 18 comments

Projects
None yet
7 participants

### Steps to Reproduce

We're having an issue with a Xamarin project, which as we added System.IO.Packaging 4.4.1 nuget package dependency, the reference is resolved as the ref/netstandard1.3 DLL, a reference assembly. It seems that because of that, the Xamarin app fails to start because this DLL does not get packaged, and so the app fails to start with this common xamarin error https://forums.xamarin.com/discussion/63584/android-could-not-load-assembly-xxx-during-startup-registration

There seems to be an issue open related to that dotnet/corefx#23830

### Expected Behavior

The application starts correctly.

### Version Information

VS 15.5.2
Xamarin 4.8
Xamarin.Android 8.1

VS bug #580833

### weshaggard commented Jan 3, 2018

 @marek-safar @akoeplinger does System.IO.Packaging exist in the Xamarin platform?
Contributor

### marek-safar commented Jan 3, 2018

 @weshaggard no, we thought as this is fully managed assembly and we never supported it we could just get it from nuget as netstandard1.x

### weshaggard commented Jan 3, 2018 • edited

 @marek-safar you're right this package doesn't have the Xamarian placeholders in it so it should be using the netstandard implementation. @alexdrl can you give more information on the error you are hitting? Such as which assembly cannot be loaded? Can you also verify what assembly is getting deployed with your application? I would expect the lib\netstandard1.3 or lib\netstandard2.0 library to be deployed.

Contributor

### jonpryor commented Jan 3, 2018

 This feels like a variation on Bug #57342 and other bugs that I vaguely recall seeing but can't readily find. @dellis1972: Do you remember anything more recent/specific? @alexdrl: Could you please provide the diagnostic build output of the packaging process for your app? msbuild /v:diag /t:SignAndroidPackage App.csproj > b.txt  Then upload b.txt "somewhere" (gist.github.com works).
Contributor

### jonpryor commented Jan 3, 2018

 Possibly related?

### alexdrl commented Jan 4, 2018

 @jonpryor This is the build log. https://gist.github.com/alexdrl/9b1e284b6227e02a3413cb209aa4de84

### alexdrl commented Jan 4, 2018

 @weshaggard This is the debug log that is displaying running the android app https://gist.github.com/alexdrl/39fb731fadd62d84fcd8ed2952e707e0
Contributor

### marek-safar commented Jan 4, 2018

 @alexdrl please attach full re-build log with verbosity level set to Diagnostic

### alexdrl commented Jan 4, 2018

 @marek-safar I uploaded the file to this temporary repo as this is huge for the gist to manage, it is located here https://github.com/alexdrl/msbuildlog/blob/master/cleanlog.zip
Contributor

### dellis1972 commented Jan 4, 2018

 @jonpryor looks like the fix we put in for ignoring reference assemblies is working . I see this following in the log file from above. warning : Ignoring D:\W\Packages\system.io.packaging\4.0.0\ref\netstandard1.3 as it is a Reference Assembly [D:\W\AR\RPQPrototype\HealthAndWelfare\UI\Mobile\XF\Main\Droid\XF.Main.Droid.csproj] So I guess we are correctly ignoring the reference assembly, but for some reason the actual assembly we need is not included in the list of resolved assemblies.
Contributor

### jonpryor commented Jan 4, 2018

 I'm not certain that we are ignoring the reference assembly:  BuildApk Task (TaskId:1229) ApkInputPath: obj\Debug\android\bin\packaged_resources (TaskId:1229) ... obj\Debug\android\assets\System.IO.Packaging.dll (TaskId:1229)  So we're finding a System.IO.Packaging.dll assembly, and copying into obj\Debug\android\assets. Where's it coming from? This is where MSBuild diagnostic output is wonderful, compared to xbuild... Task "BuildApk" (TaskId:1229) Task Parameter:AndroidNdkDirectory=C:\ProgramData\Microsoft\AndroidNDK64\android-ndk-r13b\ (TaskId:1229) Task Parameter:ApkInputPath=obj\Debug\android\bin\packaged_resources (TaskId:1229) Task Parameter:ApkOutputPath=obj\Debug\android\bin\RPQPrototype.Android.apk (TaskId:1229) Task Parameter:EmbedAssemblies=False (TaskId:1229) Task Parameter: ResolvedUserAssemblies= ... Task Parameter: EmbeddedNativeLibraryAssemblies= ... D:\W\Packages\system.io.packaging\4.0.0\ref\netstandard1.3\System.IO.Packaging.dll CopyLocal=false FusionName=System.IO.Packaging, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ImageRuntime=v4.0.30319 NuGetIsFrameworkReference=false NuGetPackageId=System.IO.Packaging NuGetPackageVersion=4.0.0 NuGetSourceType=Package OriginalItemSpec=D:\W\Packages\system.io.packaging\4.0.0\ref\netstandard1.3\System.IO.Packaging.dll Private=false ReferenceAssembly=D:\W\Packages\system.io.packaging\4.0.0\ref\netstandard1.3\System.IO.Packaging.dll ReferenceSourceTarget=ResolveAssemblyReference ResolvedFrom={RawFileName} Version=  That does not look right; @(ReferencePath) and/or @(ReferenceDependencyPaths) is hitting the reference assembly, not the actual assembly. Regardless, that doesn't answer where obj\Debug\android\assets\System.IO.Packaging.dll is coming from. Searching further backward... Task "LinkAssemblies" (TaskId:1189) Task Parameter:UseSharedRuntime=true (TaskId:1189) Task Parameter:MainAssembly=obj\Debug\android\assets\ADDInformatica.RPQPrototype.HealthAndWelfare.UI.Mobile.XF.Main.Droid.dll (TaskId:1189) Task Parameter:OutputDirectory=obj\Debug\linkdst\ (TaskId:1189) Task Parameter:OptionalDestinationDirectory=obj\Debug\android\assets\ (TaskId:1189) Task Parameter:LinkMode=None (TaskId:1189) Task Parameter:LinkDescriptions=LinkDescription.xml (TaskId:1189) Task Parameter:LinkOnlyNewerThan=obj\Debug\link.flag (TaskId:1189) Task Parameter: ResolvedAssemblies= ... D:\W\Packages\system.io.packaging\4.0.0\ref\netstandard1.3\System.IO.Packaging.dll  The  task (optionally) links the assemblies -- LinkMode=None here, so no linking is performed -- and copies the assemblies into obj\Debug\android\assets. We thus infer that @(ResolvedAssemblies) erroneously contains the reference assembly. We may be emitting the warning about ignoring a reference assembly, but notice that we're ignoring netstandard1.3, not System.IO.Packaging.dll. It's System.IO.Packaging.dll which is causing problems. @(ResolvedAssemblies) is set by the  task, and we see that @(FIlteredAssemblies) contains the reference assembly: Task "ResolveAssemblies" (TaskId:1169) Task Parameter: Assemblies= ... D:\W\Packages\system.io.packaging\4.0.0\ref\netstandard1.3\System.IO.Packaging.dll  Unfortunately, it appears that our creation of @(FilteredAssemblies) removes the item metadata, so we don't see any metadata within the above fragment. @(FilteredAssemblies) in turn comes from @(ReferenceCopyLocalPaths) and @(ReferencePath). Unfortunately, I can't quickly find where System.IO.Packaging.dll is coming from to be located within either @(ReferenceCopyLocalPaths) or @(ReferencePath).

Closed

Closed

Closed

Open

Contributor

### dellis1972 commented Jan 23, 2018

 Some more informations. It looks like the required target ResolvePackageDependenciesForBuild is not built. This is probably because it is part of the Microsoft.NET.Sdk.targets. Since android (and iOS) projects do not use the new project format I suspect that those targets are not being imported. They are then never run, so we end up with the wrong references. @radical might be able to confirm this. I'm trying to see what we need to do to add this to android.

Closed

Closed

### ConX-Ryan commented Feb 12, 2018

 what is the estimated working timeline on fixing this and the downstream issues? 1196 Xamarin Forms with .NETStandard 2.0 is DOA at the moment
Contributor

### dellis1972 commented Feb 12, 2018

 @ConX-Ryan from my understanding this is a problem in the MSbuild NetStandard targets so this will probably be tracked on Microsoft/msbuild#2776. @radical can you confirm that is the case?

Closed

Merged

### johnwmcintosh commented Feb 26, 2018

 I'm having this problem with EF Core 2.0.1 as described here https://stackoverflow.com/questions/48956433/ef-core-2-0-1-unsafe-in-xamarin-android @JonDouglas asked I post a "reaction" here. Not sure what that means so I'm just using a comment.

### jonpryor added a commit that referenced this issue Feb 27, 2018

 [Xamarin.Android.Build.Tasks] Improve .NET Standard Support (#1185) 
Context: #1154

This PR brings in changes from xamarin/xamarin-macios#2643 and
xamarin/xamarin-macios#2731 to improve our .NET Standard support.
While this does not fix the packaging problem in #1154 it will give
us parity with the iOS code base.
 f988952 

### jonpryor added a commit that referenced this issue Feb 27, 2018

 [Xamarin.Android.Build.Tasks] Improve .NET Standard Support (#1185) 
Context: #1154

This PR brings in changes from xamarin/xamarin-macios#2643 and
xamarin/xamarin-macios#2731 to improve our .NET Standard support.
While this does not fix the packaging problem in #1154 it will give
us parity with the iOS code base.
 2d315d7 

### dellis1972 added a commit to dellis1972/java.interop that referenced this issue Mar 5, 2018

 [Java.Interop.Tools.Cecil] Change DirectoryAssemblyResolver to allow … 
…forced loading.

Context xamarin/xamarin-android#1154

One of the problems we currently face is that our build system
resolves ref netstandard libraries. With the current cache
system, onces an assembly has been loaded into the Cecil cache
it only ever uses that assembly. We might need to replace the
current cached version with a new one if we detect a ref and
need to reload the lib.
 f8be593 

Merged

### dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Mar 5, 2018

 [Xamarin.Android.Build.Tasks] Better support for netstandard libraries. 
Fixes xamarin#1154, xamarin#1162

Netstandard packages sometimes ship with both reference and
implementation assemblies. The Nuget build task ResolveNuGetPackageAssets
only resolves the ref version of the assemblies. There does
not seem to be away way to FORCE Nuget to resolve the lib one.
How .net Core manages to do this is still a mistery. That said
the Nuget ResolveNuGetPackageAssets does give us a hint as to
how to use the project.assets.json file to figure out what
lib version of the package we should be including.

This commit reworks ResolveAssemblies to attempt to map the
ref to a lib if we find a Referenece Assembly. Historically
we just issue a warning (which will probably be ignored), but
now we will use the project.assets.json file to find the
implementation version of the ref assembly.

We need to be using NewtonSoft.Json since it provides a decent
API for querying json. We make use of the Nuget build properties
$(ProjectLockFile) for the location of the project.assets.json , $(NuGetPackageRoot) for the root folder of the Nuget packages
and $(NuGetTargetMoniker) and $(_NuGetTargetFallbackMoniker)
for resolving which TargetFrameworks we are looking for. All of these
properties should be set by Nuget. If they are not we should fallback
to the default behaviour and just issue the warning.

{
"version": 3,
"targets": {
"MonoAndroid,Version=v8.1": {
"System.IO.Packaging/4.4.0": {
"type": "package",
"compile": {
"ref/netstandard1.3/System.IO.Packaging.dll": {}
},
"runtime": {
"lib/netstandard1.3/System.IO.Packaging.dll": {}
}
},
}
}
}

The code above is a cut down sample of the project.assets.json. So our
code will first resolve the targets. We use $(NuGetTargetMoniker) to do this. For an android project this should have a value of MonoAndroid,Version=v8.1. Note we do NOT need to worry about the version here. When Nuget restores the packages it creates the file so it will use the correct version. Next we try to find the System.IO.Packaging/4.4.0. My first throught was to use the version of the reference assembly we just loaded. But in this package even though the nuget version was 4.4.0 the assembly versioin was 4.0.2 .. so not helpful. So we need to just search for the items starting with System.IO.Packaging. Next is to look for the runtime item and then finally the value of that. Once we have resolved the path we need to then combine that with the $(NuGetPackageRoot) to get the
full path to the new library. If at any point during all of this code
we don't get what we expect (i.e a null) we should abort and just issue
the warning.

The only real concern with this is if the format of the project.assets.json
file changes. It is not ment to be edited by a human so there is the
possibiltity that the Nuget team will decide to either change the schema or
even migrate to a new file format.
 b0c0795 

Merged

Contributor

### jonpryor commented Mar 5, 2018

 @dellis1972: This is thought provoking: xamarin/xamarin-macios#3199 (comment) With a .NET Core project, for example, there are two steps: build and publish. The build target compiles against the ref assembly. The publish target will result in the lib assembly being copied to the publish directory so it can be used at runtime. Should we follow suite, such that our "Build" step can use reference assemblies, while the "Publish" step acquires and uses the actual assemblies? Can we follow suite? Is such a change supportable by our build process?
Contributor

### dellis1972 commented Mar 5, 2018

 ResolveAssemblies is what we use to pull together the list of assemblies we need to package. See #1356

### jonpryor added a commit to xamarin/java.interop that referenced this issue Mar 5, 2018

 [Java.Interop.Tools.Cecil] Change DirectoryAssemblyResolver to allow … 
…forced loading. (#270)

Context: xamarin/xamarin-android#1154
Context: xamarin/xamarin-android#1356

One of the problems we currently face is that our build system
resolves ref netstandard libraries. With the current cache
system, onces an assembly has been loaded into the Cecil cache
it only ever uses that assembly. We might need to replace the
current cached version with a new one if we detect a ref and
need to reload the lib.
 c6aa720 

### dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Mar 6, 2018

 [Xamarin.Android.Build.Tasks] Better support for netstandard libraries. 
Fixes xamarin#1154, xamarin#1162

Netstandard packages sometimes ship with both reference and
implementation assemblies. The Nuget build task ResolveNuGetPackageAssets
only resolves the ref version of the assemblies. There does
not seem to be away way to FORCE Nuget to resolve the lib one.
How .net Core manages to do this is still a mistery. That said
the Nuget ResolveNuGetPackageAssets does give us a hint as to
how to use the project.assets.json file to figure out what
lib version of the package we should be including.

This commit reworks ResolveAssemblies to attempt to map the
ref to a lib if we find a Referenece Assembly. Historically
we just issue a warning (which will probably be ignored), but
now we will use the project.assets.json file to find the
implementation version of the ref assembly.

We need to be using NewtonSoft.Json since it provides a decent
API for querying json. We make use of the Nuget build properties
$(ProjectLockFile) for the location of the project.assets.json , $(NuGetPackageRoot) for the root folder of the Nuget packages
and $(NuGetTargetMoniker) and $(_NuGetTargetFallbackMoniker)
for resolving which TargetFrameworks we are looking for. All of these
properties should be set by Nuget. If they are not we should fallback
to the default behaviour and just issue the warning.

{
"version": 3,
"targets": {
"MonoAndroid,Version=v8.1": {
"System.IO.Packaging/4.4.0": {
"type": "package",
"compile": {
"ref/netstandard1.3/System.IO.Packaging.dll": {}
},
"runtime": {
"lib/netstandard1.3/System.IO.Packaging.dll": {}
}
},
}
}
}

The code above is a cut down sample of the project.assets.json. So our
code will first resolve the targets. We use $(NuGetTargetMoniker) to do this. For an android project this should have a value of MonoAndroid,Version=v8.1. Note we do NOT need to worry about the version here. When Nuget restores the packages it creates the file so it will use the correct version. Next we try to find the System.IO.Packaging/4.4.0. My first throught was to use the version of the reference assembly we just loaded. But in this package even though the nuget version was 4.4.0 the assembly versioin was 4.0.2 .. so not helpful. So we need to just search for the items starting with System.IO.Packaging. Next is to look for the runtime item and then finally the value of that. Once we have resolved the path we need to then combine that with the $(NuGetPackageRoot) to get the
full path to the new library. If at any point during all of this code
we don't get what we expect (i.e a null) we should abort and just issue
the warning.

The only real concern with this is if the format of the project.assets.json
file changes. It is not ment to be edited by a human so there is the
possibiltity that the Nuget team will decide to either change the schema or
even migrate to a new file format.
 0a4b493 

### dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Mar 9, 2018

 [Xamarin.Android.Build.Tasks] Better support for netstandard libraries. 
Fixes xamarin#1154, xamarin#1162

Netstandard packages sometimes ship with both reference and
implementation assemblies. The Nuget build task ResolveNuGetPackageAssets
only resolves the ref version of the assemblies. There does
not seem to be away way to FORCE Nuget to resolve the lib one.
How .net Core manages to do this is still a mistery. That said
the Nuget ResolveNuGetPackageAssets does give us a hint as to
how to use the project.assets.json file to figure out what
lib version of the package we should be including.

This commit reworks ResolveAssemblies to attempt to map the
ref to a lib if we find a Referenece Assembly. Historically
we just issue a warning (which will probably be ignored), but
now we will use the project.assets.json file to find the
implementation version of the ref assembly.

We need to be using NewtonSoft.Json since it provides a decent
API for querying json. We make use of the Nuget build properties
$(ProjectLockFile) for the location of the project.assets.json , $(NuGetPackageRoot) for the root folder of the Nuget packages
and $(NuGetTargetMoniker) and $(_NuGetTargetFallbackMoniker)
for resolving which TargetFrameworks we are looking for. All of these
properties should be set by Nuget. If they are not we should fallback
to the default behaviour and just issue the warning.

{
"version": 3,
"targets": {
"MonoAndroid,Version=v8.1": {
"System.IO.Packaging/4.4.0": {
"type": "package",
"compile": {
"ref/netstandard1.3/System.IO.Packaging.dll": {}
},
"runtime": {
"lib/netstandard1.3/System.IO.Packaging.dll": {}
}
},
}
}
}

The code above is a cut down sample of the project.assets.json. So our
code will first resolve the targets. We use $(NuGetTargetMoniker) to do this. For an android project this should have a value of MonoAndroid,Version=v8.1. Note we do NOT need to worry about the version here. When Nuget restores the packages it creates the file so it will use the correct version. Next we try to find the System.IO.Packaging/4.4.0. My first throught was to use the version of the reference assembly we just loaded. But in this package even though the nuget version was 4.4.0 the assembly versioin was 4.0.2 .. so not helpful. So we need to just search for the items starting with System.IO.Packaging. Next is to look for the runtime item and then finally the value of that. Once we have resolved the path we need to then combine that with the $(NuGetPackageRoot) to get the
full path to the new library. If at any point during all of this code
we don't get what we expect (i.e a null) we should abort and just issue
the warning.

The only real concern with this is if the format of the project.assets.json
file changes. It is not ment to be edited by a human so there is the
possibiltity that the Nuget team will decide to either change the schema or
even migrate to a new file format.
 ac2fee7 

### dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Mar 9, 2018

 [Xamarin.Android.Build.Tasks] Better support for netstandard libraries. 
Fixes xamarin#1154, xamarin#1162

Netstandard packages sometimes ship with both reference and
implementation assemblies. The Nuget build task ResolveNuGetPackageAssets
only resolves the ref version of the assemblies. There does
not seem to be away way to FORCE Nuget to resolve the lib one.
How .net Core manages to do this is still a mistery. That said
the Nuget ResolveNuGetPackageAssets does give us a hint as to
how to use the project.assets.json file to figure out what
lib version of the package we should be including.

This commit reworks ResolveAssemblies to attempt to map the
ref to a lib if we find a Referenece Assembly. Historically
we just issue a warning (which will probably be ignored), but
now we will use the project.assets.json file to find the
implementation version of the ref assembly.

We need to be using Nuget.ProjectModel since it an API for
querying the project.assets.json. We make use of the Nuget build properties
$(ProjectLockFile) for the location of the project.assets.json , $(NuGetPackageRoot) for the root folder of the Nuget packages
and $(NuGetTargetMoniker) for resolving which TargetFrameworks we are looking for. All of these properties should be set by Nuget. If they are not we should fallback to the default behaviour and just issue the warning. { "version": 3, "targets": { "MonoAndroid,Version=v8.1": { "System.IO.Packaging/4.4.0": { "type": "package", "compile": { "ref/netstandard1.3/System.IO.Packaging.dll": {} }, "runtime": { "lib/netstandard1.3/System.IO.Packaging.dll": {} } }, } } } The code above is a cut down sample of the project.assets.json. So our code will first resolve the targets. We use $(NuGetTargetMoniker) to
do this. For an android project this should have a value of
MonoAndroid,Version=v8.1. Note we do NOT need to worry about the version
here. When Nuget restores the packages it creates the file so it will
use the correct version.
Next we try to find the System.IO.Packaging. We need to look at the
lockFile.Libraries to get information about the install path in the
Nuget folder, and then target.Libraries to pick out the  runtime
item.
Once we have resolved the path we need to then combine that with the
$(NuGetPackageRoot) to get the full path to the new library. If at any point during all of this code we don't get what we expect (i.e a null) we should abort and just issue the warning. The only real concern with this is if the format of the project.assets.json file changes. It is not ment to be edited by a human so there is the possibiltity that the Nuget team will decide to either change the schema or even migrate to a new file format. Hopefully we can just update the Nuget nuggets if that happens.  4bddb52  ### jonpryor added the vs-sync label Mar 12, 2018 ### dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Mar 13, 2018  [Xamarin.Android.Build.Tasks] Better support for netstandard libraries.  Fixes xamarin#1154, xamarin#1162 Netstandard packages sometimes ship with both reference and implementation assemblies. The Nuget build task ResolveNuGetPackageAssets only resolves the ref version of the assemblies. There does not seem to be away way to FORCE Nuget to resolve the lib one. How .net Core manages to do this is still a mistery. That said the Nuget ResolveNuGetPackageAssets does give us a hint as to how to use the project.assets.json file to figure out what lib version of the package we should be including. This commit reworks ResolveAssemblies to attempt to map the ref to a lib if we find a Referenece Assembly. Historically we just issue a warning (which will probably be ignored), but now we will use the project.assets.json file to find the implementation version of the ref assembly. We need to be using Nuget.ProjectModel since it an API for querying the project.assets.json. We make use of the Nuget build properties $(ProjectLockFile) for the location of the project.assets.json
, $(NuGetPackageRoot) for the root folder of the Nuget packages and $(NuGetTargetMoniker) for resolving which TargetFrameworks
we are looking for. All of these properties should be set by Nuget.
If they are not we should fallback to the default behaviour and just issue the warning.

{
"version": 3,
"targets": {
"MonoAndroid,Version=v8.1": {
"System.IO.Packaging/4.4.0": {
"type": "package",
"compile": {
"ref/netstandard1.3/System.IO.Packaging.dll": {}
},
"runtime": {
"lib/netstandard1.3/System.IO.Packaging.dll": {}
}
},
}
}
}

The code above is a cut down sample of the project.assets.json. So our
code will first resolve the targets. We use $(NuGetTargetMoniker) to do this. For an android project this should have a value of MonoAndroid,Version=v8.1. Note we do NOT need to worry about the version here. When Nuget restores the packages it creates the file so it will use the correct version. Next we try to find the System.IO.Packaging. We need to look at the lockFile.Libraries to get information about the install path in the Nuget folder, and then target.Libraries to pick out the runtime item. Once we have resolved the path we need to then combine that with the $(NuGetPackageRoot) to get the full path to the new library. If at any
point during all of this code we don't get what we expect (i.e a null) we
should abort and just issue the warning.

The only real concern with this is if the format of the project.assets.json
file changes. It is not ment to be edited by a human so there is the
possibiltity that the Nuget team will decide to either change the schema or
even migrate to a new file format. Hopefully we can just update the Nuget
nuggets if that happens.
 2b7e2e0 

### dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Mar 15, 2018

 [Xamarin.Android.Build.Tasks] Better support for netstandard libraries. 
Fixes xamarin#1154, xamarin#1162

Netstandard packages sometimes ship with both reference and
implementation assemblies. The Nuget build task ResolveNuGetPackageAssets
only resolves the ref version of the assemblies. There does
not seem to be away way to FORCE Nuget to resolve the lib one.
How .net Core manages to do this is still a mistery. That said
the Nuget ResolveNuGetPackageAssets does give us a hint as to
how to use the project.assets.json file to figure out what
lib version of the package we should be including.

This commit reworks ResolveAssemblies to attempt to map the
ref to a lib if we find a Referenece Assembly. Historically
we just issue a warning (which will probably be ignored), but
now we will use the project.assets.json file to find the
implementation version of the ref assembly.

We need to be using Nuget.ProjectModel since it an API for
querying the project.assets.json. We make use of the Nuget build properties
$(ProjectLockFile) for the location of the project.assets.json , $(NuGetPackageRoot) for the root folder of the Nuget packages
and $(NuGetTargetMoniker) for resolving which TargetFrameworks we are looking for. All of these properties should be set by Nuget. If they are not we should fallback to the default behaviour and just issue the warning. { "version": 3, "targets": { "MonoAndroid,Version=v8.1": { "System.IO.Packaging/4.4.0": { "type": "package", "compile": { "ref/netstandard1.3/System.IO.Packaging.dll": {} }, "runtime": { "lib/netstandard1.3/System.IO.Packaging.dll": {} } }, } } } The code above is a cut down sample of the project.assets.json. So our code will first resolve the targets. We use $(NuGetTargetMoniker) to
do this. For an android project this should have a value of
MonoAndroid,Version=v8.1. Note we do NOT need to worry about the version
here. When Nuget restores the packages it creates the file so it will
use the correct version.
Next we try to find the System.IO.Packaging. We need to look at the
lockFile.Libraries to get information about the install path in the
Nuget folder, and then target.Libraries to pick out the  runtime
item.
Once we have resolved the path we need to then combine that with the
$(NuGetPackageRoot) to get the full path to the new library. If at any point during all of this code we don't get what we expect (i.e a null) we should abort and just issue the warning. The only real concern with this is if the format of the project.assets.json file changes. It is not ment to be edited by a human so there is the possibiltity that the Nuget team will decide to either change the schema or even migrate to a new file format. Hopefully we can just update the Nuget nuggets if that happens.  db12884  ### dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Mar 20, 2018  [Xamarin.Android.Build.Tasks] Better support for netstandard libraries.  Fixes xamarin#1154, xamarin#1162 Netstandard packages sometimes ship with both reference and implementation assemblies. The Nuget build task ResolveNuGetPackageAssets only resolves the ref version of the assemblies. There does not seem to be away way to FORCE Nuget to resolve the lib one. How .net Core manages to do this is still a mistery. That said the Nuget ResolveNuGetPackageAssets does give us a hint as to how to use the project.assets.json file to figure out what lib version of the package we should be including. This commit reworks ResolveAssemblies to attempt to map the ref to a lib if we find a Referenece Assembly. Historically we just issue a warning (which will probably be ignored), but now we will use the project.assets.json file to find the implementation version of the ref assembly. We need to be using Nuget.ProjectModel since it an API for querying the project.assets.json. We make use of the Nuget build properties $(ProjectLockFile) for the location of the project.assets.json
, $(NuGetPackageRoot) for the root folder of the Nuget packages and $(NuGetTargetMoniker) for resolving which TargetFrameworks
we are looking for. All of these properties should be set by Nuget.
If they are not we should fallback to the default behaviour and just issue the warning.

{
"version": 3,
"targets": {
"MonoAndroid,Version=v8.1": {
"System.IO.Packaging/4.4.0": {
"type": "package",
"compile": {
"ref/netstandard1.3/System.IO.Packaging.dll": {}
},
"runtime": {
"lib/netstandard1.3/System.IO.Packaging.dll": {}
}
},
}
}
}

The code above is a cut down sample of the project.assets.json. So our
code will first resolve the targets. We use $(NuGetTargetMoniker) to do this. For an android project this should have a value of MonoAndroid,Version=v8.1. Note we do NOT need to worry about the version here. When Nuget restores the packages it creates the file so it will use the correct version. Next we try to find the System.IO.Packaging. We need to look at the lockFile.Libraries to get information about the install path in the Nuget folder, and then target.Libraries to pick out the runtime item. Once we have resolved the path we need to then combine that with the $(NuGetPackageRoot) to get the full path to the new library. If at any
point during all of this code we don't get what we expect (i.e a null) we
should abort and just issue the warning.

The only real concern with this is if the format of the project.assets.json
file changes. It is not ment to be edited by a human so there is the
possibiltity that the Nuget team will decide to either change the schema or
even migrate to a new file format. Hopefully we can just update the Nuget
nuggets if that happens.
 81f04dd 

### jonpryor added a commit that referenced this issue Mar 21, 2018

 Bump to Java.Interop/master/56e978f (#1445) 
Fixes: #1396

Context: #1154
Context: #1356
Context: #1418
 1826ec2 

### dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Mar 21, 2018

 [Xamarin.Android.Build.Tasks] Better support for netstandard libraries. 
Fixes xamarin#1154, xamarin#1162

Netstandard packages sometimes ship with both reference and
implementation assemblies. The Nuget build task ResolveNuGetPackageAssets
only resolves the ref version of the assemblies. There does
not seem to be away way to FORCE Nuget to resolve the lib one.
How .net Core manages to do this is still a mistery. That said
the Nuget ResolveNuGetPackageAssets does give us a hint as to
how to use the project.assets.json file to figure out what
lib version of the package we should be including.

This commit reworks ResolveAssemblies to attempt to map the
ref to a lib if we find a Referenece Assembly. Historically
we just issue a warning (which will probably be ignored), but
now we will use the project.assets.json file to find the
implementation version of the ref assembly.

We need to be using Nuget.ProjectModel since it an API for
querying the project.assets.json. We make use of the Nuget build properties
$(ProjectLockFile) for the location of the project.assets.json , $(NuGetPackageRoot) for the root folder of the Nuget packages
and $(NuGetTargetMoniker) for resolving which TargetFrameworks we are looking for. All of these properties should be set by Nuget. If they are not we should fallback to the default behaviour and just issue the warning. { "version": 3, "targets": { "MonoAndroid,Version=v8.1": { "System.IO.Packaging/4.4.0": { "type": "package", "compile": { "ref/netstandard1.3/System.IO.Packaging.dll": {} }, "runtime": { "lib/netstandard1.3/System.IO.Packaging.dll": {} } }, } } } The code above is a cut down sample of the project.assets.json. So our code will first resolve the targets. We use $(NuGetTargetMoniker) to
do this. For an android project this should have a value of
MonoAndroid,Version=v8.1. Note we do NOT need to worry about the version
here. When Nuget restores the packages it creates the file so it will
use the correct version.
Next we try to find the System.IO.Packaging. We need to look at the
lockFile.Libraries to get information about the install path in the
Nuget folder, and then target.Libraries to pick out the  runtime
item.
Once we have resolved the path we need to then combine that with the
\$(NuGetPackageRoot) to get the full path to the new library. If at any
point during all of this code we don't get what we expect (i.e a null) we
should abort and just issue the warning.

The only real concern with this is if the format of the project.assets.json
file changes. It is not ment to be edited by a human so there is the
possibiltity that the Nuget team will decide to either change the schema or
even migrate to a new file format. Hopefully we can just update the Nuget
nuggets if that happens.
 536120c 

### jonpryor added a commit that referenced this issue Mar 21, 2018

 [Xamarin.Android.Build.Tasks] Better support for netstandard librarie… 
…s. (#1356)

Fixes: #1154
Fixes: #1162

NetStandard packages sometimes ship with both reference and
implementation assemblies. The NuGet build task
<ResolveNuGetPackageAssets/> only resolves the ref version of the
assemblies. There does not seem to be away way to *force* NuGet to
resolve the lib one.

This commit reworks the <ResolveAssemblies/> task to attempt to map
the ref to a lib if we find a Referenece Assembly. Historically
we just issue a warning (which will probably be ignored), but
now we will use the project.assets.json file to find the
implementation version of the ref assembly, by using the
NuGet.ProjectModel package to find the library which is associated
with a reference assembly.

We thus "ignore" reference assemblies, using the "referenced"/"real"
assemblies instead, to ensure that our existing build process
continues to generate usable packages.

*Note*: An alternative approach would be to "embrace" reference
assemblies, allowing them to be used in the build. This doesn't
currently work with our build system, as we assume assemblies will
contain native libraries, Android resources, and other artifacts
which must be extracted at build time, and reference assemblies will
not contain these artifacts.

We would like to explore the "embrace" strategy, but this will
require far more effort to support.
 f7c942d 

### jonpryor added a commit that referenced this issue Mar 21, 2018

 [Xamarin.Android.Build.Tasks] Better support for netstandard librarie… 
…s. (#1356)

Fixes: #1154
Fixes: #1162

NetStandard packages sometimes ship with both reference and
implementation assemblies. The NuGet build task
<ResolveNuGetPackageAssets/> only resolves the ref version of the
assemblies. There does not seem to be away way to *force* NuGet to
resolve the lib one.

This commit reworks the <ResolveAssemblies/> task to attempt to map
the ref to a lib if we find a Referenece Assembly. Historically
we just issue a warning (which will probably be ignored), but
now we will use the project.assets.json file to find the
implementation version of the ref assembly, by using the
NuGet.ProjectModel package to find the library which is associated
with a reference assembly.

We thus "ignore" reference assemblies, using the "referenced"/"real"
assemblies instead, to ensure that our existing build process
continues to generate usable packages.

*Note*: An alternative approach would be to "embrace" reference
assemblies, allowing them to be used in the build. This doesn't
currently work with our build system, as we assume assemblies will
contain native libraries, Android resources, and other artifacts
which must be extracted at build time, and reference assemblies will
not contain these artifacts.

We would like to explore the "embrace" strategy, but this will
require far more effort to support.
 c7b9a50 

### jonpryor added a commit to xamarin/java.interop that referenced this issue Mar 22, 2018

 [Java.Interop.Tools.Cecil] Change DirectoryAssemblyResolver to allow … 
…forced loading. (#270)

Context: xamarin/xamarin-android#1154
Context: xamarin/xamarin-android#1356

One of the problems we currently face is that our build system
resolves ref netstandard libraries. With the current cache
system, onces an assembly has been loaded into the Cecil cache
it only ever uses that assembly. We might need to replace the
current cached version with a new one if we detect a ref and
need to reload the lib.
 4e1965d 

### jonpryor added a commit that referenced this issue Mar 22, 2018

 Bump to Java.Interop/d15-7/4e1965d5 
Context: #1154
Context: #1356

Commit c7b9a50 [broke the build][0], because we neglected to
cherry-pick a dependency from Java.Interop (doh!):

[0]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android-d15-7/13/

DirectoryAssemblyResolver.Load(string fileName, bool forceLoad)
overload, which should fix the above error.
 2901bfc