From: Ankit Jain Date: Tue, 29 Mar 2016 21:23:06 +0000 (-0400) Subject: AL: Use IKVM.Reflection to get custom attributes from the template assembly, X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mono.git;a=commitdiff_plain;h=e4f1b8c13d59c69ac213a2db3cb28c3e08fff297 AL: Use IKVM.Reflection to get custom attributes from the template assembly, .. instead of System.Reflection. This allows AL to work even if the dependent assemblies of the template are not available. --- diff --git a/mcs/tools/al/Al.cs b/mcs/tools/al/Al.cs index caf1a67a5b2..bdc741144ea 100644 --- a/mcs/tools/al/Al.cs +++ b/mcs/tools/al/Al.cs @@ -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 (); + 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; diff --git a/mcs/tools/al/Makefile b/mcs/tools/al/Makefile index 280ddc00554..d2cea54c02e 100644 --- a/mcs/tools/al/Makefile +++ b/mcs/tools/al/Makefile @@ -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 diff --git a/mcs/tools/al/al.exe.sources b/mcs/tools/al/al.exe.sources index 08f674c872a..96d3be17ba5 100644 --- a/mcs/tools/al/al.exe.sources +++ b/mcs/tools/al/al.exe.sources @@ -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