5 // Jb Evain (jbevain@gmail.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
30 using System
.Collections
;
32 using SR
= System
.Reflection
;
33 using System
.Xml
.XPath
;
35 using Mono
.Linker
.Steps
;
37 namespace Mono
.Linker
{
41 static readonly string _linker
= "Mono CIL Linker";
43 public static int Main (string [] args
)
46 Usage ("No parameters specified");
50 Driver driver
= new Driver (args
);
53 } catch (Exception e
) {
54 Console
.WriteLine ("Fatal error in {0}", _linker
);
55 Console
.WriteLine (e
);
64 public Driver (string [] args
)
66 _queue
= new Queue (args
);
69 bool HaveMoreTokens ()
71 return _queue
.Count
> 0;
76 Pipeline p
= GetStandardPipeline ();
77 LinkContext context
= GetDefaultContext (p
);
78 I18nAssemblies assemblies
= I18nAssemblies
.All
;
79 ArrayList custom_steps
= new ArrayList ();
81 bool resolver
= false;
82 while (HaveMoreTokens ()) {
83 string token
= GetParam ();
85 Usage ("Option is too short");
87 if (! (token
[0] == '-' || token
[1] == '/'))
88 Usage ("Expecting an option, got instead: " + token
);
90 if (token
[0] == '-' && token
[1] == '-') {
93 Usage ("Option is too short");
110 DirectoryInfo info
= new DirectoryInfo (GetParam ());
111 context
.Resolver
.AddSearchDirectory (info
.FullName
);
115 context
.OutputDirectory
= GetParam ();
118 context
.CoreAction
= ParseAssemblyAction (GetParam ());
121 AssemblyAction action
= ParseAssemblyAction (GetParam ());
122 context
.Actions
[GetParam ()] = action
;
125 custom_steps
.Add (GetParam ());
128 foreach (string file
in GetFiles (GetParam ()))
129 p
.PrependStep (new ResolveFromXmlStep (new XPathDocument (file
)));
133 foreach (string file
in GetFiles (GetParam ()))
134 p
.PrependStep (new ResolveFromAssemblyStep (file
));
138 foreach (string file
in GetFiles (GetParam ()))
139 p
.PrependStep (new ResolveFromXApiStep (new XPathDocument (file
)));
143 assemblies
= ParseI18n (GetParam ());
146 context
.SetParameter (GetParam (), GetParam ());
149 context
.LinkSymbols
= bool.Parse (GetParam ());
152 if (!bool.Parse (GetParam ()))
153 p
.RemoveStep (typeof (RegenerateGuidStep
));
156 Usage ("Unknown option: `" + token
[1] + "'");
162 Usage ("No resolver was created (use -x, -a or -i)");
164 foreach (string custom_step
in custom_steps
)
165 AddCustomStep (p
, custom_step
);
167 p
.AddStepAfter (typeof (LoadReferencesStep
), new LoadI18nAssemblies (assemblies
));
172 static void AddCustomStep (Pipeline pipeline
, string arg
)
174 int pos
= arg
.IndexOf (":");
176 pipeline
.AppendStep (ResolveStep (arg
));
180 string [] parts
= arg
.Split (':');
181 if (parts
.Length
!= 2)
182 Usage ("Step is specified as TYPE:STEP");
184 if (parts
[0].IndexOf (",") > -1)
185 pipeline
.AddStepBefore (FindStep (pipeline
, parts
[1]), ResolveStep (parts
[0]));
186 else if (parts
[1].IndexOf (",") > -1)
187 pipeline
.AddStepAfter (FindStep (pipeline
, parts
[0]), ResolveStep (parts
[1]));
189 Usage ("No comma separator in TYPE or STEP");
192 static Type
FindStep (Pipeline pipeline
, string name
)
194 foreach (IStep step
in pipeline
.GetSteps ()) {
195 Type t
= step
.GetType ();
203 static IStep
ResolveStep (string type
)
205 Type step
= Type
.GetType (type
, false);
207 Usage (String
.Format ("Step type '{0}' not found.", type
));
208 if (!typeof (IStep
).IsAssignableFrom (step
))
209 Usage (String
.Format ("Step type '{0}' does not implement IStep interface.", type
));
210 return (IStep
) Activator
.CreateInstance (step
);
213 static string [] GetFiles (string param
)
215 if (param
.Length
< 1 || param
[0] != '@')
216 return new string [] {param}
;
218 string file
= param
.Substring (1);
219 return ReadLines (file
);
222 static string [] ReadLines (string file
)
224 ArrayList lines
= new ArrayList ();
225 using (StreamReader reader
= new StreamReader (file
)) {
227 while ((line
= reader
.ReadLine ()) != null)
230 return (string []) lines
.ToArray (typeof (string));
233 static I18nAssemblies
ParseI18n (string str
)
235 I18nAssemblies assemblies
= I18nAssemblies
.None
;
236 string [] parts
= str
.Split (',');
237 foreach (string part
in parts
)
238 assemblies
|= (I18nAssemblies
) Enum
.Parse (typeof (I18nAssemblies
), part
.Trim (), true);
243 static AssemblyAction
ParseAssemblyAction (string s
)
245 return (AssemblyAction
) Enum
.Parse (typeof (AssemblyAction
), s
, true);
250 if (_queue
.Count
== 0)
251 Usage ("Expecting a parameter");
253 return (string) _queue
.Dequeue ();
256 static LinkContext
GetDefaultContext (Pipeline pipeline
)
258 LinkContext context
= new LinkContext (pipeline
);
259 context
.CoreAction
= AssemblyAction
.Skip
;
260 context
.OutputDirectory
= "output";
264 static void Usage (string msg
)
266 Console
.WriteLine (_linker
);
268 Console
.WriteLine ("Error: " + msg
);
269 Console
.WriteLine ("monolinker [options] -x|-a|-i file");
271 Console
.WriteLine (" --about About the {0}", _linker
);
272 Console
.WriteLine (" --version Print the version number of the {0}", _linker
);
273 Console
.WriteLine (" -out Specify the output directory, default to `output'");
274 Console
.WriteLine (" -c Action on the core assemblies, skip, copy or link, default to skip");
275 Console
.WriteLine (" -p Action per assembly");
276 Console
.WriteLine (" -s Add a new step to the pipeline.");
277 Console
.WriteLine (" -d Add a directory where the linker will look for assemblies");
278 Console
.WriteLine (" -b Generate debug symbols for each linked module (true or false)");
279 Console
.WriteLine (" -g Generate a new unique guid for each linked module (true or false)");
280 Console
.WriteLine (" -l List of i18n assemblies to copy to the output directory");
281 Console
.WriteLine (" separated with a comma: none,all,cjk,mideast,other,rare,west");
282 Console
.WriteLine (" default is all");
283 Console
.WriteLine (" -x Link from an XML descriptor");
284 Console
.WriteLine (" -a Link from a list of assemblies");
285 Console
.WriteLine (" -i Link from an mono-api-info descriptor");
286 Console
.WriteLine ("");
288 Environment
.Exit (1);
291 static void Version ()
293 Console
.WriteLine ("{0} Version {1}",
295 System
.Reflection
.Assembly
.GetExecutingAssembly ().GetName ().Version
);
302 Console
.WriteLine ("For more information, visit the project Web site");
303 Console
.WriteLine (" http://www.mono-project.com/");
308 static Pipeline
GetStandardPipeline ()
310 Pipeline p
= new Pipeline ();
311 p
.AppendStep (new LoadReferencesStep ());
312 p
.AppendStep (new BlacklistStep ());
313 p
.AppendStep (new TypeMapStep ());
314 p
.AppendStep (new MarkStep ());
315 p
.AppendStep (new SweepStep ());
316 p
.AppendStep (new CleanStep ());
317 p
.AppendStep (new RegenerateGuidStep ());
318 p
.AppendStep (new OutputStep ());