2007-08-27 Jb Evain <jbevain@novell.com>
[mono.git] / mcs / tools / linker / Mono.Linker / LinkContext.cs
1 //
2 // LinkContext.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2006 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System.Collections;
30 using System.IO;
31 using Mono.Cecil;
32
33 namespace Mono.Linker {
34
35         public class LinkContext {
36
37                 Pipeline _pipeline;
38                 AssemblyAction _coreAction;
39                 Hashtable _actions;
40                 string _outputDirectory;
41                 Hashtable _parameters;
42                 bool _linkSymbols;
43
44                 AssemblyResolver _resolver;
45
46                 public Pipeline Pipeline {
47                         get { return _pipeline; }
48                 }
49
50                 public string OutputDirectory {
51                         get { return _outputDirectory; }
52                         set { _outputDirectory = value; }
53                 }
54
55                 public AssemblyAction CoreAction {
56                         get { return _coreAction; }
57                         set { _coreAction = value; }
58                 }
59
60                 public bool LinkSymbols {
61                         get { return _linkSymbols; }
62                         set { _linkSymbols = value; }
63                 }
64
65                 public IDictionary Actions {
66                         get { return _actions; }
67                 }
68
69                 public AssemblyResolver Resolver {
70                         get { return _resolver; }
71                 }
72
73                 public LinkContext (Pipeline pipeline)
74                 {
75                         _pipeline = pipeline;
76                         _resolver = new AssemblyResolver ();
77                         _actions = new Hashtable ();
78                         _parameters = new Hashtable ();
79                 }
80
81                 public TypeDefinition GetType (string type)
82                 {
83                         int pos = type.IndexOf (",");
84                         type = type.Replace ("+", "/");
85                         if (pos == -1) {
86                                 foreach (AssemblyDefinition asm in GetAssemblies ())
87                                         if (asm.MainModule.Types.Contains (type))
88                                                 return asm.MainModule.Types [type];
89
90                                 return null;
91                         }
92
93                         string asmname = type.Substring (pos + 1);
94                         type = type.Substring (0, pos);
95                         AssemblyDefinition assembly = Resolve (AssemblyNameReference.Parse (asmname));
96                         return assembly.MainModule.Types [type];
97                 }
98
99                 public AssemblyDefinition Resolve (string name)
100                 {
101                         if (File.Exists (name)) {
102                                 AssemblyDefinition assembly = AssemblyFactory.GetAssembly (name);
103                                 _resolver.CacheAssembly (assembly);
104                                 SafeLoadSymbols (assembly);
105                                 return assembly;
106                         } else {
107                                 AssemblyNameReference reference = new AssemblyNameReference ();
108                                 reference.Name = name;
109                                 return Resolve (reference);
110                         }
111                 }
112
113                 public AssemblyDefinition Resolve (IMetadataScope scope)
114                 {
115                         AssemblyNameReference reference = GetReference (scope);
116
117                         AssemblyDefinition assembly = _resolver.Resolve (reference);
118
119                         if (SeenFirstTime (assembly)) {
120                                 SetAction (assembly);
121                                 SafeLoadSymbols (assembly);
122                         }
123
124                         return assembly;
125                 }
126
127                 static void SafeLoadSymbols (AssemblyDefinition assembly)
128                 {
129                         try {
130                                 assembly.MainModule.LoadSymbols ();
131                                 Annotations.SetHasSymbols (assembly);
132                         } catch {
133                                 return; // resharper loves this
134                         }
135                 }
136
137                 static bool SeenFirstTime (AssemblyDefinition assembly)
138                 {
139                         return !Annotations.HasAction (assembly);
140                 }
141
142                 static AssemblyNameReference GetReference (IMetadataScope scope)
143                 {
144                         AssemblyNameReference reference;
145                         if (scope is ModuleDefinition) {
146                                 AssemblyDefinition asm = ((ModuleDefinition) scope).Assembly;
147                                 reference = asm.Name;
148                         } else
149                                 reference = (AssemblyNameReference) scope;
150
151                         return reference;
152                 }
153
154                 void SetAction (AssemblyDefinition assembly)
155                 {
156                         AssemblyAction action = AssemblyAction.Link;
157
158                         AssemblyNameDefinition name = assembly.Name;
159
160                         if (_actions.Contains (name.Name))
161                                 action = (AssemblyAction) _actions [name.Name];
162                         else if (IsCore (name))
163                                 action = _coreAction;
164
165                         Annotations.SetAction (assembly, action);
166                 }
167
168                 static bool IsCore (AssemblyNameReference name)
169                 {
170                         return name.Name == "mscorlib"
171                                 || name.Name == "Accessibility"
172                                 || name.Name.StartsWith ("System")
173                                 || name.Name.StartsWith ("Microsoft");
174                 }
175
176                 public AssemblyDefinition [] GetAssemblies ()
177                 {
178                         IDictionary cache = _resolver.AssemblyCache;
179                         AssemblyDefinition [] asms = new AssemblyDefinition [cache.Count];
180                         cache.Values.CopyTo (asms, 0);
181                         return asms;
182                 }
183
184                 public void SetParameter (string key, string value)
185                 {
186                         _parameters [key] = value;
187                 }
188
189                 public bool HasParameter (string key)
190                 {
191                         return _parameters.Contains (key);
192                 }
193
194                 public string GetParameter (string key)
195                 {
196                         return (string) _parameters [key];
197                 }
198         }
199 }