Skip to content

Commit cc74519

Browse files
committed
First Pass at using Resource Designer assembly [WIP]
Context dotnet#6310
1 parent 93306b8 commit cc74519

File tree

55 files changed

+2108
-320
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2108
-320
lines changed

build-tools/installers/create-installers.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@
303303
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.CSharp.targets" ExcludeFromAndroidNETSdk="true" />
304304
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.D8.targets" />
305305
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Designer.targets" />
306+
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Resource.Designer.targets" />
306307
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.DesignTime.targets" />
307308
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.EmbeddedResource.targets" />
308309
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.FSharp.targets" ExcludeFromAndroidNETSdk="true" />
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
using Mono.Cecil;
6+
using Mono.Cecil.Cil;
7+
8+
using Java.Interop.Tools.Cecil;
9+
10+
using Mono.Linker;
11+
using Mono.Linker.Steps;
12+
13+
using Mono.Tuner;
14+
#if ILLINK
15+
using Microsoft.Android.Sdk.ILLink;
16+
#endif // ILLINK
17+
18+
namespace MonoDroid.Tuner
19+
{
20+
public class FixLegacyResourceDesignerStep : LinkDesignerBase
21+
{
22+
#if ILLINK
23+
protected override void Process ()
24+
{
25+
cache = Context;
26+
}
27+
#else
28+
public FixLegacyResourceDesignerStep (IMetadataResolver cache)
29+
{
30+
this.cache = cache;
31+
}
32+
33+
readonly
34+
#endif
35+
IMetadataResolver cache;
36+
AssemblyDefinition designerAssembly = null;
37+
TypeDefinition designerType = null;
38+
Dictionary<string, MethodDefinition> lookup;
39+
40+
protected override void EndProcess ()
41+
{
42+
if (designerAssembly != null) {
43+
LogMessage ($" Setting Action on {designerAssembly.Name} to Link.");
44+
Annotations.SetAction (designerAssembly, AssemblyAction.Link);
45+
}
46+
}
47+
48+
protected override void LoadDesigner ()
49+
{
50+
if (designerAssembly != null)
51+
return;
52+
var designerNameAssembly = AssemblyNameReference.Parse ("Xamarin.Android.Resource.Designer, Version=1.0.0.0");
53+
try {
54+
designerAssembly = Resolve (designerNameAssembly);
55+
} catch (Mono.Cecil.AssemblyResolutionException) {
56+
} catch (System.IO.FileNotFoundException) {
57+
}
58+
if (designerAssembly == null) {
59+
LogMessage ($" Did not find Xamarin.Android.Resource.Designer");
60+
return;
61+
}
62+
designerType = designerAssembly.MainModule.GetTypes ().First (x => x.FullName == "Xamarin.Android.Resource.Designer.Resource");
63+
lookup = BuildResourceDesignerPropertyLookup (designerType);
64+
return;
65+
}
66+
internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly)
67+
{
68+
if (designerAssembly == null) {
69+
LogMessage ($" Not using Xamarin.Android.Resource.Designer");
70+
return false;
71+
}
72+
73+
if (!FindResourceDesigner (assembly, mainApplication: false, out TypeDefinition designer, out CustomAttribute designerAttribute)) {
74+
LogMessage ($" {assembly.Name.Name} has no designer. ");
75+
return false;
76+
}
77+
78+
LogMessage ($" {assembly.Name.Name} has a designer. ");
79+
LogMessage ($" BaseType: {designer.BaseType.FullName}. ");
80+
if (designer.BaseType.FullName == "Xamarin.Android.Resource.Designer.Resource") {
81+
LogMessage ($" {assembly.Name.Name} has already been processed. ");
82+
return false;
83+
}
84+
85+
LogMessage ($" Adding reference {designerAssembly.Name.Name}.");
86+
assembly.MainModule.AssemblyReferences.Add (designerAssembly.Name);
87+
var importedDesignerType = assembly.MainModule.ImportReference (designerType.Resolve ());
88+
89+
LogMessage ($" FixupAssemblyTypes {assembly.Name.Name}.");
90+
// now replace all ldsfld with a call to the property get_ method.
91+
FixupAssemblyTypes (assembly, designer);
92+
93+
LogMessage ($" ClearDesignerClass {assembly.Name.Name}.");
94+
// then clean out the designer.
95+
ClearDesignerClass (designer, completely: true);
96+
designer.BaseType = importedDesignerType;
97+
return true;
98+
}
99+
100+
Dictionary<string, MethodDefinition> BuildResourceDesignerPropertyLookup (TypeDefinition type)
101+
{
102+
LogMessage ($" Building Designer Lookups for {type.FullName}");
103+
var output = new Dictionary<string, MethodDefinition> (StringComparer.OrdinalIgnoreCase);
104+
foreach (TypeDefinition definition in type.NestedTypes)
105+
{
106+
foreach (PropertyDefinition property in definition.Properties)
107+
{
108+
string key = $"{definition.Name}::{property.Name}";
109+
if (!output.ContainsKey (key)) {
110+
LogMessage ($" Adding {key}");
111+
output.Add(key, property.GetMethod);
112+
}
113+
}
114+
}
115+
return output;
116+
}
117+
118+
protected override void FixBody (MethodBody body, TypeDefinition designer)
119+
{
120+
// replace
121+
// IL_0068: ldsfld int32 Xamarin.Forms.Platform.Android.Resource/Layout::Toolbar
122+
// with
123+
// call int32 Xamarin.Forms.Platform.Android.Resource/Layout::get_Toolbar()
124+
string designerFullName = $"{designer.FullName}/";
125+
var processor = body.GetILProcessor ();
126+
Dictionary<Instruction, Instruction> instructions = new Dictionary<Instruction, Instruction>();
127+
foreach (var i in body.Instructions)
128+
{
129+
string line = i.ToString ();
130+
int idx = line.IndexOf (designerFullName, StringComparison.OrdinalIgnoreCase);
131+
if (idx >= 0) {
132+
string key = line.Substring (idx + designerFullName.Length);
133+
LogMessage ($"Looking for {key}.");
134+
if (lookup.TryGetValue (key, out MethodDefinition method)) {
135+
var importedMethod = designer.Module.ImportReference (method);
136+
var newIn = Instruction.Create (OpCodes.Call, importedMethod);
137+
instructions.Add (i, newIn);
138+
} else {
139+
LogMessage ($"DEBUG! Failed to find {key}!");
140+
}
141+
}
142+
}
143+
if (instructions.Count > 0)
144+
LogMessage ($" Fixing up {body.Method.FullName}");
145+
foreach (var i in instructions)
146+
{
147+
LogMessage ($" Replacing {i.Key}");
148+
LogMessage ($" With {i.Value}");
149+
processor.Replace(i.Key, i.Value);
150+
}
151+
}
152+
}
153+
}

src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,24 @@ protected bool FindResourceDesigner (AssemblyDefinition assembly, bool mainAppli
6767
return false;
6868
}
6969

70-
protected void ClearDesignerClass (TypeDefinition designer)
70+
protected void ClearDesignerClass (TypeDefinition designer, bool completely = false)
7171
{
7272
LogMessage ($" TryRemoving {designer.FullName}");
7373
// for each of the nested types clear all but the
7474
// int[] fields.
75-
for (int i = designer.NestedTypes.Count -1; i >= 0; i--) {
76-
var nestedType = designer.NestedTypes [i];
77-
RemoveFieldsFromType (nestedType, designer.Module);
78-
if (nestedType.Fields.Count == 0) {
79-
// no fields we do not need this class at all.
80-
designer.NestedTypes.RemoveAt (i);
75+
if (!completely) {
76+
for (int i = designer.NestedTypes.Count -1; i >= 0; i--) {
77+
var nestedType = designer.NestedTypes [i];
78+
RemoveFieldsFromType (nestedType, designer.Module);
79+
if (nestedType.Fields.Count == 0) {
80+
// no fields we do not need this class at all.
81+
designer.NestedTypes.RemoveAt (i);
82+
}
8183
}
84+
RemoveUpdateIdValues (designer);
85+
} else {
86+
designer.NestedTypes.Clear ();
8287
}
83-
RemoveUpdateIdValues (designer);
8488
designer.Fields.Clear ();
8589
designer.Properties.Clear ();
8690
designer.CustomAttributes.Clear ();

src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/Linker.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ static Pipeline CreatePipeline (LinkerOptions options)
111111
pipeline.AppendStep (new RemoveResources (options.I18nAssemblies)); // remove collation tables
112112
// end monodroid specific
113113

114+
if (options.UseDesignerAssembly)
115+
pipeline.AppendStep (new FixLegacyResourceDesignerStep (cache));
114116
pipeline.AppendStep (new FixAbstractMethodsStep (cache));
115117
pipeline.AppendStep (new MonoDroidMarkStep (cache));
116118
pipeline.AppendStep (new SweepStep ());

src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkerOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ class LinkerOptions
2626
public bool PreserveJniMarshalMethods { get; set; }
2727
public bool DeterministicOutput { get; set; }
2828
public bool LinkResources { get; set; }
29+
public bool UseDesignerAssembly { get; set; }
2930
}
3031
}

src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/MonoDroidProfile.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ protected override bool IsSdk (string assemblyName)
1919
{
2020
return assemblyName.Equals ("Java.Interop", StringComparison.Ordinal)
2121
|| assemblyName.Equals ("Java.Interop.GenericMarshaler", StringComparison.Ordinal)
22+
|| assemblyName.Equals ("Xamarin.Android.Resource.Designer", StringComparison.Ordinal)
2223
|| base.IsSdk (assemblyName);
2324
}
2425
}

src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
154154
<AndroidAapt2LinkExtraArgs Condition=" $(AndroidResgenExtraArgs.Contains('--no-version-vectors')) And !($(AndroidAapt2LinkExtraArgs.Contains('--no-version-vectors'))) ">--no-version-vectors $(AndroidAapt2LinkExtraArgs) </AndroidAapt2LinkExtraArgs>
155155
</PropertyGroup>
156156
<Aapt2Link
157-
Condition=" '$(_AndroidResourceDesignerFile)' != '' "
157+
Condition=" '$(_AndroidResourceDesignerFile)' != '' Or '$(AndroidUseDesignerAssembly)' == 'True' "
158158
ContinueOnError="$(DesignTimeBuild)"
159159
DaemonMaxInstanceCount="$(Aapt2DaemonMaxInstanceCount)"
160160
DaemonKeepInDomain="$(_Aapt2DaemonKeepInDomain)"

src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Designer.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ Copyright (C) 2016 Xamarin. All rights reserved.
145145
</Target>
146146

147147
<Target Name="SetupDependenciesForDesigner"
148-
DependsOnTargets="UpdateAndroidResources;_AdjustJavacVersionArguments;_GeneratePackageManagerJavaForDesigner;_GetMonoPlatformJarPath;_DetermineJavaLibrariesToCompile"
148+
DependsOnTargets="_ResolveMonoAndroidSdks;UpdateAndroidResources;_AdjustJavacVersionArguments;_GeneratePackageManagerJavaForDesigner;_GetMonoPlatformJarPath;_DetermineJavaLibrariesToCompile"
149149
Inputs="@(_AndroidMSBuildAllProjects);$(MonoPlatformJarPath);@(_JavaStubFiles);@(AndroidJavaSource)"
150150
Outputs="$(_AndroidStampDirectory)SetupDependenciesForDesigner.stamp">
151151
<Javac

0 commit comments

Comments
 (0)