-
Notifications
You must be signed in to change notification settings - Fork 528
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First Pass at using Resource Designer assembly
- Loading branch information
1 parent
b1180c8
commit 95e7992
Showing
9 changed files
with
262 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
...rin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<!-- | ||
*********************************************************************************************** | ||
Xamarin.Android.Resource.Designer.targets | ||
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have | ||
created a backup copy. Incorrect changes to this file will make it | ||
impossible to load or build your projects from the command-line or the IDE. | ||
This file imports the version- and platform-specific targets for the project importing | ||
this file. This file also defines targets to produce an error if the specified targets | ||
file does not exist, but the project is built anyway (command-line or IDE build). | ||
Copyright (C) 2016 Xamarin. All rights reserved. | ||
*********************************************************************************************** | ||
--> | ||
|
||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
|
||
<UsingTask TaskName="Xamarin.Android.Tasks.GenerateResourceDesignerAssembly" AssemblyFile="Xamarin.Android.Build.Tasks.dll" /> | ||
|
||
<PropertyGroup> | ||
<AndroidUseDesignerAssembly Condition=" '$(AndroidUseIntermediateDesignerFile)' == 'False' And '$(AndroidUseDesignerAssembly)' == '' ">True</AndroidUseDesignerAssembly> | ||
<AndroidUseDesignerAssembly Condition=" '$(AndroidUseDesignerAssembly)' == '' ">False</AndroidUseDesignerAssembly> | ||
<_GenerateResourceDesignerAssemblyOutput>$(IntermediateOutputPath)Xamarin.Android.Resource.Designer.dll</_GenerateResourceDesignerAssemblyOutput> | ||
</PropertyGroup> | ||
|
||
<Target Name="_GenerateResourceDesignerAssembly" | ||
Inputs="$(IntermediateOutputPath)R.txt" | ||
Outputs="$(_GenerateResourceDesignerAssemblyOutput)" | ||
Condition=" '$(AndroidUseDesignerAssembly)' == 'True' And Exists ('$(IntermediateOutputPath)R.txt') "> | ||
<ItemGroup> | ||
<_DesignerNamespaces Include="$(RootNamespace)" /> | ||
</ItemGroup> | ||
<GenerateResourceDesignerAssembly | ||
ContinueOnError="$(DesignTimeBuild)" | ||
RTxtFile="$(IntermediateOutputPath)R.txt" | ||
IsApplication="$(AndroidApplication)" | ||
DesignTimeBuild="$(DesignTimeBuild)" | ||
OutputFile="$(_GenerateResourceDesignerAssemblyOutput)" | ||
Namespaces="@(_DesignerNamespaces)" | ||
TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)" | ||
TargetFrameworkVersion="$(TargetFrameworkVersion)" | ||
UsingAndroidNETSdk="$(UsingAndroidNETSdk)" | ||
> | ||
</GenerateResourceDesignerAssembly> | ||
<ItemGroup> | ||
<FileWrites Include="$(_GenerateResourceDesignerAssemblyOutput)" /> | ||
<ReferencePath Include="$(_GenerateResourceDesignerAssemblyOutput)"> | ||
<CopyLocal>true</CopyLocal> | ||
</ReferencePath> | ||
<Compile Remove="$(_AndroidResourceDesignerFile)" /> | ||
</ItemGroup> | ||
</Target> | ||
|
||
<PropertyGroup> | ||
<BuildResourceDesignerDependsOn> | ||
$(_GenerateResourceDesignerAssembly) | ||
</BuildResourceDesignerDependsOn> | ||
</PropertyGroup> | ||
|
||
<Target Name="BuildResourceDesigner" Condition=" '$(AndroidUseDesignerAssembly)' == 'True' " | ||
DependsOnTargets="$(BuildResourceDesignerDependsOn)" /> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
184 changes: 184 additions & 0 deletions
184
src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
// Copyright (C) 2011 Xamarin, Inc. All rights reserved. | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.Versioning; | ||
using System.IO; | ||
using System.Linq; | ||
using Microsoft.Build.Framework; | ||
using Microsoft.Build.Utilities; | ||
using Microsoft.Android.Build.Tasks; | ||
using Mono.Cecil; | ||
using Mono.Cecil.Cil; | ||
|
||
namespace Xamarin.Android.Tasks | ||
{ | ||
public class GenerateResourceDesignerAssembly : AndroidTask | ||
{ | ||
const string DesignerAssemblyName = "Xamarin.Android.Resource.Designer"; | ||
public override string TaskPrefix => "GRDA"; | ||
|
||
[Required] | ||
public ITaskItem RTxtFile { get; set; } | ||
|
||
public ITaskItem ResourceMap { get; set; } | ||
|
||
[Required] | ||
public bool IsApplication { get; set; } | ||
|
||
[Required] | ||
public bool DesignTimeBuild { get; set; } | ||
|
||
[Required] | ||
public ITaskItem OutputFile { get; set; } | ||
|
||
[Required] | ||
public string TargetFrameworkVersion { get; set; } | ||
|
||
[Required] | ||
public string TargetFrameworkIdentifier { get; set; } | ||
|
||
[Required] | ||
public bool UsingAndroidNETSdk { get; set; } | ||
|
||
public string[] Namespaces { get; set; } | ||
|
||
public override bool RunTask () | ||
{ | ||
// Generate an assembly which contains all the values in the provided | ||
// R.txt file. | ||
var assembly = AssemblyDefinition.CreateAssembly ( | ||
new AssemblyNameDefinition (DesignerAssemblyName, new Version ()), | ||
DesignerAssemblyName, | ||
ModuleKind.Dll); | ||
|
||
var module = assembly.MainModule; | ||
|
||
if (!IsApplication) { | ||
MethodReference referenceAssemblyConstructor = module.ImportReference ( typeof (ReferenceAssemblyAttribute).GetConstructor (Type.EmptyTypes)); | ||
module.Assembly.CustomAttributes.Add (new CustomAttribute (referenceAssemblyConstructor)); | ||
} | ||
|
||
MethodReference targetFrameworkConstructor = module.ImportReference (typeof (TargetFrameworkAttribute).GetConstructor(new [] { typeof (string) })); | ||
var attr = new CustomAttribute (targetFrameworkConstructor); | ||
attr.ConstructorArguments.Add (new CustomAttributeArgument (module.TypeSystem.String, $"{TargetFrameworkIdentifier},Version={TargetFrameworkVersion}")); | ||
module.Assembly.CustomAttributes.Add (attr); | ||
|
||
if (UsingAndroidNETSdk) { | ||
// add .net 6 specific attributes we might not need these. | ||
// TargetPlatform | ||
// SupportedOSPlatform | ||
} | ||
|
||
if (!UsingAndroidNETSdk) | ||
module.AssemblyReferences.Add(AssemblyNameReference.Parse("mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e")); | ||
module.AssemblyReferences.Add(AssemblyNameReference.Parse("Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065")); | ||
module.AssemblyReferences.Add(AssemblyNameReference.Parse("System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e")); | ||
|
||
var att = TypeAttributes.Class | TypeAttributes.Public; | ||
|
||
var resourceDesigner = new TypeDefinition( | ||
DesignerAssemblyName, | ||
"Resource", | ||
att, | ||
module.TypeSystem.Object); | ||
module.Types.Add(resourceDesigner); | ||
|
||
ProcessRtxtFile (RTxtFile.ItemSpec, resourceDesigner, module); | ||
|
||
foreach (var ns in (Namespaces ?? Array.Empty<string> ())) { | ||
module.Types.Add (new TypeDefinition (ns, "Resource", att, resourceDesigner)); | ||
} | ||
|
||
assembly.Write (OutputFile.ItemSpec); | ||
return !Log.HasLoggedErrors; | ||
} | ||
|
||
void ProcessRtxtFile (string file, TypeDefinition resourceDesigner, ModuleDefinition module) | ||
{ | ||
var lines = System.IO.File.ReadLines (file); | ||
foreach (var line in lines) { | ||
var items = line.Split (new char [] { ' ' }, 4); | ||
int value = items [1] != "styleable" ? Convert.ToInt32 (items [3], 16) : -1; | ||
string itemName = items [2]; | ||
switch (items [1]) { | ||
case "anim": | ||
case "animator": | ||
case "attr": | ||
case "array": | ||
case "bool": | ||
case "color": | ||
case "dimen": | ||
case "drawable": | ||
case "font": | ||
case "id": | ||
case "integer": | ||
case "interpolator": | ||
case "layout": | ||
case "menu": | ||
case "mipmap": | ||
case "plurals": | ||
case "raw": | ||
case "string": | ||
case "style": | ||
case "transition": | ||
case "xml": | ||
CreateIntProperty (items [1], itemName, value, resourceDesigner, module); | ||
break; | ||
// case "styleable": | ||
// switch (items [0]) { | ||
// case "int": | ||
// CreateIntField (styleable, itemName, Convert.ToInt32 (items [3], 10)); | ||
// break; | ||
// case "int[]": | ||
// var arrayValues = items [3].Trim (new char [] { '{', '}' }) | ||
// .Replace (" ", "") | ||
// .Split (new char [] { ',' }); | ||
// CreateIntArrayField (styleable, itemName, arrayValues.Length, | ||
// arrayValues.Select (x => string.IsNullOrEmpty (x) ? -1 : Convert.ToInt32 (x, 16)).ToArray ()); | ||
// break; | ||
// } | ||
// break; | ||
// for custom views | ||
default: | ||
CreateIntProperty (items [1], itemName, value, resourceDesigner, module); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
void CreateIntProperty (string resourceClass, string propertyName, int value, TypeDefinition resourceDesigner, ModuleDefinition module) | ||
{ | ||
TypeDefinition nestedType = CreateResourceClass (resourceDesigner, resourceClass, module); | ||
PropertyDefinition p = CreateProperty (propertyName, value, module); | ||
nestedType.Properties.Add (p); | ||
nestedType.Methods.Add (p.GetMethod); | ||
} | ||
|
||
Dictionary<string, TypeDefinition> resourceClasses = new Dictionary<string, TypeDefinition> (); | ||
|
||
TypeDefinition CreateResourceClass (TypeDefinition resourceDesigner, string className, ModuleDefinition module) | ||
{ | ||
string name = ResourceParser.GetNestedTypeName (className); | ||
if (resourceClasses.ContainsKey (name)) { | ||
return resourceClasses[name]; | ||
} | ||
var resourceClass = new TypeDefinition (DesignerAssemblyName, name, TypeAttributes.Class | TypeAttributes.Public, module.TypeSystem.Object); | ||
resourceDesigner.NestedTypes.Add(resourceClass); | ||
resourceClasses [name] = resourceClass; | ||
return resourceClass; | ||
} | ||
|
||
PropertyDefinition CreateProperty (string propertyName, int value, ModuleDefinition module) | ||
{ | ||
var p = new PropertyDefinition (propertyName, PropertyAttributes.None, module.TypeSystem.Int32); | ||
var getter = new MethodDefinition ($"{propertyName}_get", MethodAttributes.Public | MethodAttributes.Static, module.TypeSystem.Int32); | ||
p.GetMethod = getter; | ||
p.SetMethod = null; | ||
var il = p.GetMethod.Body.GetILProcessor (); | ||
il.Emit (OpCodes.Ldc_I4, value); | ||
il.Emit (OpCodes.Ret); | ||
return p; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters