From 5544f92b182363f3a2378da985dd76f98dc854a2 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Sat, 24 Sep 2016 17:48:33 -0400 Subject: [PATCH] [Xamarin.Android.Build.Tasks] Dispose DirectoryAssemblyResolver instances Context: https://bugzilla.xamarin.com/show_bug.cgi?id=44529 Commit 1d658252 bumped to Cecil 0.10.0-beta1-v2 and Java.Interop/a1d3ecc8, which likewise uses Cecil 0.10.0-beta1-v2. Among the various API changes in Cecil 0.10.x vs. Cecil 0.9.x is a change to `Mono.Cecil.IAssemblyResolver`, implemented by `Java.Interop.Tools.Cecil.DirectoryAssemblyResolver`, to implement the `IDisposable` interface. Java.Interop/a1d3ecc8 added a `DirectoryAssemblyResolver.Dispose()` method, but this method didn't *do* anything. Cecil 0.10.0-beta1-v2 also has a *semantic* change vs. Cecil 0.9.x: `AssemblyDefinition` is no longer a "purely in-memory" construct. Instead, it holds a `System.IO.Stream` to the assembly it's reading (unless `Mono.Cecil.ReaderParameters.InMemory` is `true`). This semantic change means that an assembly can't be read from and written to at the same time via different mechanisms, so long as there is an `AssemblyDefinition` instance to that file. Which brings us to (private) Bug #44529, in which an `IOException` is thrown from the `` task: Error executing task StripEmbeddedLibraries: System.IO.IOException: Sharing violation on path .../obj/Release/linksrc/Xamarin.Android.NUnitLite.dll at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) [0x0025f] in <253a3790b2c44512bbca8669ecfc1822>:0 at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share) [0x00000] in <253a3790b2c44512bbca8669ecfc1822>:0 at (wrapper remoting-invoke-with-check) System.IO.FileStream:.ctor (string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare) at Mono.Cecil.ModuleDefinition.GetFileStream (System.String fileName, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share) [0x00007] in :0 at Mono.Cecil.ModuleDefinition.Write (System.String fileName, Mono.Cecil.WriterParameters parameters) [0x00007] in :0 at Mono.Cecil.AssemblyDefinition.Write (System.String fileName, Mono.Cecil.WriterParameters parameters) [0x00001] in :0 at Xamarin.Android.Tasks.StripEmbeddedLibraries.Execute () [0x0034a] in <3d5202a5d4874a76a99388021bf1ab1a>:0 The underlying cause of the `IOException` is twofold: 1. `AssemblyDefinition` instances now hold a `FileStream` to the file they're reading from (and optionally writing to), and this `FileStream` will be kept open until `AssemblyDefinition.Dispose()` is called. 2. Nothing in `Xamarin.Android.Build.Tasks` calls `AssemblyDefinition.Dispose()`. Nor should anything in `Xamarin.Android.Build.Tasks` call `AssemblyDefinition.Dispose()`! (Almost) All `AssemblyDefinition` instances are *cached* within `DirectoryAssemblyResolver` instances, and nothing calls `DirectoryAssemblyResolver.Dispose()` either! (Not that this matters *too* much, becuase `DirectoryAssemblyResolver.Dispose()` is currently a no-op.) There is no sane reasoning here: so long as we're using `DirectoryAssemblyResolver`, we're going to have more files open (compared to when Cecil 0.9.x was used), which can result in file sharing problems and the above `IOException`. The way foward is: 1. `Java.Interop.Tools.Cecil.DirectoryAssemblyResolver` needs to be updated so that [`DirectoryAssemblyResolver.Dispose()` is useful][0], i.e. that it will `Dispose()` of all held `AssemblyDefinition` instances. 2. Bump to Java.Interop/084e9f7f to pick up (1). 3. `Xamarin.Android.Build.Tasks.dll` needs to be updated so that `DirectoryAssemblyResolver.Dispose()` is used. 4. All code, in particular `Xamarin.Andorid.Build.Tasks.dll`, needs to be reviewed to ensure it doesn't do anything "stupid" with `AssemblyDefinition` instances and/or `DirectoryAssemblyResolver.` Examples of "stupid" things include: * `Dispose()`ing of the return value from `DirectoryAssemblyResolver.Load()`: resolver.Load (assemblyName).Dispose(); * Treating `AssemblyDefinition` instances in a manner inconsistent with how `DirectoryAssemblyResolver` loads them. `DirectoryAssemblyResolver` will be getting a new constructor overload which takes an `Mono.Cecil.ReaderParameters` parameter; the default will be the default Cecil behavior, which is for read-only behavior. Thus, trying to use the `AssemblyDefinition` in a "write" context will fail: var r = new DirectoryAssemblyResolver (...); var a = r.Load (assemblyName); a.Write (); // BOOM [0]: https://github.com/xamarin/java.interop/pull/88 --- external/Java.Interop | 2 +- .../Tasks/BuildApk.cs | 45 ++++++++++--------- .../Tasks/CheckTargetFrameworks.cs | 18 ++++---- .../Tasks/GenerateJavaStubs.cs | 12 ++--- .../Tasks/GenerateResourceDesigner.cs | 33 +++++++------- .../GetAdditionalResourcesFromAssemblies.cs | 45 ++++++++++--------- .../Tasks/LinkAssemblies.cs | 12 ++++- .../Tasks/ResolveAssemblies.cs | 36 ++++++++------- .../Tasks/ResolveLibraryProjectImports.cs | 7 ++- .../Tasks/StripEmbeddedLibraries.cs | 8 +++- 10 files changed, 121 insertions(+), 97 deletions(-) diff --git a/external/Java.Interop b/external/Java.Interop index a1d3ecc8ba6..084e9f7f5c7 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit a1d3ecc8ba6e67b96ae1c633194b0e78c2ac5c23 +Subproject commit 084e9f7f5c7de86a75a372dbff58f72042df2477 diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs b/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs index 653e519819a..1e1fd67e3ae 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs @@ -444,30 +444,31 @@ void AddRuntimeLibraries (ZipArchive apk, string supportedAbis) void AddNativeLibrariesFromAssemblies (ZipArchive apk, string supportedAbis) { var abis = supportedAbis.Split (new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); - var res = new DirectoryAssemblyResolver (Console.WriteLine, loadDebugSymbols: false); + using (var res = new DirectoryAssemblyResolver (Console.WriteLine, loadDebugSymbols: false)) { foreach (var assembly in EmbeddedNativeLibraryAssemblies) res.Load (assembly.ItemSpec); - foreach (var assemblyPath in EmbeddedNativeLibraryAssemblies) { - var assembly = res.GetAssembly (assemblyPath.ItemSpec); - foreach (var mod in assembly.Modules) { - var ressozip = mod.Resources.FirstOrDefault (r => r.Name == "__AndroidNativeLibraries__.zip") as EmbeddedResource; - if (ressozip == null) - continue; - var data = ressozip.GetResourceData (); - using (var ms = new MemoryStream (data)) { - using (var zip = ZipArchive.Open (ms)) { - foreach (var e in zip.Where (x => abis.Any (a => x.FullName.Contains (a)))) { - if (e.IsDirectory) - continue; - var key = e.FullName.Replace ("native_library_imports", "lib"); - if (apk.Any(k => k.FullName == key)) { - Log.LogCodedWarning ("4301", "Apk already contains the item {0}; ignoring.", key); - continue; - } - using (var s = new MemoryStream ()) { - e.Extract (s); - s.Position = 0; - apk.AddEntry (s.ToArray (),key); + foreach (var assemblyPath in EmbeddedNativeLibraryAssemblies) { + var assembly = res.GetAssembly (assemblyPath.ItemSpec); + foreach (var mod in assembly.Modules) { + var ressozip = mod.Resources.FirstOrDefault (r => r.Name == "__AndroidNativeLibraries__.zip") as EmbeddedResource; + if (ressozip == null) + continue; + var data = ressozip.GetResourceData (); + using (var ms = new MemoryStream (data)) { + using (var zip = ZipArchive.Open (ms)) { + foreach (var e in zip.Where (x => abis.Any (a => x.FullName.Contains (a)))) { + if (e.IsDirectory) + continue; + var key = e.FullName.Replace ("native_library_imports", "lib"); + if (apk.Any (k => k.FullName == key)) { + Log.LogCodedWarning ("4301", "Apk already contains the item {0}; ignoring.", key); + continue; + } + using (var s = new MemoryStream ()) { + e.Extract (s); + s.Position = 0; + apk.AddEntry (s.ToArray (), key); + } } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CheckTargetFrameworks.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CheckTargetFrameworks.cs index cddc6ff69b1..974c4f22c7f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CheckTargetFrameworks.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CheckTargetFrameworks.cs @@ -23,9 +23,8 @@ public class CheckTargetFrameworks : Task public string ProjectFile { get; set; } Dictionary apiLevels = new Dictionary (); - DirectoryAssemblyResolver res; - int ExtractApiLevel(ITaskItem ass) + int ExtractApiLevel(DirectoryAssemblyResolver res, ITaskItem ass) { Log.LogDebugMessage (ass.ItemSpec); foreach (var ca in res.GetAssembly (ass.ItemSpec).CustomAttributes) { @@ -51,13 +50,14 @@ public override bool Execute () Log.LogDebugMessage (" ProjectFile: {0}", ProjectFile); Log.LogDebugTaskItems (" ResolvedUserAssemblies: {0}", ResolvedAssemblies); - res = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false); - foreach (var assembly in ResolvedAssemblies) { - res.Load (Path.GetFullPath (assembly.ItemSpec)); - var apiLevel = ExtractApiLevel (assembly); - if (apiLevel > 0) { - Log.LogDebugMessage ("{0}={1}", Path.GetFileNameWithoutExtension (assembly.ItemSpec), apiLevel); - apiLevels.Add (assembly, apiLevel); + using (var res = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false)) { + foreach (var assembly in ResolvedAssemblies) { + res.Load (Path.GetFullPath (assembly.ItemSpec)); + var apiLevel = ExtractApiLevel (res, assembly); + if (apiLevel > 0) { + Log.LogDebugMessage ("{0}={1}", Path.GetFileNameWithoutExtension (assembly.ItemSpec), apiLevel); + apiLevels.Add (assembly, apiLevel); + } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs index 4302432f731..8d99775bf99 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs @@ -79,7 +79,11 @@ public override bool Execute () Log.LogDebugMessage (" ApplicationJavaClass: {0}", ApplicationJavaClass); try { - Run (); + // We're going to do 3 steps here instead of separate tasks so + // we can share the list of JLO TypeDefinitions between them + using (var res = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: true)) { + Run (res); + } } catch (XamarinAndroidException e) { Log.LogCodedError (string.Format ("XA{0:0000}", e.Code), e.MessageWithoutCode); @@ -90,17 +94,13 @@ public override bool Execute () return !Log.HasLoggedErrors; } - void Run () + void Run (DirectoryAssemblyResolver res) { PackageNamingPolicy pnp; JniType.PackageNamingPolicy = Enum.TryParse (PackageNamingPolicy, out pnp) ? pnp : PackageNamingPolicyEnum.LowercaseHash; var temp = Path.Combine (Path.GetTempPath (), Path.GetRandomFileName ()); Directory.CreateDirectory (temp); - // We're going to do 3 steps here instead of separate tasks so - // we can share the list of JLO TypeDefinitions between them - var res = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols:true); - var selectedWhitelistAssemblies = new List (); // Put every assembly we'll need in the resolver diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesigner.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesigner.cs index ec1c1640e75..e1c8956b25f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesigner.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesigner.cs @@ -106,23 +106,24 @@ public override bool Execute () var assemblyNames = new List (); if (IsApplication && References != null && References.Any ()) { // FIXME: should this be unified to some better code with ResolveLibraryProjectImports? - var resolver = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false); - foreach (var assemblyName in References) { - var suffix = assemblyName.ItemSpec.EndsWith (".dll") ? String.Empty : ".dll"; - string hintPath = assemblyName.GetMetadata ("HintPath").Replace (Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); - string fileName = assemblyName.ItemSpec + suffix; - resolver.Load (Path.GetFullPath (assemblyName.ItemSpec)); - if (!String.IsNullOrEmpty (hintPath) && !File.Exists (hintPath)) // ignore invalid HintPath - hintPath = null; - string assemblyPath = String.IsNullOrEmpty (hintPath) ? fileName : hintPath; - if (MonoAndroidHelper.IsFrameworkAssembly (fileName) && !MonoAndroidHelper.FrameworkEmbeddedJarLookupTargets.Contains (Path.GetFileName (fileName))) - continue; - Log.LogDebugMessage ("Scan assembly {0} for resource generator", fileName); - assemblyNames.Add (assemblyPath); + using (var resolver = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false)) { + foreach (var assemblyName in References) { + var suffix = assemblyName.ItemSpec.EndsWith (".dll") ? String.Empty : ".dll"; + string hintPath = assemblyName.GetMetadata ("HintPath").Replace (Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + string fileName = assemblyName.ItemSpec + suffix; + resolver.Load (Path.GetFullPath (assemblyName.ItemSpec)); + if (!String.IsNullOrEmpty (hintPath) && !File.Exists (hintPath)) // ignore invalid HintPath + hintPath = null; + string assemblyPath = String.IsNullOrEmpty (hintPath) ? fileName : hintPath; + if (MonoAndroidHelper.IsFrameworkAssembly (fileName) && !MonoAndroidHelper.FrameworkEmbeddedJarLookupTargets.Contains (Path.GetFileName (fileName))) + continue; + Log.LogDebugMessage ("Scan assembly {0} for resource generator", fileName); + assemblyNames.Add (assemblyPath); + } + var assemblies = assemblyNames.Select (assembly => resolver.GetAssembly (assembly)); + new ResourceDesignerImportGenerator (Namespace, resources) + .CreateImportMethods (assemblies); } - var assemblies = assemblyNames.Select (assembly => resolver.GetAssembly (assembly)); - new ResourceDesignerImportGenerator (Namespace, resources) - .CreateImportMethods (assemblies); } AdjustConstructor (isFSharp, resources); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GetAdditionalResourcesFromAssemblies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GetAdditionalResourcesFromAssemblies.cs index acb68e5f400..656beb25c14 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GetAdditionalResourcesFromAssemblies.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GetAdditionalResourcesFromAssemblies.cs @@ -363,28 +363,29 @@ public override bool Execute () ? CachePath : Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData), CacheBaseDir); - var resolver = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false); - foreach (var assemblyItem in Assemblies) { - string fullPath = Path.GetFullPath (assemblyItem.ItemSpec); - if (assemblies.Contains (fullPath)) { - LogDebugMessage (" Skip assembly: {0}, it was already processed", fullPath); - continue; - } - assemblies.Add (fullPath); - resolver.Load (fullPath); - // Append source file name (without the Xamarin. prefix or extension) to the base folder - // This would help avoid potential collisions. - foreach (var ca in resolver.GetAssembly (assemblyItem.ItemSpec).CustomAttributes) { - switch (ca.AttributeType.FullName) { - case "Android.IncludeAndroidResourcesFromAttribute": - AddAttributeValue (androidResources, ca, "XA5206", "{0}. Android resource directory {1} doesn't exist.", true, fullPath); - break; - case "Java.Interop.JavaLibraryReferenceAttribute": - AddAttributeValue (javaLibraries, ca, "XA5207", "{0}. Java library file {1} doesn't exist.", false, fullPath); - break; - case "Android.NativeLibraryReferenceAttribute": - AddAttributeValue (nativeLibraries, ca, "XA5210", "{0}. Native library file {1} doesn't exist.", false, fullPath); - break; + using (var resolver = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false)) { + foreach (var assemblyItem in Assemblies) { + string fullPath = Path.GetFullPath (assemblyItem.ItemSpec); + if (assemblies.Contains (fullPath)) { + LogDebugMessage (" Skip assembly: {0}, it was already processed", fullPath); + continue; + } + assemblies.Add (fullPath); + resolver.Load (fullPath); + // Append source file name (without the Xamarin. prefix or extension) to the base folder + // This would help avoid potential collisions. + foreach (var ca in resolver.GetAssembly (assemblyItem.ItemSpec).CustomAttributes) { + switch (ca.AttributeType.FullName) { + case "Android.IncludeAndroidResourcesFromAttribute": + AddAttributeValue (androidResources, ca, "XA5206", "{0}. Android resource directory {1} doesn't exist.", true, fullPath); + break; + case "Java.Interop.JavaLibraryReferenceAttribute": + AddAttributeValue (javaLibraries, ca, "XA5207", "{0}. Java library file {1} doesn't exist.", false, fullPath); + break; + case "Android.NativeLibraryReferenceAttribute": + AddAttributeValue (nativeLibraries, ca, "XA5210", "{0}. Native library file {1} doesn't exist.", false, fullPath); + break; + } } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssemblies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssemblies.cs index 12723dc3764..73b8e614fe9 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssemblies.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssemblies.cs @@ -75,8 +75,16 @@ public override bool Execute () Log.LogDebugMessage (" DumpDependencies: {0}", DumpDependencies); Log.LogDebugMessage (" LinkOnlyNewerThan: {0}", LinkOnlyNewerThan); - var res = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false); - + var rp = new ReaderParameters { + InMemory = true, + }; + using (var res = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false, loadReaderParameters: rp)) { + return Execute (res); + } + } + + bool Execute (DirectoryAssemblyResolver res) + { // Put every assembly we'll need in the resolver foreach (var assembly in ResolvedAssemblies) { res.Load (Path.GetFullPath (assembly.ItemSpec)); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAssemblies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAssemblies.cs index 090e409f83e..85bc81ce91e 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAssemblies.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAssemblies.cs @@ -42,9 +42,14 @@ public class ResolveAssemblies : Task [Output] public string[] ResolvedDoNotPackageAttributes { get; set; } - DirectoryAssemblyResolver resolver; - public override bool Execute () + { + using (var resolver = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false)) { + return Execute (resolver); + } + } + + bool Execute (DirectoryAssemblyResolver resolver) { Log.LogDebugMessage ("ResolveAssemblies Task"); Log.LogDebugMessage (" ReferenceAssembliesDirectory: {0}", ReferenceAssembliesDirectory); @@ -52,7 +57,6 @@ public override bool Execute () Log.LogDebugMessage (" LinkMode: {0}", LinkMode); Log.LogDebugTaskItems (" Assemblies:", Assemblies); - resolver = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false); foreach (var dir in ReferenceAssembliesDirectory.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) resolver.SearchDirectories.Add (dir); @@ -80,14 +84,14 @@ public override bool Execute () } try { foreach (var assembly in topAssemblyReferences) - AddAssemblyReferences (assemblies, assembly, true); + AddAssemblyReferences (resolver, assemblies, assembly, true); } catch (Exception ex) { Log.LogError ("Exception while loading assemblies: {0}", ex); return false; } // Add I18N assemblies if needed - AddI18nAssemblies (assemblies); + AddI18nAssemblies (resolver, assemblies); ResolvedAssemblies = assemblies.Select (a => new TaskItem (a)).ToArray (); ResolvedSymbols = assemblies.Select (a => a + ".mdb").Where (a => File.Exists (a)).Select (a => new TaskItem (a)).ToArray (); @@ -100,13 +104,13 @@ public override bool Execute () Log.LogDebugTaskItems (" [Output] ResolvedFrameworkAssemblies:", ResolvedFrameworkAssemblies); Log.LogDebugTaskItems (" [Output] ResolvedDoNotPackageAttributes:", ResolvedDoNotPackageAttributes); - return true; + return !Log.HasLoggedErrors; } readonly List do_not_package_atts = new List (); int indent = 2; - private void AddAssemblyReferences (ICollection assemblies, AssemblyDefinition assembly, bool topLevel) + void AddAssemblyReferences (DirectoryAssemblyResolver resolver, ICollection assemblies, AssemblyDefinition assembly, bool topLevel) { var fqname = assembly.MainModule.FullyQualifiedName; @@ -130,7 +134,7 @@ private void AddAssemblyReferences (ICollection assemblies, AssemblyDefi // Recurse into each referenced assembly foreach (AssemblyNameReference reference in assembly.MainModule.AssemblyReferences) { var reference_assembly = resolver.Resolve (reference); - AddAssemblyReferences (assemblies, reference_assembly, false); + AddAssemblyReferences (resolver, assemblies, reference_assembly, false); } indent -= 2; } @@ -147,7 +151,7 @@ static LinkModes ParseLinkMode (string linkmode) return mode; } - private void AddI18nAssemblies (ICollection assemblies) + void AddI18nAssemblies (DirectoryAssemblyResolver resolver, ICollection assemblies) { var i18n = Linker.ParseI18nAssemblies (I18nAssemblies); var link = ParseLinkMode (LinkMode); @@ -156,25 +160,25 @@ private void AddI18nAssemblies (ICollection assemblies) if (i18n == Mono.Linker.I18nAssemblies.None) return; - assemblies.Add (ResolveI18nAssembly ("I18N")); + assemblies.Add (ResolveI18nAssembly (resolver, "I18N")); if (i18n.HasFlag (Mono.Linker.I18nAssemblies.CJK)) - assemblies.Add (ResolveI18nAssembly ("I18N.CJK")); + assemblies.Add (ResolveI18nAssembly (resolver, "I18N.CJK")); if (i18n.HasFlag (Mono.Linker.I18nAssemblies.MidEast)) - assemblies.Add (ResolveI18nAssembly ("I18N.MidEast")); + assemblies.Add (ResolveI18nAssembly (resolver, "I18N.MidEast")); if (i18n.HasFlag (Mono.Linker.I18nAssemblies.Other)) - assemblies.Add (ResolveI18nAssembly ("I18N.Other")); + assemblies.Add (ResolveI18nAssembly (resolver, "I18N.Other")); if (i18n.HasFlag (Mono.Linker.I18nAssemblies.Rare)) - assemblies.Add (ResolveI18nAssembly ("I18N.Rare")); + assemblies.Add (ResolveI18nAssembly (resolver, "I18N.Rare")); if (i18n.HasFlag (Mono.Linker.I18nAssemblies.West)) - assemblies.Add (ResolveI18nAssembly ("I18N.West")); + assemblies.Add (ResolveI18nAssembly (resolver, "I18N.West")); } - private string ResolveI18nAssembly (string name) + string ResolveI18nAssembly (DirectoryAssemblyResolver resolver, string name) { var assembly = resolver.Resolve (AssemblyNameReference.Parse (name)); return assembly.MainModule.FullyQualifiedName; diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs index cb30333484f..eb542d9ea2c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs @@ -71,7 +71,10 @@ public override bool Execute () var resolvedResourceDirectories = new List (); var resolvedAssetDirectories = new List (); var resolvedEnvironmentFiles = new List (); - Extract (jars, resolvedResourceDirectories, resolvedAssetDirectories, resolvedEnvironmentFiles); + + using (var resolver = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false)) { + Extract (resolver, jars, resolvedResourceDirectories, resolvedAssetDirectories, resolvedEnvironmentFiles); + } Jars = jars.ToArray (); ResolvedResourceDirectories = resolvedResourceDirectories @@ -133,6 +136,7 @@ static string GetTargetAssembly (ITaskItem assemblyName) // Extracts library project contents under e.g. obj/Debug/[__library_projects__/*.jar | res/*/*] void Extract ( + DirectoryAssemblyResolver res, ICollection jars, ICollection resolvedResourceDirectories, ICollection resolvedAssetDirectories, @@ -142,7 +146,6 @@ void Extract ( if (!outdir.Exists) outdir.Create (); - var res = new DirectoryAssemblyResolver (Log.LogWarning, loadDebugSymbols: false); foreach (var assembly in Assemblies) res.Load (assembly.ItemSpec); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/StripEmbeddedLibraries.cs b/src/Xamarin.Android.Build.Tasks/Tasks/StripEmbeddedLibraries.cs index a79f8328af7..85f29b807ca 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/StripEmbeddedLibraries.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/StripEmbeddedLibraries.cs @@ -28,7 +28,13 @@ public override bool Execute () Log.LogDebugMessage ("StripEmbeddedLibraries Task"); Log.LogDebugTaskItems (" Assemblies: ", Assemblies); - var res = new DirectoryAssemblyResolver (Log.LogWarning, true); + using (var res = new DirectoryAssemblyResolver (Log.LogWarning, true)) { + return Execute (res); + } + } + + bool Execute (DirectoryAssemblyResolver res) + { foreach (var assembly in Assemblies) res.Load (Path.GetFullPath (assembly.ItemSpec));