Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] Don't deploy Facade assemblies (#337)
Browse files Browse the repository at this point in the history
A change "somewhere" has recently causes this issue. The problem is
in Release mode we now include the Facade assemblies in the package.
Which is something we definately should NOT be doing.

That said we do need the Facades in order for Linking and Aot to
work since Cecil needs to be able to load them.
So what this commit does is make sure the `ResolveAssemblies` task
adds metadata for the Facades. We can then use that in the `BuildApk`
Task to filter out the assemblies we do not want to ship.
  • Loading branch information
dellis1972 authored and jonpryor committed Jan 9, 2017
1 parent bf1bc93 commit a7beb70
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 15 deletions.
29 changes: 18 additions & 11 deletions src/Xamarin.Android.Build.Tasks/Tasks/ResolveAssemblies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public class ResolveAssemblies : Task
[Required]
public string ReferenceAssembliesDirectory { get; set; }

public ITaskItem[] DesignTimeFacadeDirectories { get; set; }

public string I18nAssemblies { get; set; }
public string LinkMode { get; set; }

Expand Down Expand Up @@ -56,11 +58,12 @@ bool Execute (DirectoryAssemblyResolver resolver)
Log.LogDebugMessage (" I18nAssemblies: {0}", I18nAssemblies);
Log.LogDebugMessage (" LinkMode: {0}", LinkMode);
Log.LogDebugTaskItems (" Assemblies:", Assemblies);
Log.LogDebugTaskItems (" DesignTimeFacadeDirectories:", DesignTimeFacadeDirectories);

foreach (var dir in ReferenceAssembliesDirectory.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
resolver.SearchDirectories.Add (dir);

var assemblies = new HashSet<string> ();
var assemblies = new HashSet<ITaskItem> (new ITaskItemEqualityComparer ());

var topAssemblyReferences = new List<AssemblyDefinition> ();

Expand All @@ -76,7 +79,7 @@ bool Execute (DirectoryAssemblyResolver resolver)
if (assemblyDef == null)
throw new InvalidOperationException ("Failed to load assembly " + assembly.ItemSpec);
topAssemblyReferences.Add (assemblyDef);
assemblies.Add (Path.GetFullPath (assemblyDef.MainModule.FullyQualifiedName));
assemblies.Add (new TaskItem (Path.GetFullPath (assemblyDef.MainModule.FullyQualifiedName)));
}
} catch (Exception ex) {
Log.LogError ("Exception while loading assemblies: {0}", ex);
Expand All @@ -93,8 +96,8 @@ bool Execute (DirectoryAssemblyResolver resolver)
// Add I18N assemblies if needed
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 ();
ResolvedAssemblies = assemblies.ToArray ();
ResolvedSymbols = assemblies.Select (a => new TaskItem (a + ".mdb")).Where (a => File.Exists (a.ItemSpec)).ToArray ();
ResolvedFrameworkAssemblies = ResolvedAssemblies.Where (p => MonoAndroidHelper.IsFrameworkAssembly (p.ItemSpec, true)).ToArray ();
ResolvedUserAssemblies = ResolvedAssemblies.Where (p => !MonoAndroidHelper.IsFrameworkAssembly (p.ItemSpec, true)).ToArray ();
ResolvedDoNotPackageAttributes = do_not_package_atts.ToArray ();
Expand All @@ -110,13 +113,14 @@ bool Execute (DirectoryAssemblyResolver resolver)
readonly List<string> do_not_package_atts = new List<string> ();
int indent = 2;

void AddAssemblyReferences (DirectoryAssemblyResolver resolver, ICollection<string> assemblies, AssemblyDefinition assembly, bool topLevel)
void AddAssemblyReferences (DirectoryAssemblyResolver resolver, ICollection<ITaskItem> assemblies, AssemblyDefinition assembly, bool topLevel)
{
var fqname = assembly.MainModule.FullyQualifiedName;
var fullPath = Path.GetFullPath (fqname);
var item = new TaskItem (fullPath);

// Don't repeat assemblies we've already done
if (!topLevel && assemblies.Contains (fullPath))
if (!topLevel && assemblies.Contains (item))
return;

foreach (var att in assembly.CustomAttributes.Where (a => a.AttributeType.FullName == "Java.Interop.DoNotPackageAttribute")) {
Expand All @@ -129,8 +133,11 @@ void AddAssemblyReferences (DirectoryAssemblyResolver resolver, ICollection<stri
Log.LogMessage (MessageImportance.Low, "{0}Adding assembly reference for {1}, recursively...", new string (' ', indent), assembly.Name);
indent += 2;
// Add this assembly
if (!topLevel && assemblies.All (a => new AssemblyNameDefinition (a, null).Name != assembly.Name.Name))
assemblies.Add (fullPath);
if (!topLevel && assemblies.All (a => new AssemblyNameDefinition (a.ItemSpec, null).Name != assembly.Name.Name)) {
var path = Path.GetDirectoryName (fullPath);
item.SetMetadata ("ResolvedFrom", DesignTimeFacadeDirectories.Any (x => Path.GetDirectoryName (x.ItemSpec).StartsWith (Path.GetDirectoryName (path))) ? "ImplicitlyExpandDesignTimeFacades" : "");
assemblies.Add (item);
}

// Recurse into each referenced assembly
foreach (AssemblyNameReference reference in assembly.MainModule.AssemblyReferences) {
Expand All @@ -152,7 +159,7 @@ static LinkModes ParseLinkMode (string linkmode)
return mode;
}

void AddI18nAssemblies (DirectoryAssemblyResolver resolver, ICollection<string> assemblies)
void AddI18nAssemblies (DirectoryAssemblyResolver resolver, ICollection<ITaskItem> assemblies)
{
var i18n = Linker.ParseI18nAssemblies (I18nAssemblies);
var link = ParseLinkMode (LinkMode);
Expand All @@ -179,10 +186,10 @@ void AddI18nAssemblies (DirectoryAssemblyResolver resolver, ICollection<string>
assemblies.Add (ResolveI18nAssembly (resolver, "I18N.West"));
}

string ResolveI18nAssembly (DirectoryAssemblyResolver resolver, string name)
ITaskItem ResolveI18nAssembly (DirectoryAssemblyResolver resolver, string name)
{
var assembly = resolver.Resolve (AssemblyNameReference.Parse (name));
return Path.GetFullPath (assembly.MainModule.FullyQualifiedName);
return new TaskItem (Path.GetFullPath (assembly.MainModule.FullyQualifiedName));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using Microsoft.Build.Framework;

namespace Xamarin.Android.Tasks
{
public class ITaskItemEqualityComparer : IEqualityComparer<ITaskItem>
{
public bool Equals (ITaskItem x, ITaskItem y)
{
if (x == null || y == null)
return false;
return x.ItemSpec == y.ItemSpec;
}

public int GetHashCode (ITaskItem obj)
{
if (obj == null)
return 0;
return obj.ItemSpec.GetHashCode ();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,9 @@
<Compile Include="Utilities\Files.cs">
<Link>Utilities\Files.cs</Link>
</Compile>
<Compile Include="Utilities\ITaskItemEqualityComparer.cs">
<Link>Utilities\ITaskItemEqualityComparer.cs</Link>
</Compile>
<Compile Include="$(LinkerSourceFullPath)\tuner\Mono.Tuner\ApplyPreserveAttributeBase.cs">
<Link>Linker\Mono.Tuner\ApplyPreserveAttributeBase.cs</Link>
</Compile>
Expand Down
25 changes: 21 additions & 4 deletions src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,7 @@ because xbuild doesn't support framework reference assemblies.
_GetAdditionalResourcesFromAssemblies;
_CreateAdditionalResourceCache;
_GenerateAndroidResourceDir;
_ValidateAndroidPackageProperties;
</_UpdateAndroidResgenDependsOnTargets>
</PropertyGroup>

Expand Down Expand Up @@ -1409,6 +1410,7 @@ because xbuild doesn't support framework reference assemblies.
Assemblies="$(OutDir)$(TargetFileName);@(FilteredAssemblies)"
I18nAssemblies="$(MandroidI18n)"
LinkMode="$(AndroidLinkMode)"
DesignTimeFacadeDirectories="@(DesignTimeFacadeDirectories)"
ReferenceAssembliesDirectory="$(TargetFrameworkDirectory)">
<Output TaskParameter="ResolvedAssemblies" ItemName="ResolvedAssemblies" />
<Output TaskParameter="ResolvedUserAssemblies" ItemName="ResolvedUserAssemblies" />
Expand Down Expand Up @@ -1614,6 +1616,7 @@ because xbuild doesn't support framework reference assemblies.
<Target Name="_PrepareAssemblies" DependsOnTargets="$(_PrepareAssembliesDependsOnTargets)">
<!-- Update our assembly lists to the copies for linking. We also need to verify
they still exist cause linking will delete them if they aren't used -->

<GetFilesThatExist
Condition="'$(AndroidLinkMode)' != 'None'"
Files="@(ResolvedAssemblies->'$(MonoAndroidIntermediateAssetsDir)%(Filename)%(Extension)')">
Expand All @@ -1640,36 +1643,42 @@ because xbuild doesn't support framework reference assemblies.

<CreateItem
Include="@(ResolvedAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(Filename)%(Extension)')"
PreserveExistingMetadata="True"
Condition="'$(AndroidLinkMode)' == 'None'">
<Output TaskParameter="Include" ItemName="_ResolvedAssemblies" />
</CreateItem>

<CreateItem
Include="@(ResolvedSymbols->'$(MonoAndroidIntermediateAssemblyDir)%(Filename)%(Extension)')"
PreserveExistingMetadata="True"
Condition="'$(AndroidLinkMode)' == 'None'">
<Output TaskParameter="Include" ItemName="_ResolvedSymbols" />
</CreateItem>

<CreateItem
Include="@(ResolvedUserAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(Filename)%(Extension)')"
PreserveExistingMetadata="True"
Condition="'$(AndroidLinkMode)' == 'None'">
<Output TaskParameter="Include" ItemName="_ResolvedUserAssemblies" />
</CreateItem>

<CreateItem
Include="@(ResolvedFrameworkAssemblies)"
PreserveExistingMetadata="True"
Condition="'$(AndroidLinkMode)' == 'None'">
<Output TaskParameter="Include" ItemName="_ResolvedFrameworkAssemblies" />
</CreateItem>

<CreateItem
Include="@(_ResolvedFrameworkAssemblies)"
PreserveExistingMetadata="True"
Condition="'$(AndroidLinkMode)' == 'None' OR '$(AndroidUseSharedRuntime)' == 'true'">
<Output TaskParameter="Include" ItemName="_ShrunkFrameworkAssemblies" />
</CreateItem>

<CreateItem
Include="@(_ResolvedFrameworkAssemblies->'$(MonoAndroidIntermediateAssetsDir)shrunk\%(Filename)%(Extension)')"
PreserveExistingMetadata="True"
Condition="'$(AndroidLinkMode)' != 'None' AND '$(AndroidUseSharedRuntime)' != 'true'">
<Output TaskParameter="Include" ItemName="_ShrunkFrameworkAssemblies" />
</CreateItem>
Expand Down Expand Up @@ -1735,6 +1744,7 @@ because xbuild doesn't support framework reference assemblies.
_CheckDuplicateJavaLibraries;
_GetAdditionalResourcesFromAssemblies;
_CreateAdditionalResourceCache;
_DefineBuildTargetAbis;
</_CreateBaseApkDependsOnTargets>
<_CreateBaseApkInputs>
$(MSBuildAllProjects)
Expand Down Expand Up @@ -2151,6 +2161,12 @@ because xbuild doesn't support framework reference assemblies.
<Touch Files="$(_AndroidApkPerAbiFlagFile)" Condition="'$(AndroidCreatePackagePerAbi)' == 'true'" AlwaysCreate="True" />
</Target>

<Target Name="FilterDesignTimeFacades">
<ItemGroup>
<_FilteredShrunkFrameworkAssemblies Include="@(_ShrunkFrameworkAssemblies)" Condition="'%(_ShrunkFrameworkAssemblies.ResolvedFrom)' != 'ImplicitlyExpandDesignTimeFacades'" />
</ItemGroup>
</Target>

<PropertyGroup>
<_PrepareBuildApkDependsOnTargets>
_SetLatestTargetFrameworkVersion;
Expand All @@ -2167,6 +2183,7 @@ because xbuild doesn't support framework reference assemblies.
_ResolveSatellitePaths;
_CheckApkPerAbiFlag
;_LintChecks
;FilterDesignTimeFacades
</_PrepareBuildApkDependsOnTargets>
</PropertyGroup>

Expand Down Expand Up @@ -2202,7 +2219,7 @@ because xbuild doesn't support framework reference assemblies.
SupportedAbis="$(_BuildTargetAbis)"
AndroidSequencePointsMode="$(_SequencePointsMode)"
AotAdditionalArguments="$(AndroidAotAdditionalArguments)"
ResolvedAssemblies="@(_ResolvedUserAssemblies);@(_ShrunkFrameworkAssemblies)"
ResolvedAssemblies="@(_ResolvedUserAssemblies);@(_FilteredShrunkFrameworkAssemblies)"
AotOutputDirectory="$(_AndroidAotBinDirectory)"
IntermediateAssemblyDir="$(MonoAndroidIntermediateAssemblyDir)"
LinkMode="$(AndroidLinkMode)"
Expand All @@ -2216,14 +2233,14 @@ because xbuild doesn't support framework reference assemblies.
Condition=" '$(AndroidAotMode)' == 'Hybrid' And '$(AotAssemblies)' == 'True' "
AndroidAotMode="$(AndroidAotMode)"
ToolPath="$(_MonoAndroidToolsDirectory)"
ResolvedAssemblies="@(_ResolvedAssemblies)">
ResolvedAssemblies="@(_FilteredShrunkFrameworkAssemblies)">
</CilStrip>

<!-- Bundle the assemblies into native libraries in the apk -->
<MakeBundleNativeCodeExternal
Condition="'$(BundleAssemblies)' == 'True'"
AndroidNdkDirectory="$(_AndroidNdkDirectory)"
Assemblies="@(_ResolvedUserAssemblies);@(_AndroidResolvedSatellitePaths);@(_ShrunkFrameworkAssemblies)"
Assemblies="@(_ResolvedUserAssemblies);@(_AndroidResolvedSatellitePaths);@(_FilteredShrunkFrameworkAssemblies)"
IncludePath="$(MonoAndroidIncludeDirectory)"
SupportedAbis="$(_BuildTargetAbis)"
TempOutputPath="$(IntermediateOutputPath)"
Expand All @@ -2241,7 +2258,7 @@ because xbuild doesn't support framework reference assemblies.
EmbedAssemblies="$(EmbedAssembliesIntoApk)"
Environments="@(AndroidEnvironment);@(LibraryEnvironments)"
ResolvedUserAssemblies="@(_ResolvedUserAssemblies);@(_AndroidResolvedSatellitePaths)"
ResolvedFrameworkAssemblies="@(_ShrunkFrameworkAssemblies)"
ResolvedFrameworkAssemblies="@(_FilteredShrunkFrameworkAssemblies)"
NativeLibraries="@(AndroidNativeLibrary)"
AdditionalNativeLibraryReferences="@(_AdditionalNativeLibraryReferences)"
EmbeddedNativeLibraryAssemblies="$(OutDir)$(TargetFileName);@(ReferencePath);@(ReferenceDependencyPaths)"
Expand Down

0 comments on commit a7beb70

Please sign in to comment.