-
Notifications
You must be signed in to change notification settings - Fork 526
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Xamarin.Android.Build.Tasks] <FilterAssemblies/> support missing TFI
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.
- Loading branch information
1 parent
28e1f93
commit 71623cc
Showing
7 changed files
with
181 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
...arin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/FilterAssembliesTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
using NUnit.Framework; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Net.Http; | ||
using System.Threading.Tasks; | ||
using Xamarin.Android.Tasks; | ||
using Xamarin.Tools.Zip; | ||
using TaskItem = Microsoft.Build.Utilities.TaskItem; | ||
|
||
namespace Xamarin.Android.Build.Tests | ||
{ | ||
[TestFixture] | ||
public class FilterAssembliesTests : BaseTest | ||
{ | ||
HttpClient httpClient = new HttpClient (); | ||
string tempDirectory; | ||
|
||
[SetUp] | ||
public void Setup () | ||
{ | ||
tempDirectory = Path.Combine (Path.GetTempPath (), Path.GetRandomFileName ()); | ||
Directory.CreateDirectory (tempDirectory); | ||
} | ||
|
||
[TearDown] | ||
public void TearDown () | ||
{ | ||
Directory.Delete (tempDirectory, recursive: true); | ||
} | ||
|
||
async Task<string> DownloadFromNuGet (string url) | ||
{ | ||
var response = await httpClient.GetAsync (url); | ||
response.EnsureSuccessStatusCode (); | ||
var temp = Path.Combine (tempDirectory, Path.GetRandomFileName ()); | ||
using (var httpStream = await response.Content.ReadAsStreamAsync ()) | ||
using (var fileStream = File.Create (temp)) { | ||
await httpStream.CopyToAsync (fileStream); | ||
} | ||
return temp; | ||
} | ||
|
||
async Task<string []> GetAssembliesFromNuGet (string url, string path) | ||
{ | ||
var assemblies = new List<string> (); | ||
var nuget = await DownloadFromNuGet (url); | ||
using (var zip = ZipArchive.Open (nuget, FileMode.Open)) { | ||
foreach (var entry in zip) { | ||
if (entry.FullName.StartsWith (path, StringComparison.OrdinalIgnoreCase) && | ||
entry.FullName.EndsWith (".dll", StringComparison.OrdinalIgnoreCase)) { | ||
var temp = Path.Combine (tempDirectory, Path.GetFileName (entry.NativeFullName)); | ||
assemblies.Add (temp); | ||
using (var fileStream = File.Create (temp)) { | ||
entry.Extract (fileStream); | ||
} | ||
} | ||
} | ||
} | ||
return assemblies.ToArray (); | ||
} | ||
|
||
string [] Run (params string [] assemblies) | ||
{ | ||
var task = new FilterAssemblies { | ||
BuildEngine = new MockBuildEngine (TestContext.Out), | ||
TargetFrameworkIdentifier = "MonoAndroid", | ||
FallbackReference = "Mono.Android", | ||
InputAssemblies = assemblies.Select (a => new TaskItem (a)).ToArray (), | ||
}; | ||
Assert.IsTrue (task.Execute (), "task.Execute() should have succeeded."); | ||
return task.OutputAssemblies.Select (a => Path.GetFileName (a.ItemSpec)).ToArray (); | ||
} | ||
|
||
[Test] | ||
public async Task CircleImageView () | ||
{ | ||
var assemblies = await GetAssembliesFromNuGet ( | ||
"https://www.nuget.org/api/v2/package/Refractored.Controls.CircleImageView/1.0.1", | ||
"lib/MonoAndroid10/"); | ||
var actual = Run (assemblies); | ||
var expected = new [] { "Refractored.Controls.CircleImageView.dll" }; | ||
CollectionAssert.AreEqual (expected, actual); | ||
} | ||
|
||
[Test] | ||
public async Task XamarinForms () | ||
{ | ||
var assemblies = await GetAssembliesFromNuGet ( | ||
"https://www.nuget.org/api/v2/package/Xamarin.Forms/3.6.0.220655", | ||
"lib/MonoAndroid90/"); | ||
var actual = Run (assemblies); | ||
var expected = new [] { | ||
"FormsViewGroup.dll", | ||
"Xamarin.Forms.Platform.Android.dll", | ||
"Xamarin.Forms.Platform.dll", | ||
}; | ||
CollectionAssert.AreEqual (expected, actual); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters