AL: Use IKVM.Reflection to get custom attributes from the template assembly,
authorAnkit Jain <ankit.jain@xamarin.com>
Tue, 29 Mar 2016 21:23:06 +0000 (17:23 -0400)
committerAnkit Jain <ankit.jain@xamarin.com>
Tue, 5 Apr 2016 22:30:27 +0000 (18:30 -0400)
.. instead of System.Reflection. This allows AL to work even if the
dependent assemblies of the template are not available.

mcs/tools/al/Al.cs
mcs/tools/al/Makefile
mcs/tools/al/al.exe.sources

index caf1a67a5b2a322c1a2020f6dbcec1b674f9e242..bdc741144ea595cb7d7bcbeb8b509e5a3e225148 100644 (file)
@@ -12,6 +12,7 @@ using System;
 using System.Globalization;
 using System.IO;
 using System.Collections;
+using System.Collections.Generic;
 using System.Reflection;
 using System.Reflection.Emit;
 using System.Security.Cryptography;
@@ -19,6 +20,7 @@ using System.Text;
 using System.Configuration.Assemblies;
 
 using Mono.Security.Cryptography;
+using IKR = IKVM.Reflection;
 
 namespace Mono.AssemblyLinker
 {
@@ -591,46 +593,8 @@ namespace Mono.AssemblyLinker
                         * Emit Manifest
                         * */
 
-                       if (isTemplateFile) {
-                               // LAMESPEC: according to MSDN, the template assembly must have a
-                               // strong name but this is not enforced
-                               Assembly assembly = Assembly.LoadFrom (templateFile);
-
-                               // inherit signing related settings from template, but do not
-                               // override command-line options
-                               object [] attrs = assembly.GetCustomAttributes (true);
-                               foreach (object o in attrs) {
-                                       if (o is AssemblyKeyFileAttribute) {
-                                               if (keyfile != null)
-                                                       // ignore if specified on command line
-                                                       continue;
-                                               AssemblyKeyFileAttribute keyFileAttr = (AssemblyKeyFileAttribute) o;
-                                               // ignore null or zero-length keyfile
-                                               if (keyFileAttr.KeyFile == null || keyFileAttr.KeyFile.Length == 0)
-                                                       continue;
-                                               keyfile = Path.Combine (Path.GetDirectoryName(templateFile),
-                                                       keyFileAttr.KeyFile);
-                                       } else if (o is AssemblyDelaySignAttribute) {
-                                               if (delaysign != DelaySign.NotSet)
-                                                       // ignore if specified on command line
-                                                       continue;
-                                               AssemblyDelaySignAttribute delaySignAttr = (AssemblyDelaySignAttribute) o;
-                                               delaysign = delaySignAttr.DelaySign ? DelaySign.Yes :
-                                                       DelaySign.No;
-                                       } else if (o is AssemblyKeyNameAttribute) {
-                                               if (keyname != null)
-                                                       // ignore if specified on command line
-                                                       continue;
-                                               AssemblyKeyNameAttribute keynameAttr = (AssemblyKeyNameAttribute) o;
-                                               // ignore null or zero-length keyname
-                                               if (keynameAttr.KeyName == null || keynameAttr.KeyName.Length == 0)
-                                                       continue;
-                                               keyname = keynameAttr.KeyName;
-                                       }
-                               }
-                               aname.Version = assembly.GetName().Version;
-                               aname.HashAlgorithm = assembly.GetName().HashAlgorithm;
-                       }
+                       if (isTemplateFile)
+                               aname = ReadCustomAttributesFromTemplateFile (templateFile, aname);
 
                        SetKeyPair (aname);
 
@@ -765,6 +729,85 @@ namespace Mono.AssemblyLinker
                        }
                }
 
+               private AssemblyName ReadCustomAttributesFromTemplateFile (string templateFile, AssemblyName aname)
+               {
+                       // LAMESPEC: according to MSDN, the template assembly must have a
+                       // strong name but this is not enforced
+                       const IKR.UniverseOptions options = IKR.UniverseOptions.MetadataOnly;
+
+                       var universe = new IKR.Universe (options);
+                       var asm = universe.LoadFile (templateFile);
+
+                       // Create missing assemblies, we don't want to load them!
+                       // Code taken from ikdasm
+                       var names = new HashSet<string> ();
+                       IKR.AssemblyName[] assembly_refs = asm.ManifestModule.__GetReferencedAssemblies ();
+
+                       var resolved_assemblies = new IKR.Assembly [assembly_refs.Length];
+                       for (int i = 0; i < resolved_assemblies.Length; i++) {
+                               string name = assembly_refs [i].Name;
+
+                               while (names.Contains (name)) {
+                                       name = name + "_" + i;
+                               }
+                               names.Add (name);
+                               resolved_assemblies [i] = universe.CreateMissingAssembly (assembly_refs [i].FullName);
+                       }
+                       asm.ManifestModule.__ResolveReferencedAssemblies (resolved_assemblies);
+
+                       foreach (var attr_data in asm.__GetCustomAttributes (null, false)) {
+                               string asm_name = attr_data.AttributeType.Assembly.GetName ().Name;
+                               if (asm_name != "mscorlib")
+                                       continue;
+
+                               switch (attr_data.AttributeType.FullName) {
+                                       case "System.Reflection.AssemblyKeyFileAttribute": {
+                                               if (keyfile != null)
+                                                       // ignore if specified on command line
+                                                       continue;
+
+                                               // / AssemblyKeyFileAttribute .ctor(string keyFile)
+                                               string key_file_value = (string) attr_data.ConstructorArguments [0].Value;
+
+                                               if (!String.IsNullOrEmpty (key_file_value))
+                                                       keyfile = Path.Combine (Path.GetDirectoryName (templateFile), key_file_value);
+                                       }
+                                       break;
+
+                                       case "System.Reflection.AssemblyDelaySignAttribute": {
+                                               if (delaysign != DelaySign.NotSet)
+                                                       // ignore if specified on command line
+                                                       continue;
+
+                                               // AssemblyDelaySignAttribute .ctor(bool delaySign)
+                                               bool delay_sign_value = (bool) attr_data.ConstructorArguments [0].Value;
+                                               delaysign = delay_sign_value ? DelaySign.Yes : DelaySign.No;
+                                       }
+                                       break;
+
+                                       case "System.Reflection.AssemblyKeyNameAttribute": {
+                                               if (keyname != null)
+                                                       // ignore if specified on command line
+                                                       continue;
+
+                                               // AssemblyKeyNameAttribute .ctor(string keyName)
+                                               string key_name_value = (string) attr_data.ConstructorArguments [0].Value;
+
+                                               // ignore null or zero-length keyname
+                                               if (!String.IsNullOrEmpty (key_name_value))
+                                                       keyname = key_name_value;
+                                       }
+                                       break;
+                               }
+                       }
+
+                       var asm_name_for_template_file = asm.GetName ();
+                       aname.Version = asm_name_for_template_file.Version;
+                       aname.HashAlgorithm = asm_name_for_template_file.HashAlgorithm;
+
+                       return aname;
+               }
+
                private void LoadArgs (string file, ArrayList args) {
                        StreamReader f = null;
                        string line;
index 280ddc005548f8f161e73a3ac3d2438cb1ff8bb9..d2cea54c02e12c544c56576c93308018b211d71a 100644 (file)
@@ -3,7 +3,7 @@ SUBDIRS =
 include ../../build/rules.make
 
 LOCAL_MCS_FLAGS =
-LIB_REFS = Mono.Security
+LIB_REFS = System System.Core Mono.Security System.Security Mono.CompilerServices.SymbolWriter
 PROGRAM = al.exe
 
 CLEAN_FILES = al.exe al.exe.mdb
index 08f674c872a3517204d766c24283477200aa0991..96d3be17ba56dbd1414eefabea4bb4a5704559b1 100644 (file)
@@ -1,2 +1,9 @@
 Al.cs
 ../../build/common/Consts.cs
+../../../external/ikvm/reflect/*.cs
+../../../external/ikvm/reflect/Emit/*.cs
+../../../external/ikvm/reflect/Metadata/*.cs
+../../../external/ikvm/reflect/Reader/*.cs
+../../../external/ikvm/reflect/Writer/*.cs
+../../../external/ikvm/reflect/Impl/*.cs
+../../../external/ikvm/reflect/Properties/*.cs