Skip to content

[Xamarin.Android.Build.Tasks] Dispose DirectoryAssemblyResolver instances #233

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

Merged
merged 1 commit into from
Sep 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion external/Java.Interop
45 changes: 23 additions & 22 deletions src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}
Expand Down
18 changes: 9 additions & 9 deletions src/Xamarin.Android.Build.Tasks/Tasks/CheckTargetFrameworks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ public class CheckTargetFrameworks : Task
public string ProjectFile { get; set; }

Dictionary<ITaskItem, int> apiLevels = new Dictionary<ITaskItem, int> ();
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) {
Expand All @@ -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);
}
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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<string> ();

// Put every assembly we'll need in the resolver
Expand Down
33 changes: 17 additions & 16 deletions src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesigner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,23 +106,24 @@ public override bool Execute ()
var assemblyNames = new List<string> ();
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
}
Expand Down
12 changes: 10 additions & 2 deletions src/Xamarin.Android.Build.Tasks/Tasks/LinkAssemblies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
36 changes: 20 additions & 16 deletions src/Xamarin.Android.Build.Tasks/Tasks/ResolveAssemblies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,21 @@ 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);
Log.LogDebugMessage (" I18nAssemblies: {0}", I18nAssemblies);
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);

Expand Down Expand Up @@ -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 ();
Expand All @@ -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<string> do_not_package_atts = new List<string> ();
int indent = 2;

private void AddAssemblyReferences (ICollection<string> assemblies, AssemblyDefinition assembly, bool topLevel)
void AddAssemblyReferences (DirectoryAssemblyResolver resolver, ICollection<string> assemblies, AssemblyDefinition assembly, bool topLevel)
{
var fqname = assembly.MainModule.FullyQualifiedName;

Expand All @@ -130,7 +134,7 @@ private void AddAssemblyReferences (ICollection<string> 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;
}
Expand All @@ -147,7 +151,7 @@ static LinkModes ParseLinkMode (string linkmode)
return mode;
}

private void AddI18nAssemblies (ICollection<string> assemblies)
void AddI18nAssemblies (DirectoryAssemblyResolver resolver, ICollection<string> assemblies)
{
var i18n = Linker.ParseI18nAssemblies (I18nAssemblies);
var link = ParseLinkMode (LinkMode);
Expand All @@ -156,25 +160,25 @@ private void AddI18nAssemblies (ICollection<string> 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ public override bool Execute ()
var resolvedResourceDirectories = new List<string> ();
var resolvedAssetDirectories = new List<string> ();
var resolvedEnvironmentFiles = new List<string> ();
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
Expand Down Expand Up @@ -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<string> jars,
ICollection<string> resolvedResourceDirectories,
ICollection<string> resolvedAssetDirectories,
Expand All @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down