-
Notifications
You must be signed in to change notification settings - Fork 526
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Xamarin.Android.Build.Tasks] <FilterAssemblies/> support missing TFI #2958
[Xamarin.Android.Build.Tasks] <FilterAssemblies/> support missing TFI #2958
Conversation
I want to look at |
6613f3f
to
5ca58d1
Compare
// Fallback to looking at references | ||
if (string.IsNullOrEmpty (targetFrameworkIdentifier) && !string.IsNullOrEmpty (FallbackReference)) { | ||
Log.LogDebugMessage ($"Checking references for: {assemblyItem.ItemSpec}"); | ||
foreach (var handle in reader.AssemblyReferences) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to be recursive? As-is, this will only handle direct assembly references.
For example, Xamarin.Forms.Core.dll
references Xamarin.Forms.Platform.dll
-- which exists for multiple platforms -- and the MonoAndroid10/Xamarin.Forms.Platform.dll
references Xamarin.Forms.Platform.Android.dll
which references Mono.Android.dll
. (Deep breath.)
Thus, should we effectively emit this, i.e. "recursively" resolve references?
<ItemGroup>
<_ResolvedUserAssemblies Include="Xamarin.Forms">
<TargetFrameworkIdentifier>MonoAndroid</TargetFrameworkIdentifier>
</ItemGroup>
...though then everything could then be treated as MonoAndroid profile assemblies, which feels like it would defeat the purpose.
Thus, how thorough do we need to be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have only found this one case where this [assembly:TargetFramework]
was missing... It was shipped to NuGet in 2015.
I built it from source: https://github.com/jamesmontemagno/CircleImageView-Xamarin.Android
And the assembly produced with VS 2019 has:
[assembly: TargetFramework("MonoAndroid,Version=v5.0", FrameworkDisplayName = "Xamarin.Android v5.0 Support")]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m overthinking this; Xamarin.Forms does not need to have %(TargetFrameworkIdentifier)
=MonoAndroid.
Reason being that while, indirectly, mythical type A
using Xamarin.Forms has a reference graph which eventually includes Mono.Android.dll
(via Xamarin.Forms.Platform.Android.dll
), A
cannot use any types from Mono.Android.dll
— even indirect inheritance! — without referencing it explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the commit message around this conversation 👍
5ca58d1
to
3ae293f
Compare
Context: https://www.nuget.org/packages/Refractored.Controls.CircleImageView/ Context: https://github.com/Azure-Samples/MyDriving The MyDriving sample app currently fails to build on master with: Resources/layout/fragment_profile.axml(2): error APT0000: attribute civ_border_width (aka com.microsoft.mydriving:civ_border_width) not found. The failure happens with both `aapt` and `aapt2`. This layout is using a custom view such as: <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:local="http://schemas.android.com/apk/res-auto"> ... <refractored.controls.CircleImageView local:civ_border_width="0dp" /> ... </ScrollView> This comes from the `Refractored.Controls.CircleImageView` NuGet package. In 5ec3e3a, I added a `<FilterAssemblies/>` MSBuild task that appears to be to blame. It is not returning `Refractored.Controls.CircleImageView.dll`, but it needs to! `Refractored.Controls.CircleImageView.dll` has no `[assembly: System.Runtime.Versioning.TargetFrameworkAttribute]`... // C:\src\des\MyDriving\packages\Refractored.Controls.CircleImageView.1.0.1\lib\MonoAndroid10\Refractored.Controls.CircleImageView.dll // Refractored.Controls.CircleImageView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null // Global type: <Module> // Architecture: x86 // Runtime: v4.0.30319 // Hash algorithm: SHA1 using Android.Runtime; using System.Reflection; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; [assembly: AssemblyTitle("Refractored.Controls.CircleImageView")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("2015 Refractored LLC/James Montemagno")] [assembly: AssemblyTrademark("")] [assembly: NamespaceMapping(Java = "de.hdodenhof.circleimageview", Managed = "Refractored.Controls")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: SecurityPermission(8, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] It is indeed a `MonoAndroid` assembly, since it references `Mono.Android.dll`. It is weird, though... ~~ What should we do? ~~ One idea is to look for `Mono.Android.dll` references in each assembly *instead* of `TargetFrameworkIdentifier`. Looking at the assemblies in Xamarin.Forms, there is a complication to this: * `Xamarin.Forms.Core.dll` (a NetStandard library) references * `Xamarin.Forms.Platform.dll` (a MonoAndroid library?) references * `Xamarin.Forms.Platform.Android.dll` But `Xamarin.Forms.Platform.dll` does not reference `Mono.Android.dll`? So then should we "recursively" look for any reference to `Mono.Android.dll` in a given dependency tree? I don't think so? This would include more assemblies than we want... In the above example `Xamarin.Forms.Core.dll` would get counted as a "MonoAndroid" assembly. ~~ Conclusion ~~ I think we should stick with `TargetFrameworkIdentifier`, and in the rare case it is missing look for a `Mono.Android.dll` reference for the single assembly. This seems like it is going to cover all cases to me, and we still will get good performance. So we will cover: * `Xamarin.Forms.Platform.dll` counted as a "MonoAndroid" assembly since it has a `TargetFrameworkIdentifier` (but no reference). * `Refractored.Controls.CircleImageView.dll` counted as a "MonoAndroid" assembly. It has no `TargetFrameworkIdentifier, but has a reference to `Mono.Android.dll`. Changes include: * `<FilterAssemblies/>` needs to also check for an assembly reference to `Mono.Android` as a fallback. * `<ResolveAssemblies/>` now adds a `%(MonoAndroidReference)=True` item metadata. * When creating the `@(_ResolvedUserMonoAndroidAssemblies)` item group, we also check for `%(MonoAndroidReference)=True`. I added a few tests to verify these scenarios.
3ae293f
to
71623cc
Compare
Context: https://www.nuget.org/packages/Refractored.Controls.CircleImageView/
Context: https://github.com/Azure-Samples/MyDriving
Context: #2934
The MyDriving sample app currently fails to build on master with:
The failure happens with both
aapt
andaapt2
.This layout is using a custom view such as:
This comes from the
Refractored.Controls.CircleImageView
NuGetpackage.
In 5ec3e3a, I added a
<FilterAssemblies/>
MSBuild task that appearsto be to blame. It is not returning
Refractored.Controls.CircleImageView.dll
, but it needs to!Refractored.Controls.CircleImageView.dll
has no[assembly: System.Runtime.Versioning.TargetFrameworkAttribute]
...It is indeed a
MonoAndroid
assembly, since it referencesMono.Android.dll
. It is weird, though...What should we do?
One idea is to look for
Mono.Android.dll
references in eachassembly instead of
TargetFrameworkIdentifier
.Looking at the assemblies in Xamarin.Forms, there is a complication to
this:
Xamarin.Forms.Core.dll
(a NetStandard library) referencesXamarin.Forms.Platform.dll
(a MonoAndroid library?) referencesXamarin.Forms.Platform.Android.dll
But
Xamarin.Forms.Platform.dll
does not referenceMono.Android.dll
?So then should we "recursively" look for any reference to
Mono.Android.dll
in a given dependency tree?I don't think so? This would include more assemblies than we want...
In the above example
Xamarin.Forms.Core.dll
would get counted as a"MonoAndroid" assembly.
Conclusion
I think we should stick with
TargetFrameworkIdentifier
, and in therare case it is missing look for a
Mono.Android.dll
reference forthe single assembly. This seems like it is going to cover all cases to
me, and we still will get good performance.
So we will cover:
Xamarin.Forms.Platform.dll
counted as a "MonoAndroid" assemblysince it has a
TargetFrameworkIdentifier
(but no reference).Refractored.Controls.CircleImageView.dll
counted as a"MonoAndroid" assembly. It has no
TargetFrameworkIdentifier, but has a reference to
Mono.Android.dll`.Changes include:
<FilterAssemblies/>
needs to also check for an assembly referenceto
Mono.Android
as a fallback.<ResolveAssemblies/>
now adds a%(MonoAndroidReference)=True
item metadata.
@(_ResolvedUserMonoAndroidAssemblies)
itemgroup, we also check for
%(MonoAndroidReference)=True
.I added a few tests to verify these scenarios.