From d079a42e28d30797cd9a0b1c34a2fcb3e340c384 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Thu, 24 Aug 2017 03:21:21 +0100 Subject: [PATCH] [Xamarin.Android.Build.Tasks] Library project C# changes & Rebuilds (#764) Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=58865 Consider a project with an `App.csproj` and a referenced `Lib.csproj`. Not all changes to C# sources within `Lib.csproj` should require rebuilding and redeploying the `.apk` when Fast Deployment is enabled; only those that result in changes to Java Callable Wrappers should require rebuilding and redeploying the `.apk`. Unfortunately, that wasn't the case: *any* change to `Lib.csproj` would result rebuilding and redeploying the `.apk`, because `AndroidManifest.xml` was constantly being modified, which would cause the `_CompileToDalvikWithDx` target to be invoked, resulting in a `.apk` rebuild + redeploy. The item was constantly being duplicated in the manifest. As a result it was always newer and was triggering a change of build targets. So we need to double check we are NOT adding 100% duplicate values to the manifest. --- .../Tests/Xamarin.Android.Build.Tests/ManifestTest.cs | 4 ++++ .../Utilities/ManifestDocument.cs | 11 +++++++++++ .../Utilities/XDocumentExtensions.cs | 5 +++++ 3 files changed, 20 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs index 882b4d3f1c9..30fcc1ca399 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs @@ -486,6 +486,8 @@ public void MergeLibraryManifest () android:authorities='${applicationId}.FacebookInitProvider' android:name='.internal.FacebookInitProvider' android:exported='false' /> + + ", encoding: System.Text.Encoding.UTF8); @@ -522,6 +524,8 @@ public void MergeLibraryManifest () "${applicationId}.FacebookInitProvider was not replaced with com.xamarin.manifest.FacebookInitProvider"); Assert.IsTrue (manifest.Contains ("com.xamarin.test.internal.FacebookInitProvider"), ".internal.FacebookInitProvider was not replaced with com.xamarin.test.internal.FacebookInitProvider"); + Assert.AreEqual (manifest.IndexOf ("meta-data", StringComparison.OrdinalIgnoreCase), + manifest.LastIndexOf ("meta-data", StringComparison.OrdinalIgnoreCase), "There should be only one meta-data element"); } } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs index b009cb91338..c16b4ca4ffa 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs @@ -401,6 +401,16 @@ void MergeLibraryManifest (string mergedManifest) } } + void RemoveDuplicateElements () + { + var duplicates = doc.Descendants () + .GroupBy (x => x.ToFullString ()) + .SelectMany (x => x.Skip (1)); + foreach (var duplicate in duplicates) + duplicate.Remove (); + + } + IEnumerable FixupNameElements(string packageName, IEnumerable nodes) { foreach (var element in nodes.Select ( x => x as XElement).Where (x => x != null && ManifestAttributeFixups.ContainsKey (x.Name.LocalName))) { @@ -838,6 +848,7 @@ public void Save (string filename) public void Save (System.IO.TextWriter stream) { + RemoveDuplicateElements (); var ms = new MemoryStream (); doc.Save (ms); ms.Flush (); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/XDocumentExtensions.cs b/src/Xamarin.Android.Build.Tasks/Utilities/XDocumentExtensions.cs index d05efb5ab68..5bac4ba45a3 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/XDocumentExtensions.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/XDocumentExtensions.cs @@ -22,6 +22,11 @@ public static string[] GetPaths (this XDocument doc, params string[] paths) e = e.Elements (p); return e.Select (p => p.Value).ToArray (); } + + public static string ToFullString (this XElement element) + { + return element.ToString (SaveOptions.DisableFormatting); + } } }