2 // assembly.cs: Assembly declaration and specifications
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
8 // Copyright 2001, 2002, 2003 Ximian, Inc.
9 // Copyright 2004 Novell, Inc.
15 using System.Collections.Generic;
16 using System.Globalization;
17 using System.Reflection;
18 using System.Reflection.Emit;
19 using System.Security;
20 using System.Security.Cryptography;
21 using System.Security.Permissions;
23 using Mono.Security.Cryptography;
24 using Mono.CompilerServices.SymbolWriter;
28 public interface IAssemblyDefinition
30 string FullName { get; }
31 bool HasExtensionMethod { get; }
32 bool IsCLSCompliant { get; }
35 byte[] GetPublicKeyToken ();
38 public class AssemblyDefinition : IAssemblyDefinition
40 // TODO: make it private and move all builder based methods here
41 public AssemblyBuilder Builder;
42 AssemblyBuilderExtension builder_extra;
43 MonoSymbolWriter symbol_writer;
45 bool is_cls_compliant;
46 bool wrap_non_exception_throws;
47 bool wrap_non_exception_throws_custom;
49 ModuleContainer module;
53 byte[] public_key, public_key_token;
56 // Holds private/public key pair when private key
58 StrongNameKeyPair private_key;
60 Attribute cls_attribute;
63 List<ImportedModuleDefinition> added_modules;
64 Dictionary<SecurityAction, PermissionSet> declarative_security;
65 Dictionary<ITypeDefinition, Attribute> emitted_forwarders;
66 AssemblyAttributesPlaceholder module_target_attrs;
69 // In-memory only assembly container
71 public AssemblyDefinition (ModuleContainer module, string name)
74 this.name = Path.GetFileNameWithoutExtension (name);
76 wrap_non_exception_throws = true;
78 delay_sign = RootContext.StrongNameDelaySign;
81 // Load strong name key early enough for assembly importer to be able to
82 // use the keys for InternalsVisibleTo
83 // This should go somewhere close to ReferencesLoading but don't have the place yet
85 if (RootContext.StrongNameKeyFile != null || RootContext.StrongNameKeyContainer != null) {
86 LoadPublicKey (RootContext.StrongNameKeyFile, RootContext.StrongNameKeyContainer);
91 // Assembly container with file output
93 public AssemblyDefinition (ModuleContainer module, string name, string fileName)
96 this.file_name = fileName;
101 public Attribute CLSCompliantAttribute {
103 return cls_attribute;
107 public CompilerContext Compiler {
109 return module.Compiler;
114 // Assembly entry point, aka Main method
116 public Method EntryPoint {
125 public string FullName {
127 return Builder.FullName;
131 public bool HasExtensionMethod {
133 return module.HasExtensionMethod;
137 public bool HasCLSCompliantAttribute {
139 return cls_attribute != null;
143 // TODO: This should not exist here but will require more changes
144 public MetadataImporter Importer {
148 public bool IsCLSCompliant {
150 return is_cls_compliant;
160 public bool WrapNonExceptionThrows {
162 return wrap_non_exception_throws;
168 return Compiler.Report;
174 public void AddModule (string moduleFile)
176 var mod = builder_extra.AddModule (moduleFile);
177 var imported = Importer.ImportModule (mod, module.GlobalRootNamespace);
179 if (added_modules == null) {
180 added_modules = new List<ImportedModuleDefinition> ();
181 added_modules.Add (imported);
185 public void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
187 if (a.IsValidSecurityAttribute ()) {
188 if (declarative_security == null)
189 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
191 a.ExtractSecurityPermissionSet (declarative_security);
195 if (a.Type == pa.AssemblyCulture) {
196 string value = a.GetString ();
197 if (value == null || value.Length == 0)
200 if (RootContext.Target == Target.Exe) {
201 a.Error_AttributeEmitError ("The executables cannot be satelite assemblies, remove the attribute or keep it empty");
205 if (value == "neutral")
208 if (RootContext.Target == Target.Module) {
209 SetCustomAttribute (ctor, cdata);
211 builder_extra.SetCulture (value, a.Location);
217 if (a.Type == pa.AssemblyVersion) {
218 string value = a.GetString ();
219 if (value == null || value.Length == 0)
222 var vinfo = IsValidAssemblyVersion (value.Replace ('*', '0'));
224 a.Error_AttributeEmitError (string.Format ("Specified version `{0}' is not valid", value));
228 if (RootContext.Target == Target.Module) {
229 SetCustomAttribute (ctor, cdata);
231 builder_extra.SetVersion (vinfo, a.Location);
237 if (a.Type == pa.AssemblyAlgorithmId) {
238 const int pos = 2; // skip CA header
239 uint alg = (uint) cdata [pos];
240 alg |= ((uint) cdata [pos + 1]) << 8;
241 alg |= ((uint) cdata [pos + 2]) << 16;
242 alg |= ((uint) cdata [pos + 3]) << 24;
244 if (RootContext.Target == Target.Module) {
245 SetCustomAttribute (ctor, cdata);
247 builder_extra.SetAlgorithmId (alg, a.Location);
253 if (a.Type == pa.AssemblyFlags) {
254 const int pos = 2; // skip CA header
255 uint flags = (uint) cdata[pos];
256 flags |= ((uint) cdata [pos + 1]) << 8;
257 flags |= ((uint) cdata [pos + 2]) << 16;
258 flags |= ((uint) cdata [pos + 3]) << 24;
260 // Ignore set PublicKey flag if assembly is not strongnamed
261 if ((flags & (uint) AssemblyNameFlags.PublicKey) != 0 && public_key == null)
262 flags &= ~(uint) AssemblyNameFlags.PublicKey;
264 if (RootContext.Target == Target.Module) {
265 SetCustomAttribute (ctor, cdata);
267 builder_extra.SetFlags (flags, a.Location);
273 if (a.Type == pa.TypeForwarder) {
274 TypeSpec t = a.GetArgumentType ();
275 if (t == null || TypeManager.HasElementType (t)) {
276 Report.Error (735, a.Location, "Invalid type specified as an argument for TypeForwardedTo attribute");
280 if (emitted_forwarders == null) {
281 emitted_forwarders = new Dictionary<ITypeDefinition, Attribute> ();
282 } else if (emitted_forwarders.ContainsKey (t.MemberDefinition)) {
283 Report.SymbolRelatedToPreviousError (emitted_forwarders[t.MemberDefinition].Location, null);
284 Report.Error (739, a.Location, "A duplicate type forward of type `{0}'",
285 TypeManager.CSharpName (t));
289 emitted_forwarders.Add (t.MemberDefinition, a);
291 if (t.MemberDefinition.DeclaringAssembly == this) {
292 Report.SymbolRelatedToPreviousError (t);
293 Report.Error (729, a.Location, "Cannot forward type `{0}' because it is defined in this assembly",
294 TypeManager.CSharpName (t));
299 Report.Error (730, a.Location, "Cannot forward type `{0}' because it is a nested type",
300 TypeManager.CSharpName (t));
304 builder_extra.AddTypeForwarder (t.GetDefinition (), a.Location);
308 if (a.Type == pa.Extension) {
309 a.Error_MisusedExtensionAttribute ();
313 if (a.Type == pa.InternalsVisibleTo) {
314 string assembly_name = a.GetString ();
315 if (assembly_name.Length == 0)
318 AssemblyName aname = null;
320 aname = new AssemblyName (assembly_name);
321 } catch (Exception) {
322 Report.Warning (1700, 3, a.Location, "Assembly reference `{0}' is invalid and cannot be resolved",
327 if (aname.Version != null || aname.CultureInfo != null || aname.ProcessorArchitecture != ProcessorArchitecture.None) {
328 Report.Error (1725, a.Location,
329 "Friend assembly reference `{0}' is invalid. InternalsVisibleTo declarations cannot have a version, culture or processor architecture specified",
335 // TODO: GetPublicKey () does not work on .NET when AssemblyName is constructed from a string
336 if (public_key != null && aname.GetPublicKey () == null) {
337 Report.Error (1726, a.Location,
338 "Friend assembly reference `{0}' is invalid. Strong named assemblies must specify a public key in their InternalsVisibleTo declarations",
342 } else if (a.Type == pa.RuntimeCompatibility) {
343 wrap_non_exception_throws_custom = true;
346 SetCustomAttribute (ctor, cdata);
350 // When using assembly public key attributes InternalsVisibleTo key
351 // was not checked, we have to do it later when we actually know what
352 // our public key token is
354 void CheckReferencesPublicToken ()
356 // TODO: It should check only references assemblies but there is
357 // no working SRE API
358 foreach (var a in Importer.Assemblies) {
359 if (public_key != null && !a.HasStrongName) {
360 Report.Error (1577, "Referenced assembly `{0}' does not have a strong name",
364 if (!a.IsFriendAssemblyTo (this))
367 var attr = a.GetAssemblyVisibleToName (this);
368 var atoken = attr.GetPublicKeyToken ();
370 if (ArrayComparer.IsEqual (GetPublicKeyToken (), atoken))
374 "Friend access was granted to `{0}', but the output assembly is named `{1}'. Try adding a reference to `{0}' or change the output assembly name to match it",
375 attr.FullName, FullName);
380 // Initializes the code generator
382 public bool Create (AppDomain domain, AssemblyBuilderAccess access)
384 ResolveAssemblySecurityAttributes ();
386 var an = new AssemblyName (name);
388 if (public_key != null && RootContext.Target != Target.Module) {
390 an.SetPublicKey (public_key);
392 if (public_key.Length == 16) {
393 Report.Error (1606, "Could not sign the assembly. ECMA key can only be used to delay-sign assemblies");
394 } else if (private_key == null) {
395 Error_AssemblySigning ("The specified key file does not have a private key");
397 an.KeyPair = private_key;
403 Builder = file_name == null ?
404 domain.DefineDynamicAssembly (an, access) :
405 domain.DefineDynamicAssembly (an, access, Dirname (file_name));
406 } catch (ArgumentException) {
407 // specified key may not be exportable outside it's container
408 if (RootContext.StrongNameKeyContainer != null) {
409 Report.Error (1548, "Could not access the key inside the container `" +
410 RootContext.StrongNameKeyContainer + "'.");
415 builder_extra = new AssemblyBuilderMonoSpecific (Builder, Compiler);
419 public ModuleBuilder CreateModuleBuilder ()
421 // Creates transient module
422 if (file_name == null)
423 return Builder.DefineDynamicModule (name, false);
425 var module_name = Path.GetFileName (file_name);
427 // Always initialize module without symbolInfo. We could be framework dependent
428 // but returned ISymbolWriter does not have all what we need therefore some
429 // adaptor will be needed for now we alwayas emit MDB format when generating
431 return Builder.DefineDynamicModule (module_name, module_name, false);
434 static string Dirname (string name)
436 int pos = name.LastIndexOf ('/');
439 return name.Substring (0, pos);
441 pos = name.LastIndexOf ('\\');
443 return name.Substring (0, pos);
450 if (RootContext.Target == Target.Module) {
451 module_target_attrs = new AssemblyAttributesPlaceholder (module, name);
452 module_target_attrs.CreateType ();
453 module_target_attrs.DefineType ();
454 module_target_attrs.Define ();
455 module.AddCompilerGeneratedClass (module_target_attrs);
456 } else if (added_modules != null) {
457 ReadModulesAssemblyAttributes ();
460 if (RootContext.GenerateDebugInfo) {
461 symbol_writer = new MonoSymbolWriter (file_name);
463 // TODO: global variables
464 Location.DefineSymbolDocuments (symbol_writer);
465 SymbolWriter.symwriter = symbol_writer;
470 if (module.HasExtensionMethod) {
471 var pa = module.PredefinedAttributes.Extension;
473 SetCustomAttribute (pa.Constructor, AttributeEncoder.Empty);
477 if (!wrap_non_exception_throws_custom) {
478 PredefinedAttribute pa = module.PredefinedAttributes.RuntimeCompatibility;
479 if (pa.IsDefined && pa.ResolveBuilder ()) {
480 var prop = pa.GetProperty ("WrapNonExceptionThrows", TypeManager.bool_type, Location.Null);
482 AttributeEncoder encoder = new AttributeEncoder (false);
483 encoder.EncodeNamedPropertyArgument (prop, new BoolLiteral (true, Location.Null));
484 SetCustomAttribute (pa.Constructor, encoder.ToArray ());
489 if (declarative_security != null) {
490 var args = new PermissionSet[3];
491 declarative_security.TryGetValue (SecurityAction.RequestMinimum, out args[0]);
492 declarative_security.TryGetValue (SecurityAction.RequestOptional, out args[1]);
493 declarative_security.TryGetValue (SecurityAction.RequestRefuse, out args[2]);
494 builder_extra.AddPermissionRequests (args);
497 CheckReferencesPublicToken ();
502 public byte[] GetPublicKeyToken ()
504 if (public_key == null || public_key_token != null)
505 return public_key_token;
507 HashAlgorithm ha = SHA1.Create ();
508 byte[] hash = ha.ComputeHash (public_key);
509 // we need the last 8 bytes in reverse order
510 public_key_token = new byte[8];
511 Array.Copy (hash, (hash.Length - 8), public_key_token, 0, 8);
512 Array.Reverse (public_key_token, 0, 8);
513 return public_key_token;
517 // Either keyFile or keyContainer has to be non-null
519 void LoadPublicKey (string keyFile, string keyContainer)
521 if (keyContainer != null) {
523 private_key = new StrongNameKeyPair (keyContainer);
524 public_key = private_key.PublicKey;
526 Error_AssemblySigning ("The specified key container `" + keyContainer + "' does not exist");
532 bool key_file_exists = File.Exists (keyFile);
535 // For attribute based KeyFile do additional lookup
536 // in output assembly path
538 if (!key_file_exists && RootContext.StrongNameKeyFile == null) {
540 // The key file can be relative to output assembly
542 string test_path = Path.Combine (Path.GetDirectoryName (file_name), keyFile);
543 key_file_exists = File.Exists (test_path);
548 if (!key_file_exists) {
549 Error_AssemblySigning ("The specified key file `" + keyFile + "' does not exist");
553 using (FileStream fs = new FileStream (keyFile, FileMode.Open, FileAccess.Read)) {
554 byte[] snkeypair = new byte[fs.Length];
555 fs.Read (snkeypair, 0, snkeypair.Length);
557 // check for ECMA key
558 if (snkeypair.Length == 16) {
559 public_key = snkeypair;
564 // take it, with or without, a private key
565 RSA rsa = CryptoConvert.FromCapiKeyBlob (snkeypair);
566 // and make sure we only feed the public part to Sys.Ref
567 byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa);
569 // AssemblyName.SetPublicKey requires an additional header
570 byte[] publicKeyHeader = new byte[12] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00 };
573 public_key = new byte[12 + publickey.Length];
574 Buffer.BlockCopy (publicKeyHeader, 0, public_key, 0, 12);
575 Buffer.BlockCopy (publickey, 0, public_key, 12, publickey.Length);
577 Error_AssemblySigning ("The specified key file `" + keyFile + "' has incorrect format");
585 // TODO: Is there better way to test for a private key presence ?
586 CryptoConvert.FromCapiPrivateKeyBlob (snkeypair);
587 private_key = new StrongNameKeyPair (snkeypair);
592 void ReadModulesAssemblyAttributes ()
594 foreach (var m in added_modules) {
595 var cattrs = m.ReadAssemblyAttributes ();
599 module.OptAttributes.AddAttributes (cattrs);
603 public void Resolve ()
605 if (RootContext.Unsafe) {
607 // Emits [assembly: SecurityPermissionAttribute (SecurityAction.RequestMinimum, SkipVerification = true)]
608 // when -unsafe option was specified
611 Location loc = Location.Null;
613 MemberAccess system_security_permissions = new MemberAccess (new MemberAccess (
614 new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Security", loc), "Permissions", loc);
616 Arguments pos = new Arguments (1);
617 pos.Add (new Argument (new MemberAccess (new MemberAccess (system_security_permissions, "SecurityAction", loc), "RequestMinimum")));
619 Arguments named = new Arguments (1);
620 named.Add (new NamedArgument ("SkipVerification", loc, new BoolLiteral (true, loc)));
622 GlobalAttribute g = new GlobalAttribute (new NamespaceEntry (module, null, null, null), "assembly",
623 new MemberAccess (system_security_permissions, "SecurityPermissionAttribute"),
624 new Arguments[] { pos, named }, loc, false);
625 g.AttachTo (module, module);
627 if (g.Resolve () != null) {
628 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
629 g.ExtractSecurityPermissionSet (declarative_security);
633 if (module.OptAttributes == null)
636 // Ensure that we only have GlobalAttributes, since the Search isn't safe with other types.
637 if (!module.OptAttributes.CheckTargets())
640 cls_attribute = module.ResolveAssemblyAttribute (module.PredefinedAttributes.CLSCompliant);
642 if (cls_attribute != null) {
643 is_cls_compliant = cls_attribute.GetClsCompliantAttributeValue ();
646 if (added_modules != null && RootContext.VerifyClsCompliance && is_cls_compliant) {
647 foreach (var m in added_modules) {
648 if (!m.IsCLSCompliant) {
650 "Added modules must be marked with the CLSCompliant attribute to match the assembly",
656 Attribute a = module.ResolveAssemblyAttribute (module.PredefinedAttributes.RuntimeCompatibility);
658 var val = a.GetNamedValue ("WrapNonExceptionThrows") as BoolConstant;
660 wrap_non_exception_throws = val.Value;
664 void ResolveAssemblySecurityAttributes ()
666 string key_file = null;
667 string key_container = null;
669 if (module.OptAttributes != null) {
670 foreach (Attribute a in module.OptAttributes.Attrs) {
671 // cannot rely on any resolve-based members before you call Resolve
672 if (a.ExplicitTarget != "assembly")
675 // TODO: This code is buggy: comparing Attribute name without resolving is wrong.
676 // However, this is invoked by CodeGen.Init, when none of the namespaces
678 // TODO: Does not handle quoted attributes properly
680 case "AssemblyKeyFile":
681 case "AssemblyKeyFileAttribute":
682 case "System.Reflection.AssemblyKeyFileAttribute":
683 if (RootContext.StrongNameKeyFile != null) {
684 Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ());
685 Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
686 "keyfile", "System.Reflection.AssemblyKeyFileAttribute");
688 string value = a.GetString ();
689 if (!string.IsNullOrEmpty (value)) {
690 Error_ObsoleteSecurityAttribute (a, "keyfile");
695 case "AssemblyKeyName":
696 case "AssemblyKeyNameAttribute":
697 case "System.Reflection.AssemblyKeyNameAttribute":
698 if (RootContext.StrongNameKeyContainer != null) {
699 Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ());
700 Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
701 "keycontainer", "System.Reflection.AssemblyKeyNameAttribute");
703 string value = a.GetString ();
704 if (!string.IsNullOrEmpty (value)) {
705 Error_ObsoleteSecurityAttribute (a, "keycontainer");
706 key_container = value;
710 case "AssemblyDelaySign":
711 case "AssemblyDelaySignAttribute":
712 case "System.Reflection.AssemblyDelaySignAttribute":
713 bool b = a.GetBoolean ();
715 Error_ObsoleteSecurityAttribute (a, "delaysign");
724 // We came here only to report assembly attributes warnings
725 if (public_key != null)
729 // Load the strong key file found in attributes when no
730 // command line key was given
732 if (key_file != null || key_container != null) {
733 LoadPublicKey (key_file, key_container);
734 } else if (delay_sign) {
735 Report.Warning (1607, 1, "Delay signing was requested but no key file was given");
739 public void EmbedResources ()
742 // Add Win32 resources
744 if (RootContext.Win32ResourceFile != null) {
745 Builder.DefineUnmanagedResource (RootContext.Win32ResourceFile);
747 Builder.DefineVersionInfoResource ();
750 if (RootContext.Win32IconFile != null) {
751 builder_extra.DefineWin32IconResource (RootContext.Win32IconFile);
754 if (RootContext.Resources != null) {
755 if (RootContext.Target == Target.Module) {
756 Report.Error (1507, "Cannot link resource file when building a module");
758 foreach (var res in RootContext.Resources) {
759 if (!File.Exists (res.FileName)) {
760 Report.Error (1566, "Error reading resource file `{0}'", res.FileName);
765 var stream = File.OpenRead (res.FileName);
766 module.Builder.DefineManifestResource (res.Name, stream, res.Attributes);
768 Builder.AddResourceFile (res.Name, Path.GetFileName (res.FileName), res.Attributes);
777 PortableExecutableKinds pekind;
778 ImageFileMachine machine;
780 switch (RootContext.Platform) {
782 pekind = PortableExecutableKinds.Required32Bit | PortableExecutableKinds.ILOnly;
783 machine = ImageFileMachine.I386;
786 pekind = PortableExecutableKinds.ILOnly;
787 machine = ImageFileMachine.AMD64;
790 pekind = PortableExecutableKinds.ILOnly;
791 machine = ImageFileMachine.IA64;
793 case Platform.AnyCPU:
795 pekind = PortableExecutableKinds.ILOnly;
796 machine = ImageFileMachine.I386;
800 if (RootContext.Target == Target.Module) {
801 builder_extra.SetModuleTarget ();
805 Builder.Save (module.Builder.ScopeName, pekind, machine);
806 } catch (Exception e) {
807 Report.Error (16, "Could not write to file `" + name + "', cause: " + e.Message);
810 // Save debug symbols file
811 if (symbol_writer != null) {
812 // TODO: it should run in parallel
813 symbol_writer.WriteSymbolFile (SymbolWriter.GetGuid (module.Builder));
817 void SetCustomAttribute (MethodSpec ctor, byte[] data)
819 if (module_target_attrs != null)
820 module_target_attrs.AddAssemblyAttribute (ctor, data);
822 Builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), data);
825 void SetEntryPoint ()
827 if (!RootContext.NeedsEntryPoint) {
828 if (RootContext.MainClass != null)
829 Report.Error (2017, "Cannot specify -main if building a module or library");
834 PEFileKinds file_kind;
836 switch (RootContext.Target) {
839 file_kind = PEFileKinds.Dll;
842 file_kind = PEFileKinds.WindowApplication;
845 file_kind = PEFileKinds.ConsoleApplication;
849 if (entry_point == null) {
850 if (RootContext.MainClass != null) {
851 // TODO: Should use MemberCache
852 DeclSpace main_cont = module.GetDefinition (RootContext.MainClass) as DeclSpace;
853 if (main_cont == null) {
854 Report.Error (1555, "Could not find `{0}' specified for Main method", RootContext.MainClass);
858 if (!(main_cont is ClassOrStruct)) {
859 Report.Error (1556, "`{0}' specified for Main method must be a valid class or struct", RootContext.MainClass);
863 Report.Error (1558, main_cont.Location, "`{0}' does not have a suitable static Main method", main_cont.GetSignatureForError ());
867 if (Report.Errors == 0) {
868 string pname = file_name == null ? name : Path.GetFileName (file_name);
870 Report.Error (5001, "Program `{0}' does not contain a static `Main' method suitable for an entry point",
877 Builder.SetEntryPoint (entry_point.MethodBuilder, file_kind);
880 void Error_ObsoleteSecurityAttribute (Attribute a, string option)
882 Report.Warning (1699, 1, a.Location,
883 "Use compiler option `{0}' or appropriate project settings instead of `{1}' attribute",
887 void Error_AssemblySigning (string text)
889 Report.Error (1548, "Error during assembly signing. " + text);
892 static Version IsValidAssemblyVersion (string version)
896 v = new Version (version);
899 int major = int.Parse (version, CultureInfo.InvariantCulture);
900 v = new Version (major, 0);
906 foreach (int candidate in new int [] { v.Major, v.Minor, v.Build, v.Revision }) {
907 if (candidate > ushort.MaxValue)
911 return new Version (v.Major, System.Math.Max (0, v.Minor), System.Math.Max (0, v.Build), System.Math.Max (0, v.Revision));
915 public class AssemblyResource : IEquatable<AssemblyResource>
917 public AssemblyResource (string fileName, string name)
918 : this (fileName, name, false)
922 public AssemblyResource (string fileName, string name, bool isPrivate)
926 Attributes = isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public;
929 public ResourceAttributes Attributes { get; private set; }
930 public string Name { get; private set; }
931 public string FileName { get; private set; }
932 public bool IsEmbeded { get; set; }
934 #region IEquatable<AssemblyResource> Members
936 public bool Equals (AssemblyResource other)
938 return Name == other.Name;
945 // A placeholder class for assembly attributes when emitting module
947 class AssemblyAttributesPlaceholder : CompilerGeneratedClass
949 static readonly string TypeNamePrefix = "<$AssemblyAttributes${0}>";
950 public static readonly string AssemblyFieldName = "attributes";
954 public AssemblyAttributesPlaceholder (ModuleContainer parent, string outputName)
955 : base (parent, new MemberName (GetGeneratedName (outputName)), Modifiers.STATIC)
957 assembly = new Field (this, new TypeExpression (TypeManager.object_type, Location), Modifiers.PUBLIC | Modifiers.STATIC,
958 new MemberName (AssemblyFieldName), null);
963 public void AddAssemblyAttribute (MethodSpec ctor, byte[] data)
965 assembly.SetCustomAttribute (ctor, data);
968 public static string GetGeneratedName (string outputName)
970 return string.Format (TypeNamePrefix, outputName);
975 // Extension to System.Reflection.Emit.AssemblyBuilder to have fully compatible
976 // compiler. This is a default implementation for framework System.Reflection.Emit
977 // which does not implement any of the methods
979 class AssemblyBuilderExtension
981 readonly CompilerContext ctx;
983 public AssemblyBuilderExtension (CompilerContext ctx)
988 public virtual Module AddModule (string module)
990 ctx.Report.RuntimeMissingSupport (Location.Null, "-addmodule");
994 public virtual void AddPermissionRequests (PermissionSet[] permissions)
996 ctx.Report.RuntimeMissingSupport (Location.Null, "assembly declarative security");
999 public virtual void AddTypeForwarder (TypeSpec type, Location loc)
1001 ctx.Report.RuntimeMissingSupport (loc, "TypeForwardedToAttribute");
1004 public virtual void DefineWin32IconResource (string fileName)
1006 ctx.Report.RuntimeMissingSupport (Location.Null, "-win32icon");
1009 public virtual void SetAlgorithmId (uint value, Location loc)
1011 ctx.Report.RuntimeMissingSupport (loc, "AssemblyAlgorithmIdAttribute");
1014 public virtual void SetCulture (string culture, Location loc)
1016 ctx.Report.RuntimeMissingSupport (loc, "AssemblyCultureAttribute");
1019 public virtual void SetFlags (uint flags, Location loc)
1021 ctx.Report.RuntimeMissingSupport (loc, "AssemblyFlagsAttribute");
1024 public virtual void SetVersion (Version version, Location loc)
1026 ctx.Report.RuntimeMissingSupport (loc, "AssemblyVersionAttribute");
1029 public virtual void SetModuleTarget ()
1031 ctx.Report.RuntimeMissingSupport (Location.Null, "-target:module");