X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fassembly.cs;h=a2af418af5726fac72840bcae2148e8108462998;hb=16317446d9b58e89362de5eb3e2a098d411aef00;hp=e19d00b3d3d60dd9ea4bf7bb82e54649f19b6fc4;hpb=3abe771dfe03091aa22521a9df3d4f09adc21737;p=mono.git diff --git a/mcs/mcs/assembly.cs b/mcs/mcs/assembly.cs index e19d00b3d3d..a2af418af57 100644 --- a/mcs/mcs/assembly.cs +++ b/mcs/mcs/assembly.cs @@ -6,7 +6,8 @@ // Marek Safar (marek.safar@gmail.com) // // Copyright 2001, 2002, 2003 Ximian, Inc. -// Copyright 2004 Novell, Inc. +// Copyright 2004-2011 Novell, Inc. +// Copyright 2011 Xamarin Inc // @@ -37,9 +38,11 @@ namespace Mono.CSharp string FullName { get; } bool HasExtensionMethod { get; } bool IsCLSCompliant { get; } + bool IsMissing { get; } string Name { get; } byte[] GetPublicKeyToken (); + bool IsFriendAssemblyTo (IAssemblyDefinition assembly); } public abstract class AssemblyDefinition : IAssemblyDefinition @@ -47,7 +50,7 @@ namespace Mono.CSharp // TODO: make it private and move all builder based methods here public AssemblyBuilder Builder; protected AssemblyBuilderExtension builder_extra; - MonoSymbolWriter symbol_writer; + MonoSymbolFile symbol_writer; bool is_cls_compliant; bool wrap_non_exception_throws; @@ -79,15 +82,15 @@ namespace Mono.CSharp wrap_non_exception_throws = true; - delay_sign = RootContext.StrongNameDelaySign; + delay_sign = Compiler.Settings.StrongNameDelaySign; // // Load strong name key early enough for assembly importer to be able to // use the keys for InternalsVisibleTo // This should go somewhere close to ReferencesLoading but don't have the place yet // - if (RootContext.StrongNameKeyFile != null || RootContext.StrongNameKeyContainer != null) { - LoadPublicKey (RootContext.StrongNameKeyFile, RootContext.StrongNameKeyContainer); + if (Compiler.Settings.HasKeyFileOrContainer) { + LoadPublicKey (Compiler.Settings.StrongNameKeyFile, Compiler.Settings.StrongNameKeyContainer); } } @@ -143,7 +146,7 @@ namespace Mono.CSharp // TODO: This should not exist here but will require more changes public MetadataImporter Importer { - get ; set; + get; set; } public bool IsCLSCompliant { @@ -152,6 +155,12 @@ namespace Mono.CSharp } } + bool IAssemblyDefinition.IsMissing { + get { + return false; + } + } + public string Name { get { return name; @@ -170,6 +179,12 @@ namespace Mono.CSharp } } + public MonoSymbolFile SymbolWriter { + get { + return symbol_writer; + } + } + #endregion public void AddModule (ImportedModuleDefinition module) @@ -192,7 +207,7 @@ namespace Mono.CSharp if (value == null || value.Length == 0) return; - if (RootContext.Target == Target.Exe) { + if (Compiler.Settings.Target == Target.Exe) { a.Error_AttributeEmitError ("The executables cannot be satelite assemblies, remove the attribute or keep it empty"); return; } @@ -200,7 +215,7 @@ namespace Mono.CSharp if (value == "neutral") value = ""; - if (RootContext.Target == Target.Module) { + if (Compiler.Settings.Target == Target.Module) { SetCustomAttribute (ctor, cdata); } else { builder_extra.SetCulture (value, a.Location); @@ -214,13 +229,13 @@ namespace Mono.CSharp if (value == null || value.Length == 0) return; - var vinfo = IsValidAssemblyVersion (value.Replace ('*', '0')); + var vinfo = IsValidAssemblyVersion (value, true); if (vinfo == null) { a.Error_AttributeEmitError (string.Format ("Specified version `{0}' is not valid", value)); return; } - if (RootContext.Target == Target.Module) { + if (Compiler.Settings.Target == Target.Module) { SetCustomAttribute (ctor, cdata); } else { builder_extra.SetVersion (vinfo, a.Location); @@ -236,7 +251,7 @@ namespace Mono.CSharp alg |= ((uint) cdata [pos + 2]) << 16; alg |= ((uint) cdata [pos + 3]) << 24; - if (RootContext.Target == Target.Module) { + if (Compiler.Settings.Target == Target.Module) { SetCustomAttribute (ctor, cdata); } else { builder_extra.SetAlgorithmId (alg, a.Location); @@ -256,7 +271,7 @@ namespace Mono.CSharp if ((flags & (uint) AssemblyNameFlags.PublicKey) != 0 && public_key == null) flags &= ~(uint) AssemblyNameFlags.PublicKey; - if (RootContext.Target == Target.Module) { + if (Compiler.Settings.Target == Target.Module) { SetCustomAttribute (ctor, cdata); } else { builder_extra.SetFlags (flags, a.Location); @@ -309,17 +324,16 @@ namespace Mono.CSharp string assembly_name = a.GetString (); if (assembly_name.Length == 0) return; - - AssemblyName aname = null; - try { - aname = new AssemblyName (assembly_name); - } catch (Exception) { +#if STATIC + ParsedAssemblyName aname; + ParseAssemblyResult r = Fusion.ParseAssemblyName (assembly_name, out aname); + if (r != ParseAssemblyResult.OK) { Report.Warning (1700, 3, a.Location, "Assembly reference `{0}' is invalid and cannot be resolved", assembly_name); return; } - if (aname.Version != null || aname.CultureInfo != null || aname.ProcessorArchitecture != ProcessorArchitecture.None) { + if (aname.Version != null || aname.Culture != null || aname.ProcessorArchitecture != ProcessorArchitecture.None) { Report.Error (1725, a.Location, "Friend assembly reference `{0}' is invalid. InternalsVisibleTo declarations cannot have a version, culture or processor architecture specified", assembly_name); @@ -327,17 +341,25 @@ namespace Mono.CSharp return; } - // TODO: GetPublicKey () does not work on .NET when AssemblyName is constructed from a string - if (public_key != null && aname.GetPublicKey () == null) { + if (public_key != null && !aname.HasPublicKey) { Report.Error (1726, a.Location, "Friend assembly reference `{0}' is invalid. Strong named assemblies must specify a public key in their InternalsVisibleTo declarations", assembly_name); return; } +#endif } else if (a.Type == pa.RuntimeCompatibility) { wrap_non_exception_throws_custom = true; + } else if (a.Type == pa.AssemblyFileVersion) { + string value = a.GetString (); + if (string.IsNullOrEmpty (value) || IsValidAssemblyVersion (value, false) == null) { + Report.Warning (1607, 1, a.Location, "The version number `{0}' specified for `{1}' is invalid", + value, a.Name); + return; + } } + SetCustomAttribute (ctor, cdata); } @@ -350,12 +372,22 @@ namespace Mono.CSharp { // TODO: It should check only references assemblies but there is // no working SRE API - foreach (var a in Importer.Assemblies) { + foreach (var entry in Importer.Assemblies) { + var a = entry as ImportedAssemblyDefinition; + if (a == null) + continue; + if (public_key != null && !a.HasStrongName) { Report.Error (1577, "Referenced assembly `{0}' does not have a strong name", a.FullName); } + var ci = a.Assembly.GetName ().CultureInfo; + if (!ci.Equals (System.Globalization.CultureInfo.InvariantCulture)) { + Report.Warning (1607, 1, "Referenced assembly `{0}' has different culture setting of `{1}'", + a.Name, ci.Name); + } + if (!a.IsFriendAssemblyTo (this)) continue; @@ -365,6 +397,7 @@ namespace Mono.CSharp if (ArrayComparer.IsEqual (GetPublicKeyToken (), atoken)) continue; + Report.SymbolRelatedToPreviousError (a.Location); Report.Error (281, "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", attr.FullName, FullName); @@ -375,7 +408,7 @@ namespace Mono.CSharp { var an = new AssemblyName (name); - if (public_key != null && RootContext.Target != Target.Module) { + if (public_key != null && Compiler.Settings.Target != Target.Module) { if (delay_sign) { an.SetPublicKey (public_key); } else { @@ -406,27 +439,23 @@ namespace Mono.CSharp return Builder.DefineDynamicModule (module_name, module_name, false); } - public void Emit () + public virtual void Emit () { - if (RootContext.Target == Target.Module) { + if (Compiler.Settings.Target == Target.Module) { module_target_attrs = new AssemblyAttributesPlaceholder (module, name); - module_target_attrs.CreateType (); - module_target_attrs.DefineType (); + module_target_attrs.CreateContainer (); + module_target_attrs.DefineContainer (); module_target_attrs.Define (); module.AddCompilerGeneratedClass (module_target_attrs); } else if (added_modules != null) { ReadModulesAssemblyAttributes (); } - if (RootContext.GenerateDebugInfo) { - symbol_writer = new MonoSymbolWriter (file_name); - - // TODO: global variables - Location.DefineSymbolDocuments (symbol_writer); - SymbolWriter.symwriter = symbol_writer; + if (Compiler.Settings.GenerateDebugInfo) { + symbol_writer = new MonoSymbolFile (); } - module.Emit (); + module.EmitContainer (); if (module.HasExtensionMethod) { var pa = module.PredefinedAttributes.Extension; @@ -438,10 +467,10 @@ namespace Mono.CSharp if (!wrap_non_exception_throws_custom) { PredefinedAttribute pa = module.PredefinedAttributes.RuntimeCompatibility; if (pa.IsDefined && pa.ResolveBuilder ()) { - var prop = pa.GetProperty ("WrapNonExceptionThrows", TypeManager.bool_type, Location.Null); + var prop = module.PredefinedMembers.RuntimeCompatibilityWrapNonExceptionThrows.Get (); if (prop != null) { - AttributeEncoder encoder = new AttributeEncoder (false); - encoder.EncodeNamedPropertyArgument (prop, new BoolLiteral (true, Location.Null)); + AttributeEncoder encoder = new AttributeEncoder (); + encoder.EncodeNamedPropertyArgument (prop, new BoolLiteral (Compiler.BuiltinTypes, true, Location.Null)); SetCustomAttribute (pa.Constructor, encoder.ToArray ()); } } @@ -453,11 +482,7 @@ namespace Mono.CSharp Builder.__AddDeclarativeSecurity (entry); } #else - var args = new PermissionSet[3]; - declarative_security.TryGetValue (SecurityAction.RequestMinimum, out args[0]); - declarative_security.TryGetValue (SecurityAction.RequestOptional, out args[1]); - declarative_security.TryGetValue (SecurityAction.RequestRefuse, out args[2]); - builder_extra.AddPermissionRequests (args); + throw new NotSupportedException ("Assembly-level security"); #endif } @@ -475,7 +500,7 @@ namespace Mono.CSharp byte[] hash = ha.ComputeHash (public_key); // we need the last 8 bytes in reverse order public_key_token = new byte[8]; - Array.Copy (hash, (hash.Length - 8), public_key_token, 0, 8); + Buffer.BlockCopy (hash, hash.Length - 8, public_key_token, 0, 8); Array.Reverse (public_key_token, 0, 8); return public_key_token; } @@ -502,7 +527,7 @@ namespace Mono.CSharp // For attribute based KeyFile do additional lookup // in output assembly path // - if (!key_file_exists && RootContext.StrongNameKeyFile == null) { + if (!key_file_exists && Compiler.Settings.StrongNameKeyFile == null) { // // The key file can be relative to output assembly // @@ -534,11 +559,19 @@ namespace Mono.CSharp byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa); // AssemblyName.SetPublicKey requires an additional header - byte[] publicKeyHeader = new byte[12] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00 }; + byte[] publicKeyHeader = new byte[8] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00 }; // Encode public key public_key = new byte[12 + publickey.Length]; - Buffer.BlockCopy (publicKeyHeader, 0, public_key, 0, 12); + Buffer.BlockCopy (publicKeyHeader, 0, public_key, 0, publicKeyHeader.Length); + + // Length of Public Key (in bytes) + int lastPart = public_key.Length - 12; + public_key[8] = (byte) (lastPart & 0xFF); + public_key[9] = (byte) ((lastPart >> 8) & 0xFF); + public_key[10] = (byte) ((lastPart >> 16) & 0xFF); + public_key[11] = (byte) ((lastPart >> 24) & 0xFF); + Buffer.BlockCopy (publickey, 0, public_key, 12, publickey.Length); } catch { Error_AssemblySigning ("The specified key file `" + keyFile + "' has incorrect format"); @@ -569,24 +602,25 @@ namespace Mono.CSharp public void Resolve () { - if (RootContext.Unsafe) { + if (Compiler.Settings.Unsafe && module.PredefinedTypes.SecurityAction.Define ()) { // // Emits [assembly: SecurityPermissionAttribute (SecurityAction.RequestMinimum, SkipVerification = true)] // when -unsafe option was specified // - Location loc = Location.Null; MemberAccess system_security_permissions = new MemberAccess (new MemberAccess ( new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Security", loc), "Permissions", loc); + var req_min = module.PredefinedMembers.SecurityActionRequestMinimum.Resolve (loc); + Arguments pos = new Arguments (1); - pos.Add (new Argument (new MemberAccess (new MemberAccess (system_security_permissions, "SecurityAction", loc), "RequestMinimum"))); + pos.Add (new Argument (req_min.GetConstant (null))); Arguments named = new Arguments (1); - named.Add (new NamedArgument ("SkipVerification", loc, new BoolLiteral (true, loc))); + named.Add (new NamedArgument ("SkipVerification", loc, new BoolLiteral (Compiler.BuiltinTypes, true, loc))); - GlobalAttribute g = new GlobalAttribute (new NamespaceEntry (module, null, null, null), "assembly", + Attribute g = new Attribute ("assembly", new MemberAccess (system_security_permissions, "SecurityPermissionAttribute"), new Arguments[] { pos, named }, loc, false); g.AttachTo (module, module); @@ -609,7 +643,7 @@ namespace Mono.CSharp is_cls_compliant = cls_attribute.GetClsCompliantAttributeValue (); } - if (added_modules != null && RootContext.VerifyClsCompliance && is_cls_compliant) { + if (added_modules != null && Compiler.Settings.VerifyClsCompliance && is_cls_compliant) { foreach (var m in added_modules) { if (!m.IsCLSCompliant) { Report.Error (3013, @@ -646,7 +680,7 @@ namespace Mono.CSharp case "AssemblyKeyFile": case "AssemblyKeyFileAttribute": case "System.Reflection.AssemblyKeyFileAttribute": - if (RootContext.StrongNameKeyFile != null) { + if (Compiler.Settings.StrongNameKeyFile != null) { Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ()); Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module", "keyfile", "System.Reflection.AssemblyKeyFileAttribute"); @@ -661,7 +695,7 @@ namespace Mono.CSharp case "AssemblyKeyName": case "AssemblyKeyNameAttribute": case "System.Reflection.AssemblyKeyNameAttribute": - if (RootContext.StrongNameKeyContainer != null) { + if (Compiler.Settings.StrongNameKeyContainer != null) { Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ()); Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module", "keycontainer", "System.Reflection.AssemblyKeyNameAttribute"); @@ -707,28 +741,38 @@ namespace Mono.CSharp // // Add Win32 resources // - if (RootContext.Win32ResourceFile != null) { - Builder.DefineUnmanagedResource (RootContext.Win32ResourceFile); + if (Compiler.Settings.Win32ResourceFile != null) { + Builder.DefineUnmanagedResource (Compiler.Settings.Win32ResourceFile); } else { Builder.DefineVersionInfoResource (); } - if (RootContext.Win32IconFile != null) { - builder_extra.DefineWin32IconResource (RootContext.Win32IconFile); + if (Compiler.Settings.Win32IconFile != null) { + builder_extra.DefineWin32IconResource (Compiler.Settings.Win32IconFile); } - if (RootContext.Resources != null) { - if (RootContext.Target == Target.Module) { + if (Compiler.Settings.Resources != null) { + if (Compiler.Settings.Target == Target.Module) { Report.Error (1507, "Cannot link resource file when building a module"); } else { - foreach (var res in RootContext.Resources) { + int counter = 0; + foreach (var res in Compiler.Settings.Resources) { if (!File.Exists (res.FileName)) { Report.Error (1566, "Error reading resource file `{0}'", res.FileName); continue; } if (res.IsEmbeded) { - var stream = File.OpenRead (res.FileName); + Stream stream; + if (counter++ < 10) { + stream = File.OpenRead (res.FileName); + } else { + // TODO: SRE API requires resource stream to be available during AssemblyBuilder::Save + // we workaround it by reading everything into memory to compile projects with + // many embedded resource (over 3500) references + stream = new MemoryStream (File.ReadAllBytes (res.FileName)); + } + module.Builder.DefineManifestResource (res.Name, stream, res.Attributes); } else { Builder.AddResourceFile (res.Name, Path.GetFileName (res.FileName), res.Attributes); @@ -740,31 +784,45 @@ namespace Mono.CSharp public void Save () { - PortableExecutableKinds pekind; + PortableExecutableKinds pekind = PortableExecutableKinds.ILOnly; ImageFileMachine machine; - switch (RootContext.Platform) { + switch (Compiler.Settings.Platform) { case Platform.X86: - pekind = PortableExecutableKinds.Required32Bit | PortableExecutableKinds.ILOnly; + pekind |= PortableExecutableKinds.Required32Bit; machine = ImageFileMachine.I386; break; case Platform.X64: - pekind = PortableExecutableKinds.ILOnly; + pekind |= PortableExecutableKinds.PE32Plus; machine = ImageFileMachine.AMD64; break; case Platform.IA64: - pekind = PortableExecutableKinds.ILOnly; machine = ImageFileMachine.IA64; break; + case Platform.AnyCPU32Preferred: +#if STATIC + pekind |= PortableExecutableKinds.Preferred32Bit; + machine = ImageFileMachine.I386; + break; +#else + throw new NotSupportedException (); +#endif + case Platform.Arm: +#if STATIC + machine = ImageFileMachine.ARM; + break; +#else + throw new NotSupportedException (); +#endif case Platform.AnyCPU: default: - pekind = PortableExecutableKinds.ILOnly; machine = ImageFileMachine.I386; break; } + Compiler.TimeReporter.Start (TimeReporter.TimerType.OutputSave); try { - if (RootContext.Target == Target.Module) { + if (Compiler.Settings.Target == Target.Module) { SaveModule (pekind, machine); } else { Builder.Save (module.Builder.ScopeName, pekind, machine); @@ -772,11 +830,28 @@ namespace Mono.CSharp } catch (Exception e) { Report.Error (16, "Could not write to file `" + name + "', cause: " + e.Message); } + Compiler.TimeReporter.Stop (TimeReporter.TimerType.OutputSave); // Save debug symbols file - if (symbol_writer != null) { + if (symbol_writer != null && Compiler.Report.Errors == 0) { // TODO: it should run in parallel - symbol_writer.WriteSymbolFile (SymbolWriter.GetGuid (module.Builder)); + Compiler.TimeReporter.Start (TimeReporter.TimerType.DebugSave); + + var filename = file_name + ".mdb"; + try { + // We mmap the file, so unlink the previous version since it may be in use + File.Delete (filename); + } catch { + // We can safely ignore + } + + module.WriteDebugSymbol (symbol_writer); + + using (FileStream fs = new FileStream (filename, FileMode.Create, FileAccess.Write)) { + symbol_writer.CreateSymbolFile (module.Builder.ModuleVersionId, fs); + } + + Compiler.TimeReporter.Stop (TimeReporter.TimerType.DebugSave); } } @@ -795,8 +870,8 @@ namespace Mono.CSharp void SetEntryPoint () { - if (!RootContext.NeedsEntryPoint) { - if (RootContext.MainClass != null) + if (!Compiler.Settings.NeedsEntryPoint) { + if (Compiler.Settings.MainClass != null) Report.Error (2017, "Cannot specify -main if building a module or library"); return; @@ -804,7 +879,7 @@ namespace Mono.CSharp PEFileKinds file_kind; - switch (RootContext.Target) { + switch (Compiler.Settings.Target) { case Target.Library: case Target.Module: file_kind = PEFileKinds.Dll; @@ -818,26 +893,24 @@ namespace Mono.CSharp } if (entry_point == null) { - if (RootContext.MainClass != null) { - // TODO: Should use MemberCache - DeclSpace main_cont = module.GetDefinition (RootContext.MainClass) as DeclSpace; - if (main_cont == null) { - Report.Error (1555, "Could not find `{0}' specified for Main method", RootContext.MainClass); + string main_class = Compiler.Settings.MainClass; + if (main_class != null) { + // TODO: Handle dotted names + var texpr = module.GlobalRootNamespace.LookupType (module, main_class, 0, LookupMode.Probing, Location.Null); + if (texpr == null) { + Report.Error (1555, "Could not find `{0}' specified for Main method", main_class); return; } - if (!(main_cont is ClassOrStruct)) { - Report.Error (1556, "`{0}' specified for Main method must be a valid class or struct", RootContext.MainClass); + var mtype = texpr.Type.MemberDefinition as ClassOrStruct; + if (mtype == null) { + Report.Error (1556, "`{0}' specified for Main method must be a valid class or struct", main_class); return; } - Report.Error (1558, main_cont.Location, "`{0}' does not have a suitable static Main method", main_cont.GetSignatureForError ()); - return; - } - - if (Report.Errors == 0) { + Report.Error (1558, mtype.Location, "`{0}' does not have a suitable static Main method", mtype.GetSignatureForError ()); + } else { string pname = file_name == null ? name : Path.GetFileName (file_name); - Report.Error (5001, "Program `{0}' does not contain a static `Main' method suitable for an entry point", pname); } @@ -860,26 +933,48 @@ namespace Mono.CSharp Report.Error (1548, "Error during assembly signing. " + text); } - static Version IsValidAssemblyVersion (string version) + public bool IsFriendAssemblyTo (IAssemblyDefinition assembly) { - Version v; - try { - v = new Version (version); - } catch { - try { - int major = int.Parse (version, CultureInfo.InvariantCulture); - v = new Version (major, 0); - } catch { + return false; + } + + static Version IsValidAssemblyVersion (string version, bool allowGenerated) + { + string[] parts = version.Split ('.'); + if (parts.Length < 1 || parts.Length > 4) + return null; + + var values = new int[4]; + for (int i = 0; i < parts.Length; ++i) { + if (!int.TryParse (parts[i], out values[i])) { + if (parts[i].Length == 1 && parts[i][0] == '*' && allowGenerated) { + if (i == 2) { + // Nothing can follow * + if (parts.Length > 3) + return null; + + // Generate Build value based on days since 1/1/2000 + TimeSpan days = DateTime.Today - new DateTime (2000, 1, 1); + values[i] = System.Math.Max (days.Days, 0); + i = 3; + } + + if (i == 3) { + // Generate Revision value based on every other second today + var seconds = DateTime.Now - DateTime.Today; + values[i] = (int) seconds.TotalSeconds / 2; + continue; + } + } + return null; } - } - foreach (int candidate in new int [] { v.Major, v.Minor, v.Build, v.Revision }) { - if (candidate > ushort.MaxValue) + if (values[i] > ushort.MaxValue) return null; } - return new Version (v.Major, System.Math.Max (0, v.Minor), System.Math.Max (0, v.Build), System.Math.Max (0, v.Revision)); + return new Version (values[0], values[1], values[2], values[3]); } } @@ -925,7 +1020,7 @@ namespace Mono.CSharp public AssemblyAttributesPlaceholder (ModuleContainer parent, string outputName) : base (parent, new MemberName (GetGeneratedName (outputName)), Modifiers.STATIC) { - assembly = new Field (this, new TypeExpression (TypeManager.object_type, Location), Modifiers.PUBLIC | Modifiers.STATIC, + assembly = new Field (this, new TypeExpression (parent.Compiler.BuiltinTypes.Object, Location), Modifiers.PUBLIC | Modifiers.STATIC, new MemberName (AssemblyFieldName), null); AddField (assembly); @@ -1003,28 +1098,19 @@ namespace Mono.CSharp protected readonly CompilerContext compiler; protected readonly List paths; - readonly string[] default_references; public AssemblyReferencesLoader (CompilerContext compiler) { this.compiler = compiler; - if (RootContext.LoadDefaultReferences) - default_references = GetDefaultReferences (); - else - default_references = new string[0]; - paths = new List (); - paths.AddRange (RootContext.ReferencesLookupPaths); - paths.Add (GetSystemDir ()); + paths.AddRange (compiler.Settings.ReferencesLookupPaths); paths.Add (Directory.GetCurrentDirectory ()); - // TODO: should remove redundant paths } public abstract bool HasObjectType (T assembly); protected abstract string[] GetDefaultReferences (); - public abstract T LoadAssemblyFile (string fileName); - public abstract T LoadAssemblyDefault (string assembly); + public abstract T LoadAssemblyFile (string fileName, bool isImplicitReference); public abstract void LoadReferences (ModuleContainer module); protected void Error_FileNotFound (string fileName) @@ -1051,36 +1137,24 @@ namespace Mono.CSharp fileName); } - // - // Returns the directory where the system assemblies are installed - // - static string GetSystemDir () - { - return Path.GetDirectoryName (typeof (object).Assembly.Location); - } - protected void LoadReferencesCore (ModuleContainer module, out T corlib_assembly, out List> loaded) { + compiler.TimeReporter.Start (TimeReporter.TimerType.ReferencesLoading); + loaded = new List> (); // // Load mscorlib.dll as the first // - if (RootContext.StdLib) { - corlib_assembly = LoadAssemblyDefault ("mscorlib.dll"); + if (module.Compiler.Settings.StdLib) { + corlib_assembly = LoadAssemblyFile ("mscorlib.dll", true); } else { corlib_assembly = default (T); } T a; - foreach (string r in default_references) { - a = LoadAssemblyDefault (r); - if (a != null) - loaded.Add (Tuple.Create (module.GlobalRootNamespace, a)); - } - - foreach (string r in RootContext.AssemblyReferences) { - a = LoadAssemblyFile (r); + foreach (string r in module.Compiler.Settings.AssemblyReferences) { + a = LoadAssemblyFile (r, false); if (a == null || EqualityComparer.Default.Equals (a, corlib_assembly)) continue; @@ -1097,8 +1171,8 @@ namespace Mono.CSharp loaded.Add (key); } - foreach (var entry in RootContext.AssemblyReferencesAliases) { - a = LoadAssemblyFile (entry.Item2); + foreach (var entry in module.Compiler.Settings.AssemblyReferencesAliases) { + a = LoadAssemblyFile (entry.Item2, false); if (a == null) continue; @@ -1108,6 +1182,22 @@ namespace Mono.CSharp loaded.Add (key); } + + if (compiler.Settings.LoadDefaultReferences) { + foreach (string r in GetDefaultReferences ()) { + a = LoadAssemblyFile (r, true); + if (a == null) + continue; + + var key = Tuple.Create (module.GlobalRootNamespace, a); + if (loaded.Contains (key)) + continue; + + loaded.Add (key); + } + } + + compiler.TimeReporter.Stop (TimeReporter.TimerType.ReferencesLoading); } } }