Remove Mono.GetOptions
[mono.git] / mcs / class / Mono.GetOptions / Mono.GetOptions.Useful / CommonCompilerOptions.cs
1 //
2 // CommonCompilerOptions.cs
3 //
4 // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
5 //
6 // (C) 2005 Rafael Teixeira
7 //
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;
30 using System.Collections;
31 using System.IO;
32 using System.Diagnostics;
33 using System.Reflection;
34 using System.Reflection.Emit;
35 using System.Text;
36
37 namespace Mono.GetOptions.Useful
38 {
39
40         public enum TargetType {
41                 Library, Exe, Module, WinExe
42         };
43         
44         public struct FileToCompile {
45                 public string Filename;
46                 public Encoding Encoding;
47                 
48                 public FileToCompile(string filename, Encoding encoding)
49                 {
50                         this.Filename = filename;
51                         this.Encoding = encoding;       
52                 }
53         }
54
55         public enum InternalCompilerErrorReportAction { 
56                 prompt, send, none 
57         }
58                 
59         public delegate void ModuleAdder (System.Reflection.Module module);
60         public delegate void AssemblyAdder (Assembly loadedAssembly);
61         
62         public class CommonCompilerOptions : Options {
63         
64                 public CommonCompilerOptions() : this(null, null) { }
65
66                 public CommonCompilerOptions(string[] args) : this(args, null) {}
67
68                 public CommonCompilerOptions(string[] args, ErrorReporter reportError) : base(args, OptionsParsingMode.Both, false, true, true, reportError) 
69                 {
70                         PathsToSearchForLibraries.Add (Directory.GetCurrentDirectory ());
71                 }
72                 
73                 [Option(-1, "References packages listed. {packagelist}=package,...", "pkg")]
74                 public WhatToDoNext ReferenceSomePackage(string packageName)
75                 {
76                         return ReferencePackage(packageName)?WhatToDoNext.GoAhead:WhatToDoNext.AbandonProgram;
77                 }
78
79                 private Encoding currentEncoding = null;
80                 
81                 [Option(-1, "Select codepage by {ID} (number, 'utf8' or 'reset') to process following source files", "codepage")]
82                 public string CurrentCodepage {
83                         set {
84                                 switch (value.ToLower()) {
85                                         case "reset": 
86                                                 currentEncoding = null; 
87                                                 break;
88                                         case "utf8": case "utf-8":
89                                                 currentEncoding = Encoding.UTF8;
90                                                 break;
91                                         default:
92                                                 try {
93                                                         currentEncoding = Encoding.GetEncoding(int.Parse(value));
94                                                 } catch (NotSupportedException) {
95                                                         ReportError (0, string.Format("Ignoring unsupported codepage number {0}.", value));
96                                                 } catch (Exception) {
97                                                         ReportError (0, string.Format("Ignoring unsupported codepage ID {0}.", value));
98                                                 }
99                                                 break;
100                                 }                                       
101                         }
102                 }
103                 
104                 private ArrayList warningsToIgnore = new ArrayList();
105                 public int[] WarningsToIgnore { get { return (int[])warningsToIgnore.ToArray(typeof(int)); } }
106                 
107                 [Option(-1, "Ignores warning number {XXXX}", "ignorewarn", SecondLevelHelp = true)]
108                 public WhatToDoNext SetIgnoreWarning(int warningNumber)
109                 {
110                         warningsToIgnore.Add(warningNumber);
111                         return WhatToDoNext.GoAhead;
112                 }       
113                 
114                 [Option("Sets warning {level} (the highest is 4, the default)", "wlevel", SecondLevelHelp = true)]
115                 public int WarningLevel = 4; 
116
117                 // Output file options
118                 //------------------------------------------------------------------
119                 public TargetType TargetFileType = TargetType.Exe;
120
121                 string outputFileName = null;
122                 string firstSourceFile = null;
123                 string targetFileExtension = ".exe";
124
125                 [Option("Specifies the output {file} name", 'o', "out")]
126                 public string OutputFileName 
127                 {
128                         set { outputFileName = value; }
129                         get 
130                         {
131                                 if (outputFileName == null) {
132                                         int pos = firstSourceFile.LastIndexOf(".");
133
134                                         if (pos > 0)
135                                                 outputFileName = firstSourceFile.Substring(0, pos);
136                                         else
137                                                 outputFileName = firstSourceFile;
138 // TODO: what Codegen does here to get hid of this dependency
139 //                                      string bname = CodeGen.Basename(outputFileName);
140 //                                      if (bname.IndexOf(".") == -1)
141                                                 outputFileName +=  targetFileExtension;
142                                 }
143                                 return outputFileName;
144                         }
145                 }
146
147
148                 [Option("Specifies the target {type} for the output file (exe [default], winexe, library, module)", 't', "target")]
149                 public WhatToDoNext SetTarget(string type)
150                 {
151                         switch (type.ToLower()) {
152                                 case "library":
153                                         TargetFileType = TargetType.Library;
154                                         targetFileExtension = ".dll";
155                                         break;
156                                                         
157                                 case "exe":
158                                         TargetFileType = TargetType.Exe;
159                                         targetFileExtension = ".exe";
160                                         break;
161                                                         
162                                 case "winexe":
163                                         TargetFileType = TargetType.WinExe;
164                                         targetFileExtension = ".exe";
165                                         break;
166                                                         
167                                 case "module":
168                                         TargetFileType = TargetType.Module;
169                                         targetFileExtension = ".netmodule";
170                                         break;
171                         }
172                         return WhatToDoNext.GoAhead;
173                 }
174
175                 [Option("Specifies the {name} of the Class or Module that contains Sub Main \tor inherits from System.Windows.Forms.Form.\tNeeded to select among many entry-points for a program (target=exe|winexe)",
176                         'm', "main")]
177                 public string MainClassName = null; 
178
179                 // TODO: force option to accept number in hex format
180 //              [Option("[NOT IMPLEMENTED YET]The base {address} for a library or module (hex)", SecondLevelHelp = true)]
181                 public int baseaddress;
182
183                 // input file options
184                 //------------------------------------------------------------------
185                 [Option(-1, "Imports all type information from files in the module-list. {module-list}:module,...", "addmodule")]
186                 public string AddedModule { set { foreach(string module in value.Split(',')) NetModulesToAdd.Add(module); } }
187
188 //              [Option("[NOT IMPLEMENTED YET]Include all files in the current directory and subdirectories according to the {wildcard}", "recurse")]
189                 public WhatToDoNext Recurse(string wildcard)
190                 {
191                         //AddFiles (DirName, true); // TODO wrong semantics
192                         return WhatToDoNext.GoAhead;
193                 }
194
195                 [Option(-1, "References metadata from the specified assembly-list. {assembly-list}:assembly,...", 'r', "reference")]
196                 public string AddedReference { set { foreach (string assembly in value.Split(',')) AssembliesToReference.Add(assembly); } }
197                 
198                 [Option("List of directories to search for referenced assemblies. \t{path-list}:path,...", "libpath", "lib")]
199                 public string AddedLibPath { set { foreach(string path in value.Split(',')) PathsToSearchForLibraries.Add(path); } }
200
201                 // support for the Compact Framework
202                 //------------------------------------------------------------------
203 //              [Option("[NOT IMPLEMENTED YET]Sets the compiler to TargetFileType the Compact Framework", "netcf")]
204                 public bool CompileForCompactFramework = false;
205                 
206 //              [Option("[NOT IMPLEMENTED YET]Specifies the {path} to the location of mscorlib.dll and microsoft.visualbasic.dll", "sdkpath")]
207                 public string SDKPath = null;
208
209                 // resource options
210                 //------------------------------------------------------------------
211                 public ArrayList EmbeddedResources = new ArrayList();
212                 
213                 //TODO: support -res:file[,id[,public|private]] what depends on changes at Mono.GetOptions
214                 [Option(-1, "Adds the specified file as an embedded assembly resource. \t{details}:file[,id[,public|private]]", "resource", "res")]
215                 public string AddedResource { set { EmbeddedResources.Add(value); } }
216
217                 public ArrayList LinkedResources = new ArrayList();
218                 
219                 [Option(-1, "Adds the specified file as a linked assembly resource. \t{details}:file[,id[,public|private]]", "linkresource", "linkres")]
220                 public string AddedLinkresource { set { LinkedResources.Add(value); } }
221
222                 public ArrayList Win32Resources = new ArrayList();
223                 
224 //              [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 resource {file} (.res)", "win32resource")]
225                 public string AddedWin32resource { set { Win32Resources.Add(value); } }
226
227                 public ArrayList Win32Icons = new ArrayList();
228                 
229 //              [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 icon {file} (.ico) for the default Win32 resources", "win32icon")]
230                 public string AddedWin32icon { set { Win32Icons.Add(value); } }
231
232                 // code generation options
233                 //------------------------------------------------------------------
234
235 //              [Option("[NOT IMPLEMENTED YET]Enable optimizations", "optimize", VBCStyleBoolean = true)]
236                 public bool Optimize = false;
237
238                 public bool CheckedContext = true;
239                 
240                 [Option("Remove integer checks. Default off.", SecondLevelHelp = true, VBCStyleBoolean = true)]
241                 public virtual bool removeintchecks { set { CheckedContext = !value; } }
242
243                 [Option("Emit full debugging information", 'g', "debug", VBCStyleBoolean = true)]
244                 public bool WantDebuggingSupport = false;
245
246                 [Option("Emit full debugging information (default)", "debug:full", SecondLevelHelp = true)]
247                 public bool debugfull { 
248                         set { 
249                                 WantDebuggingSupport = value; 
250                                 FullDebugging = value; 
251                                 MdbOnly = !value; 
252                         }
253                 }
254                 
255                 [Option("Emit MDB file only", "debug:pdbonly", SecondLevelHelp = true)]
256                 public bool debugpdbonly {
257                         set { 
258                                 WantDebuggingSupport = value; 
259                                 FullDebugging = !value; 
260                                 MdbOnly = value; 
261                         }
262                 }
263         
264                 public bool MdbOnly = false;
265                 public bool FullDebugging = true;
266
267
268                 // errors and warnings options
269                 //------------------------------------------------------------------
270
271                 [Option("Treat warnings as errors", "warnaserror", SecondLevelHelp = true)]
272                 public bool WarningsAreErrors = false; 
273
274                 [Option("Disable warnings", "nowarn", SecondLevelHelp = true)]
275                 public bool NoWarnings { set { if (value) WarningLevel = 0; } }
276
277
278                 // Defines
279                 //------------------------------------------------------------------
280                 public Hashtable Defines = new Hashtable();
281                 
282                 [Option(-1, "Declares global conditional compilation symbol(s). {symbol-list}:name=value,...", 'd', "define")]
283                 public string DefineSymbol { 
284                         set {
285                                 foreach(string item in value.Split(','))  {
286                                         string[] dados = item.Split('=');
287                                         if (dados.Length > 1)
288                                                 Defines.Add(dados[0], dados[1]); 
289                                         else
290                                                 Defines.Add(dados[0], "true");
291                                 }
292                         } 
293                 }
294                 
295                 [Option("Don\'t assume the standard library", "nostdlib", SecondLevelHelp = true)]
296                 public bool NoStandardLibraries = false;
297
298                 [Option("Disables implicit references to assemblies", "noconfig", SecondLevelHelp = true)]
299                 public bool NoConfig = false;
300                 
301                 [Option("Allows unsafe code", "unsafe", SecondLevelHelp = true)]
302                 public bool AllowUnsafeCode = false;
303
304                 [Option("Debugger {arguments}", "debug-args", SecondLevelHelp = true)]
305                 public WhatToDoNext SetDebugArgs(string args)
306                 {
307                         DebugListOfArguments.AddRange(args.Split(','));
308                         return WhatToDoNext.GoAhead;
309                 }
310
311                 public ArrayList Imports = new ArrayList();
312                 
313                 [Option(-1, "Declare global Imports for listed namespaces. {import-list}:namespace,...", "imports")]
314                 public string ImportNamespaces
315                 {
316                         set {
317                                 foreach(string importedNamespace in value.Split(','))
318                                         Imports.Add(importedNamespace);
319                         }
320                 }
321
322                 [Option("Specifies the root {namespace} for all type declarations", "rootnamespace",  SecondLevelHelp = true)]
323                 public string RootNamespace = null;
324                 
325                 // Signing options      
326                 //------------------------------------------------------------------
327 //              [Option("[NOT IMPLEMENTED YET]Delay-sign the assembly using only the public portion of the strong name key", VBCStyleBoolean = true)]
328                 public bool delaysign;
329                 
330 //              [Option("[NOT IMPLEMENTED YET]Specifies a strong name key {container}")]
331                 public string keycontainer;
332                 
333 //              [Option("[NOT IMPLEMENTED YET]Specifies a strong name key {file}")]
334                 public string keyfile;
335
336                 // Compiler output options      
337                 //------------------------------------------------------------------
338                 
339                 [Option("Do not display compiler copyright banner", "nologo")]
340                 public bool DontShowBanner = false;
341                 
342                 //TODO: Correct semantics
343                 [Option("Commands the compiler to show only error messages for syntax-related errors and warnings", 'q', "quiet", SecondLevelHelp = true)]
344                 public bool SuccintErrorDisplay = false;
345                 
346                 [Option("Display verbose messages", 'v', "verbose",  SecondLevelHelp = true)] 
347                 public bool Verbose = false;
348                 
349                 [Option("[IGNORED] Emit compiler output in UTF8 character encoding", "utf8output", SecondLevelHelp = true, VBCStyleBoolean = true)]
350                 public bool OutputInUTF8;
351
352 //              [Option("[NOT IMPLEMENTED YET]Create bug report {file}", "bugreport")]
353                 public string CreateBugReport;
354
355                 Hashtable sourceFiles = new Hashtable ();
356                 public override void DefaultArgumentProcessor(string fileName)
357                 {
358                         if (firstSourceFile == null)
359                                 firstSourceFile = fileName;
360
361                         if (!sourceFiles.Contains(fileName)) {
362                                 SourceFilesToCompile.Add(new FileToCompile(fileName, currentEncoding));
363                                 sourceFiles.Add(fileName, fileName);
364                         }
365                         base.DefaultArgumentProcessor(fileName);
366                 }               
367
368                 public ArrayList AssembliesToReference = new ArrayList();
369                 public ArrayList NetModulesToAdd = new ArrayList();
370                 public ArrayList PathsToSearchForLibraries = new ArrayList();
371                 public ArrayList DebugListOfArguments = new ArrayList ();
372                 public ArrayList SourceFilesToCompile = new ArrayList();
373                 
374                 public bool ReferencePackage(string packageName)
375                 {
376                         if (packageName == ""){
377                                 DoAbout ();
378                                 return false;
379                         }
380                                 
381                         ProcessStartInfo pi = new ProcessStartInfo ();
382                         pi.FileName = "pkg-config";
383                         pi.RedirectStandardOutput = true;
384                         pi.UseShellExecute = false;
385                         pi.Arguments = "--libs " + packageName;
386                         Process p = null;
387                         try {
388                                 p = Process.Start (pi);
389                         } catch (Exception e) {
390                                 ReportError (0, "Couldn't run pkg-config: " + e.Message);
391                                 return false;
392                         }
393
394                         if (p.StandardOutput == null){
395                                 ReportError (0, "Specified package did not return any information");
396                         }
397                         string pkgout = p.StandardOutput.ReadToEnd ();
398                         p.WaitForExit ();
399                         if (p.ExitCode != 0) {
400                                 ReportError (0, "Error running pkg-config. Check the above output.");
401                                 return false;
402                         }
403                         p.Close ();
404                         
405                         if (pkgout != null) {
406                                 string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}).
407                                         Split (new Char [] { ' ', '\t'});
408                                 foreach(string arg in xargs) {
409                                         string[] zargs = arg.Split(':', '=');
410                                         try {
411                                                 if (zargs.Length > 1)
412                                                         AddedReference = zargs[1];
413                                                 else
414                                                         AddedReference = arg;
415                                         } catch (Exception e) {
416                                                 ReportError (0, "Something wrong with argument (" + arg + ") in 'pkg-config --libs' output: " + e.Message);
417                                                 return false;
418                                         }
419                                 }
420                         }
421
422                         return true;
423                 }               
424                 
425                 private bool printTimeStamps = false;
426                 //
427                 // Last time we took the time
428                 //
429                 DateTime last_time;
430                 public void StartTime (string msg)
431                 {
432                         if (!printTimeStamps)
433                                 return;
434                                 
435                         last_time = DateTime.Now;
436
437                         Console.WriteLine("[*] {0}", msg);
438                 }
439
440                 public void ShowTime (string msg)
441                 {
442                         if (!printTimeStamps)
443                                 return;
444                                 
445                         DateTime now = DateTime.Now;
446                         TimeSpan span = now - last_time;
447                         last_time = now;
448
449                         Console.WriteLine (
450                                 "[{0:00}:{1:000}] {2}",
451                                 (int) span.TotalSeconds, span.Milliseconds, msg);
452                 }
453                 
454                 [Option("Displays time stamps of various compiler events", "timestamp", SecondLevelHelp = true)]
455                 public virtual bool PrintTimeStamps {
456                         set
457                         {
458                                 printTimeStamps = true;
459                                 last_time = DateTime.Now;
460                                 DebugListOfArguments.Add("timestamp");
461                         }
462                 }
463
464                 public bool BeQuiet { get { return DontShowBanner || SuccintErrorDisplay; } } 
465                 
466                 private void LoadAssembly (AssemblyAdder adder, string assemblyName, ref int errors, bool soft)
467                 {
468                         Assembly a = null;
469                         string total_log = "";
470
471                         try  {
472                                 char[] path_chars = { '/', '\\' };
473
474                                 if (assemblyName.IndexOfAny (path_chars) != -1)
475                                         a = Assembly.LoadFrom(assemblyName);
476                                 else {
477                                         string ass = assemblyName;
478                                         if (ass.EndsWith (".dll"))
479                                                 ass = assemblyName.Substring (0, assemblyName.Length - 4);
480                                         a = Assembly.Load (ass);
481                                 }
482                                 adder(a);
483                                 return;
484                         }
485                         catch (FileNotFoundException) {
486                                 if (PathsToSearchForLibraries != null) {
487                                         foreach (string dir in PathsToSearchForLibraries) {
488                                                 string full_path = Path.Combine(dir, assemblyName + ".dll");
489
490                                                 try  {
491                                                         a = Assembly.LoadFrom (full_path);
492                                                         adder(a);
493                                                         return;
494                                                 } 
495                                                 catch (FileNotFoundException ff)  {
496                                                         total_log += ff.FusionLog;
497                                                         continue;
498                                                 }
499                                         }
500                                 }
501                                 if (soft)
502                                         return;
503                                         
504                                 ReportError (6, "Can not find assembly '" + assemblyName + "'\nLog: " + total_log);
505                         }
506                         catch (BadImageFormatException f)  {
507                                 ReportError (6, "Bad file format while loading assembly\nLog: " + f.FusionLog);
508                         } catch (FileLoadException f){
509                                 ReportError (6, "File Load Exception: " + assemblyName + "\nLog: " + f.FusionLog);
510                         } catch (ArgumentNullException){
511                                 ReportError (6, "Argument Null exception");
512                         }
513                                                 
514                         errors++;
515                 }
516                 
517                 public virtual string [] AssembliesToReferenceSoftly {
518                         get {
519                                 // For now the "default config" is hardcoded we can move this outside later
520                                 return new string [] { "System", "System.Data", "System.Xml" };
521                         }
522                 }
523                 
524                 /// <summary>
525                 ///   Loads all assemblies referenced on the command line
526                 /// </summary>
527                 public bool LoadReferencedAssemblies (AssemblyAdder adder)
528                 {
529                         StartTime("Loading referenced assemblies");
530
531                         int errors = 0;
532                         int soft_errors = 0;
533                         
534                         // Load Core Library for default compilation
535                         if (!NoStandardLibraries)
536                                 LoadAssembly(adder, "mscorlib", ref errors, false);
537
538                         foreach (string r in AssembliesToReference)
539                                 LoadAssembly(adder, r, ref errors, false);
540
541                         if (!NoConfig)
542                                 foreach (string r in AssembliesToReferenceSoftly)
543                                         if (!(AssembliesToReference.Contains(r) || AssembliesToReference.Contains (r + ".dll")))
544                                                 LoadAssembly(adder, r, ref soft_errors, true);
545                         
546                         ShowTime("References loaded");
547                         return errors == 0;
548                 }
549                 
550                 private void LoadModule (MethodInfo adder_method, AssemblyBuilder assemblyBuilder, ModuleAdder adder, string module, ref int errors)
551                 {
552                         System.Reflection.Module m;
553                         string total_log = "";
554
555                         try {
556                                 try {
557                                         m = (System.Reflection.Module)adder_method.Invoke (assemblyBuilder, new object [] { module });
558                                 }
559                                 catch (TargetInvocationException ex) {
560                                         throw ex.InnerException;
561                                 }
562                                 adder(m);
563                         } 
564                         catch (FileNotFoundException) {
565                                 foreach (string dir in PathsToSearchForLibraries)       {
566                                         string full_path = Path.Combine (dir, module);
567                                         if (!module.EndsWith (".netmodule"))
568                                                 full_path += ".netmodule";
569
570                                         try {
571                                                 try {
572                                                         m = (System.Reflection.Module) adder_method.Invoke (assemblyBuilder, new object [] { full_path });
573                                                 }
574                                                 catch (TargetInvocationException ex) {
575                                                         throw ex.InnerException;
576                                                 }
577                                                 adder(m);
578                                                 return;
579                                         }
580                                         catch (FileNotFoundException ff) {
581                                                 total_log += ff.FusionLog;
582                                                 continue;
583                                         }
584                                 }
585                                 ReportError (6, "Cannot find module `" + module + "'" );
586                                 Console.WriteLine ("Log: \n" + total_log);
587                         }
588                         catch (BadImageFormatException f) {
589                                 ReportError (6, "Cannot load module (bad file format)" + f.FusionLog);
590                         }
591                         catch (FileLoadException f)     {
592                                 ReportError (6, "Cannot load module " + f.FusionLog);
593                         }
594                         catch (ArgumentNullException) {
595                                 ReportError (6, "Cannot load module (null argument)");
596                         }
597                         errors++;
598                 }
599
600                 public void UnsupportedFeatureOnthisRuntime(string feature)
601                 {
602                         ReportError (0, string.Format("Cannot use {0} on this runtime: Try the Mono runtime instead.", feature));
603                         Environment.Exit (1);
604                 }
605
606                 public bool LoadAddedNetModules(AssemblyBuilder assemblyBuilder, ModuleAdder adder)
607                 {
608                         int errors = 0;
609                         
610                         if (NetModulesToAdd.Count > 0) {
611                                 StartTime("Loading added netmodules");
612
613                                 MethodInfo adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.NonPublic);
614                                 if (adder_method == null)
615                                         UnsupportedFeatureOnthisRuntime("/addmodule");
616
617                                 foreach (string module in NetModulesToAdd)
618                                         LoadModule (adder_method, assemblyBuilder, adder, module, ref errors);
619                                         
620                                 ShowTime("   Done");
621                         }
622                         
623                         return errors == 0;
624                 }
625                 
626                 public void AdjustCodegenWhenTargetIsNetModule(AssemblyBuilder assemblyBuilder)
627                 {
628                         if (TargetFileType == TargetType.Module) {
629                                 StartTime("Adjusting AssemblyBuilder for NetModule target");
630                                 PropertyInfo module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
631                                 if (module_only == null)
632                                         UnsupportedFeatureOnthisRuntime("/target:module");
633
634                                 MethodInfo set_method = module_only.GetSetMethod (true);
635                                 set_method.Invoke (assemblyBuilder, BindingFlags.Default, null, new object[]{true}, null);
636                                 ShowTime("   Done");
637                         }
638                 }
639                 
640                 
641                 //
642                 // Given a path specification, splits the path from the file/pattern
643                 //
644                 void SplitPathAndPattern (string spec, out string path, out string pattern)
645                 {
646                         int p = spec.LastIndexOf ("/");
647                         if (p != -1){
648                                 //
649                                 // Windows does not like /file.cs, switch that to:
650                                 // "\", "file.cs"
651                                 //
652                                 if (p == 0){
653                                         path = "\\";
654                                         pattern = spec.Substring (1);
655                                 } else {
656                                         path = spec.Substring (0, p);
657                                         pattern = spec.Substring (p + 1);
658                                 }
659                                 return;
660                         }
661
662                         p = spec.LastIndexOf ("\\");
663                         if (p != -1){
664                                 path = spec.Substring (0, p);
665                                 pattern = spec.Substring (p + 1);
666                                 return;
667                         }
668
669                         path = ".";
670                         pattern = spec;
671                 }
672
673                 bool AddFiles (string spec, bool recurse)
674                 {
675                         string path, pattern;
676
677                         SplitPathAndPattern(spec, out path, out pattern);
678                         if (pattern.IndexOf("*") == -1) {
679                                 DefaultArgumentProcessor(spec);
680                                 return true;
681                         }
682
683                         string [] files = null;
684                         try {
685                                 files = Directory.GetFiles(path, pattern);
686                         } catch (System.IO.DirectoryNotFoundException) {
687                                 ReportError (2001, "Source file '" + spec + "' could not be found");
688                                 return false;
689                         } catch (System.IO.IOException){
690                                 ReportError (2001, "Source file '" + spec + "' could not be found");
691                                 return false;
692                         }
693                         foreach (string f in files)
694                                 DefaultArgumentProcessor (f);
695
696                         if (!recurse)
697                                 return true;
698                         
699                         string [] dirs = null;
700
701                         try {
702                                 dirs = Directory.GetDirectories(path);
703                         } catch {
704                         }
705                         
706                         foreach (string d in dirs) {
707                                         
708                                 // Don't include path in this string, as each
709                                 // directory entry already does
710                                 AddFiles (d + "/" + pattern, true);
711                         }
712
713                         return true;
714                 }
715
716                 public void EmbedResources(AssemblyBuilder builder)
717                 {
718                         if (EmbeddedResources != null)
719                                 foreach (string file in EmbeddedResources)
720                                         builder.AddResourceFile (file, file); // TODO: deal with resource IDs
721                 }
722
723                 public virtual bool NothingToCompile {
724                         get {
725                                 if (SourceFilesToCompile.Count == 0) {
726                                         if (!BeQuiet) 
727                                                 DoHelp();
728                                         return true;
729                                 }
730                                 if (!BeQuiet)
731                                         ShowBanner();
732                                 return false;
733                         }
734                 }
735
736         }
737         
738         public class CommonCompilerOptions2 : CommonCompilerOptions
739         {
740                 [Option("Specify target CPU platform {ID}. ID can be x86, Itanium, x64 (AMD 64bit) or anycpu (the default).", "platform", SecondLevelHelp = true)]
741                 public string TargetPlatform;
742                 
743                 [Option("What {action} (prompt | send | none) should be done when an internal compiler error occurs.\tThe default is none what just prints the error data in the compiler output", "errorreport", SecondLevelHelp = true)]
744                 public InternalCompilerErrorReportAction HowToReportErrors = InternalCompilerErrorReportAction.none;
745                 
746                 [Option("Filealign internal blocks to the {blocksize} in bytes. Valid values are 512, 1024, 2048, 4096, and 8192.", "filealign", SecondLevelHelp = true)]
747                 public int FileAlignBlockSize = 0; // 0 means use appropriate (not fixed) default               
748                 
749                 [Option("Generate documentation from xml commments.", "doc", SecondLevelHelp = true, VBCStyleBoolean = true)]
750                 public bool GenerateXmlDocumentation = false;
751                 
752                 [Option("Generate documentation from xml commments to an specific {file}.", "docto", SecondLevelHelp = true)]
753                 public string GenerateXmlDocumentationToFileName = null;
754         }
755         
756 }