Patch from Lawrence to catch correct entry points:
[mono.git] / mcs / mcs / driver.cs
1 //
2 // driver.cs: The compiler command line driver.
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10
11 namespace Mono.CSharp
12 {
13         using System;
14         using System.Reflection;
15         using System.Reflection.Emit;
16         using System.Collections;
17         using System.IO;
18         using System.Globalization;
19         using Mono.Languages;
20
21         enum Target {
22                 Library, Exe, Module, WinExe
23         };
24         
25         /// <summary>
26         ///    The compiler driver.
27         /// </summary>
28         public class Driver
29         {
30                 
31                 //
32                 // Assemblies references to be linked.   Initialized with
33                 // mscorlib.dll here.
34                 static ArrayList references;
35
36                 //
37                 // If any of these fail, we ignore the problem.  This is so
38                 // that we can list all the assemblies in Windows and not fail
39                 // if they are missing on Linux.
40                 //
41                 static ArrayList soft_references;
42
43                 // Lookup paths
44                 static ArrayList link_paths;
45
46                 // Whether we want Yacc to output its progress
47                 static bool yacc_verbose = false;
48
49                 // Whether we want to only run the tokenizer
50                 static bool tokenize = false;
51                 
52                 static int error_count = 0;
53
54                 static string first_source;
55
56                 static Target target = Target.Exe;
57                 static string target_ext = ".exe";
58
59                 static bool want_debugging_support = false;
60
61                 static bool parse_only = false;
62                 static bool timestamps = false;
63
64                 //
65                 // Whether to load the initial config file (what CSC.RSP has by default)
66                 // 
67                 static bool load_default_config = true;
68
69                 static Hashtable response_file_list;
70                 static Hashtable source_files = new Hashtable ();
71
72                 //
73                 // A list of resource files
74                 //
75                 static ArrayList resources;
76                 
77                 //
78                 // An array of the defines from the command line
79                 //
80                 static ArrayList defines;
81
82                 //
83                 // Last time we took the time
84                 //
85                 static DateTime last_time;
86                 static void ShowTime (string msg)
87                 {
88                         DateTime now = DateTime.Now;
89                         TimeSpan span = now - last_time;
90                         last_time = now;
91
92                         Console.WriteLine (
93                                 "[{0:00}:{1:000}] {2}",
94                                 (int) span.TotalSeconds, span.Milliseconds, msg);
95                 }
96                
97                 static int tokenize_file (string input_file)
98                 {
99                         Stream input;
100
101                         try {
102                                 input = File.OpenRead (input_file);
103
104                         } catch {
105                                 Report.Error (2001, "Source file '" + input_file + "' could not be opened");
106                                 return 1;
107                         }
108
109                         using (input){
110                                 Tokenizer lexer = new Tokenizer (input, input_file, defines);
111                                 int token, tokens = 0, errors = 0;
112
113                                 while ((token = lexer.token ()) != Token.EOF){
114                                         Location l = lexer.Location;
115                                         tokens++;
116                                         if (token == Token.ERROR)
117                                                 errors++;
118                                 }
119                                 Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors");
120                         }
121                         
122                         return 0;
123                 }
124                 
125                 static int parse (string input_file)
126                 {
127                         CSharpParser parser;
128                         Stream input;
129                         int errors;
130
131                         try {
132                                 input = File.OpenRead (input_file);
133                         } catch {
134                                 Report.Error (2001, "Source file '" + input_file + "' could not be opened");
135                                 return 1;
136                         }
137
138                         parser = new CSharpParser (input_file, input, defines);
139                         parser.yacc_verbose = yacc_verbose;
140                         try {
141                                 errors = parser.parse ();
142                         } catch (Exception ex) {
143                                 Console.WriteLine (ex);
144                                 Console.WriteLine ("Compilation aborted");
145                                 return 1;
146                         } finally {
147                                 input.Close ();
148                         }
149                         
150                         return errors;
151                 }
152                 
153                 static void Usage (bool is_error)
154                 {
155                         Console.WriteLine (
156                                 "Mono C# compiler, (C) 2001 Ximian, Inc.\n" +
157                                 "mcs [options] source-files\n" +
158                                 "   --about         About the Mono C# compiler\n" +
159                                 "   --checked       Set default context to checked\n" +
160                                 "   --define SYM    Defines the symbol SYM\n" +
161                                 "   --debug         Generate debugging information\n" + 
162                                 "   -g              Generate debugging information\n" +
163                                 "   --fatal         Makes errors fatal\n" +
164                                 "   -L PATH         Adds PATH to the assembly link path\n" +
165                                 "   --noconfig      Disables implicit references to assemblies\n" +
166                                 "   --nostdlib      Does not load core libraries\n" +
167                                 "   --nowarn XXX    Ignores warning number XXX\n" +
168                                 "   -o FNAME        Specifies output file\n" +
169                                 "   --optimize      Optimizes\n" +
170                                 "   -g, --debug     Write symbolic debugging information to FILE-debug.s\n" +
171                                 "   --parse         Only parses the source file\n" +
172                                 "   --probe X       Probes for the source to generate code X on line L\n" +
173                                 "   --recurse SPEC  Recursively compiles the files in SPEC ([dir]/file)\n" + 
174                                 "   --resource FILE Addds FILE as a resource\n" + 
175                                 "   --stacktrace    Shows stack trace at error location\n" +
176                                 "   --target KIND   Specifies the target (KIND is one of: exe, winexe, " +
177                                                     "library, module)\n" +
178                                 "   --timestamp     Displays time stamps of various compiler events\n" +
179                                 "   --unsafe        Allows unsafe code\n" +
180                                 "   --werror        Treat warnings as errors\n" +
181                                 "   --wlevel LEVEL  Sets warning level (the highest is 4, the default)\n" +
182                                 "   -r              References an assembly\n" +
183                                 "   -v              Verbose parsing (for debugging the parser)\n" +
184                                 "   @file           Read response file for more options");
185                         if (is_error)
186                                 error_count++;
187                 }
188
189                 static void About ()
190                 {
191                         Console.WriteLine (
192                                 "The Mono C# compiler is (C) 2001 Ximian, Inc.\n\n" +
193                                 "The compiler source code is released under the terms of the GNU GPL\n\n" +
194
195                                 "For more information on Mono, visit the project Web site\n" +
196                                 "   http://www.go-mono.com\n\n" +
197
198                                 "The compiler was written by Miguel de Icaza and Ravi Pratap");
199                 }
200                 
201                 static void error (string msg)
202                 {
203                         Console.WriteLine ("Error: " + msg);
204                 }
205
206                 static void notice (string msg)
207                 {
208                         Console.WriteLine (msg);
209                 }
210                 
211                 public static int Main (string[] args)
212                 {
213                         MainDriver (args);
214                         
215                         return (error_count + Report.Errors) != 0 ? 1 : 0;
216                 }
217
218                 static public int LoadAssembly (string assembly, bool soft)
219                 {
220                         Assembly a;
221                         string total_log = "";
222
223                         try {
224                                 char[] path_chars = { '/', '\\', '.' };
225
226                                 if (assembly.IndexOfAny (path_chars) != -1)
227                                         a = Assembly.LoadFrom (assembly);
228                                 else
229                                         a = Assembly.Load (assembly);
230                                 TypeManager.AddAssembly (a);
231                                 return 0;
232                         } catch (FileNotFoundException){
233                                 foreach (string dir in link_paths){
234                                         string full_path = dir + "/" + assembly + ".dll";
235
236                                         try {
237                                                 a = Assembly.LoadFrom (full_path);
238                                                 TypeManager.AddAssembly (a);
239                                                 return 0;
240                                         } catch (FileNotFoundException ff) {
241                                                 total_log += ff.FusionLog;
242                                                 continue;
243                                         }
244                                 }
245                                 if (soft)
246                                         return 0;
247                         } catch (BadImageFormatException f) {
248                                 error ("// Bad file format while loading assembly");
249                                 error ("Log: " + f.FusionLog);
250                                 return 1;
251                         } catch (FileLoadException f){
252                                 error ("// File Load Exception: ");
253                                 error ("Log: " + f.FusionLog);
254                                 return 1;
255                         } catch (ArgumentNullException){
256                                 error ("// Argument Null exception ");
257                                 return 1;
258                         }
259                         
260                         Report.Error (6, "Can not find assembly `" + assembly + "'" );
261                         Console.WriteLine ("Log: \n" + total_log);
262
263                         return 0;
264                 }
265
266                 /// <summary>
267                 ///   Loads all assemblies referenced on the command line
268                 /// </summary>
269                 static public int LoadReferences ()
270                 {
271                         int errors = 0;
272
273                         foreach (string r in references)
274                                 errors += LoadAssembly (r, false);
275
276                         foreach (string r in soft_references)
277                                 errors += LoadAssembly (r, true);
278                         
279                         return errors;
280                 }
281
282                 static void SetupDefaultDefines ()
283                 {
284                         defines = new ArrayList ();
285                         defines.Add ("__MonoCS__");
286                 }
287
288                 static string [] LoadArgs (string file)
289                 {
290                         StreamReader f;
291                         ArrayList args = new ArrayList ();
292                         string line;
293                         try {
294                                 f = new StreamReader (file);
295                         } catch {
296                                 return null;
297                         }
298
299                         while ((line = f.ReadLine ()) != null){
300                                 string [] line_args = line.Split (new char [] { ' ' });
301
302                                 foreach (string arg in line_args)
303                                         args.Add (arg);
304                         }
305
306                         string [] ret_value = new string [args.Count];
307                         args.CopyTo (ret_value, 0);
308
309                         return ret_value;
310                 }
311
312                 //
313                 // Returns the directory where the system assemblies are installed
314                 //
315                 static string GetSystemDir ()
316                 {
317                         Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
318
319                         foreach (Assembly a in assemblies){
320                                 string codebase = a.CodeBase;
321                                 if (codebase.EndsWith ("corlib.dll")){
322                                         return codebase.Substring (0, codebase.LastIndexOf ("/"));
323                                 }
324                         }
325
326                         Report.Error (-15, "Can not compute my system path");
327                         return "";
328                 }
329
330                 //
331                 // Given a path specification, splits the path from the file/pattern
332                 //
333                 static void SplitPathAndPattern (string spec, out string path, out string pattern)
334                 {
335                         int p = spec.LastIndexOf ("/");
336                         if (p != -1){
337                                 //
338                                 // Windows does not like /file.cs, switch that to:
339                                 // "\", "file.cs"
340                                 //
341                                 if (p == 0){
342                                         path = "\\";
343                                         pattern = spec.Substring (1);
344                                 } else {
345                                         path = spec.Substring (0, p);
346                                         pattern = spec.Substring (p + 1);
347                                 }
348                                 return;
349                         }
350
351                         p = spec.LastIndexOf ("\\");
352                         if (p != -1){
353                                 path = spec.Substring (0, p);
354                                 pattern = spec.Substring (p + 1);
355                                 return;
356                         }
357
358                         path = ".";
359                         pattern = spec;
360                 }
361
362                 static int ProcessFile (string f)
363                 {
364                         if (first_source == null)
365                                 first_source = f;
366
367                         if (source_files.Contains (f)){
368                                 Report.Error (
369                                         1516,
370                                         "Source file `" + f + "' specified multiple times");
371                                 Environment.Exit (1);
372                         } else
373                                 source_files.Add (f, f);
374                                         
375                         if (tokenize)
376                                 tokenize_file (f);
377                         else
378                                 return parse (f);
379                         return 0;
380                 }
381
382                 static int CompileFiles (string spec, bool recurse)
383                 {
384                         string path, pattern;
385                         int errors = 0;
386
387                         SplitPathAndPattern (spec, out path, out pattern);
388                         string [] files = null;
389                         try {
390                                 files = Directory.GetFiles (path, pattern);
391                         } catch (System.IO.DirectoryNotFoundException) {
392                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
393                                 return 1;
394                         } catch (System.IO.IOException){
395                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
396                                 return 1;
397                         }
398                                 
399                         foreach (string f in files)
400                                 errors += ProcessFile (f);
401
402                         if (!recurse)
403                                 return errors;
404                         
405                         string [] dirs = null;
406
407                         try {
408                                 dirs = Directory.GetDirectories (path);
409                         } catch {
410                         }
411                         
412                         foreach (string d in dirs) {
413                                         
414                                 // Don't include path in this string, as each
415                                 // directory entry already does
416                                 errors += CompileFiles (d + "/" + pattern, true);
417                         }
418                         
419
420                         return errors;
421                 }
422
423                 static void DefineDefaultConfig ()
424                 {
425                         //
426                         // For now the "default config" is harcoded into the compiler
427                         // we can move this outside later
428                         //
429                         string [] default_config = {
430                                 "System",
431                                 "System.Xml",
432 #if false
433                                 //
434                                 // Is it worth pre-loading all this stuff?
435                                 //
436                                 "Accessibility",
437                                 "System.Configuration.Install",
438                                 "System.Data",
439                                 "System.Design",
440                                 "System.DirectoryServices",
441                                 "System.Drawing.Design",
442                                 "System.Drawing",
443                                 "System.EnterpriseServices",
444                                 "System.Management",
445                                 "System.Messaging",
446                                 "System.Runtime.Remoting",
447                                 "System.Runtime.Serialization.Formatters.Soap",
448                                 "System.Security",
449                                 "System.ServiceProcess",
450                                 "System.Web",
451                                 "System.Web.RegularExpressions",
452                                 "System.Web.Services",
453                                 "System.Windows.Forms"
454 #endif
455                         };
456                         
457                         int p = 0;
458                         foreach (string def in default_config)
459                                 soft_references.Insert (p++, def);
460                 }
461                 
462                 /// <summary>
463                 ///    Parses the arguments, and drives the compilation
464                 ///    process.
465                 /// </summary>
466                 ///
467                 /// <remarks>
468                 ///    TODO: Mostly structured to debug the compiler
469                 ///    now, needs to be turned into a real driver soon.
470                 /// </remarks>
471                 static void MainDriver (string [] args)
472                 {
473                         int errors = 0, i;
474                         string output_file = null;
475                         bool parsing_options = true;
476                         
477                         references = new ArrayList ();
478                         soft_references = new ArrayList ();
479                         link_paths = new ArrayList ();
480
481                         SetupDefaultDefines ();
482                         
483                         //
484                         // Setup defaults
485                         //
486                         // This is not required because Assembly.Load knows about this
487                         // path.
488                         //
489                         link_paths.Add (GetSystemDir ());
490
491                         int argc = args.Length;
492                         for (i = 0; i < argc; i++){
493                                 string arg = args [i];
494
495                                 if (arg.StartsWith ("@")){
496                                         string [] new_args, extra_args;
497                                         string response_file = arg.Substring (1);
498
499                                         if (response_file_list == null)
500                                                 response_file_list = new Hashtable ();
501                                         
502                                         if (response_file_list.Contains (response_file)){
503                                                 Report.Error (
504                                                         1515, "Response file `" + response_file +
505                                                         "' specified multiple times");
506                                                 Environment.Exit (1);
507                                         }
508                                         
509                                         response_file_list.Add (response_file, response_file);
510                                                     
511                                         extra_args = LoadArgs (response_file);
512                                         if (extra_args == null){
513                                                 Report.Error (2011, "Unable to open response file: " +
514                                                               response_file);
515                                                 return;
516                                         }
517
518                                         new_args = new string [extra_args.Length + argc];
519                                         args.CopyTo (new_args, 0);
520                                         extra_args.CopyTo (new_args, argc);
521                                         args = new_args;
522                                         argc = new_args.Length;
523                                         continue;
524                                 }
525
526                                 //
527                                 // Prepare to recurse
528                                 //
529                                 
530                                 if (parsing_options && (arg.StartsWith ("-"))){
531                                         switch (arg){
532                                         case "-v":
533                                                 yacc_verbose = true;
534                                                 continue;
535
536                                         case "--":
537                                                 parsing_options = false;
538                                                 continue;
539
540                                         case "--parse":
541                                                 parse_only = true;
542                                                 continue;
543
544                                         case "--main": case "-m":
545                                                 if ((i + 1) >= argc){
546                                                         Usage (true);
547                                                         return;
548                                                 }
549                                                 RootContext.MainClass = args [++i];
550                                                 continue;
551
552                                         case "--unsafe":
553                                                 RootContext.Unsafe = true;
554                                                 continue;
555                                                 
556                                         case "--optimize":
557                                                 RootContext.Optimize = true;
558                                                 continue;
559
560                                         case "/?": case "/h": case "/help":
561                                         case "--help":
562                                                 Usage (false);
563                                                 return;
564
565                                         case "--define":
566                                                 if ((i + 1) >= argc){
567                                                         Usage (true);
568                                                         return;
569                                                 }
570                                                 defines.Add (args [++i]);
571                                                 continue;
572                                                 
573                                         case "--probe": {
574                                                 int code = 0;
575
576                                                 try {
577                                                         code = Int32.Parse (
578                                                                 args [++i], NumberStyles.AllowLeadingSign);
579                                                         Report.SetProbe (code);
580                                                 } catch {
581                                                         Report.Error (-14, "Invalid number specified");
582                                                 } 
583                                                 continue;
584                                         }
585
586                                         case "--tokenize": {
587                                                 tokenize = true;
588                                                 continue;
589                                         }
590                                         
591                                         case "-o": 
592                                         case "--output":
593                                                 if ((i + 1) >= argc){
594                                                         Usage (true);
595                                                         return;
596                                                 }
597                                                 output_file = args [++i];
598                                                 string bname = CodeGen.Basename (output_file);
599                                                 if (bname.IndexOf (".") == -1)
600                                                         output_file += ".exe";
601                                                 continue;
602
603                                         case "--checked":
604                                                 RootContext.Checked = true;
605                                                 continue;
606
607                                         case "--stacktrace":
608                                                 Report.Stacktrace = true;
609                                                 continue;
610
611                                         case "--resource":
612                                                 if ((i + 1) >= argc){
613                                                         Usage (true);
614                                                         Console.WriteLine("Missing argument to --resource"); 
615                                                         return;
616                                                 }
617                                                 if (resources == null)
618                                                         resources = new ArrayList ();
619                                                 
620                                                 resources.Add (args [++i]);
621                                                 continue;
622                                                         
623                                         case "--target":
624                                                 if ((i + 1) >= argc){
625                                                         Usage (true);
626                                                         return;
627                                                 }
628
629                                                 string type = args [++i];
630                                                 switch (type){
631                                                 case "library":
632                                                         target = Target.Library;
633                                                         target_ext = ".dll";
634                                                         break;
635                                                         
636                                                 case "exe":
637                                                         target = Target.Exe;
638                                                         break;
639                                                         
640                                                 case "winexe":
641                                                         target = Target.WinExe;
642                                                         break;
643                                                         
644                                                 case "module":
645                                                         target = Target.Module;
646                                                         target_ext = ".dll";
647                                                         break;
648                                                 default:
649                                                         Usage (true);
650                                                         return;
651                                                 }
652                                                 continue;
653
654                                         case "-r":
655                                                 if ((i + 1) >= argc){
656                                                         Usage (true);
657                                                         return;
658                                                 }
659                                                 
660                                                 references.Add (args [++i]);
661                                                 continue;
662                                                 
663                                         case "-L":
664                                                 if ((i + 1) >= argc){
665                                                         Usage (true);
666                                                         return;
667                                                 }
668                                                 link_paths.Add (args [++i]);
669                                                 continue;
670                                                 
671                                         case "--nostdlib":
672                                                 RootContext.StdLib = false;
673                                                 continue;
674                                                 
675                                         case "--fatal":
676                                                 Report.Fatal = true;
677                                                 continue;
678
679                                         case "--werror":
680                                                 Report.WarningsAreErrors = true;
681                                                 continue;
682
683                                         case "--nowarn":
684                                                 if ((i + 1) >= argc){
685                                                         Usage (true);
686                                                         return;
687                                                 }
688                                                 int warn;
689                                                 
690                                                 try {
691                                                         warn = Int32.Parse (args [++i]);
692                                                 } catch {
693                                                         Usage (true);
694                                                         return;
695                                                 }
696                                                 Report.SetIgnoreWarning (warn);
697                                                 continue;
698
699                                         case "--wlevel":
700                                                 if ((i + 1) >= argc){
701                                                         Report.Error (
702                                                                 1900,
703                                                                 "--wlevel requires an value from 0 to 4");
704                                                         error_count++;
705                                                         return;
706                                                 }
707                                                 int level;
708                                                 
709                                                 try {
710                                                         level = Int32.Parse (args [++i]);
711                                                 } catch {
712                                                         Report.Error (
713                                                                 1900,
714                                                                 "--wlevel requires an value from 0 to 4");
715                                                         return;
716                                                 }
717                                                 if (level < 0 || level > 4){
718                                                         Report.Error (1900, "Warning level must be 0 to 4");
719                                                         return;
720                                                 } else
721                                                         RootContext.WarningLevel = level;
722                                                 continue;
723                                                 
724                                         case "--about":
725                                                 About ();
726                                                 return;
727
728                                         case "--recurse":
729                                                 if ((i + 1) >= argc){
730                                                         Console.WriteLine ("--recurse requires an argument");
731                                                         error_count++;
732                                                         return;
733                                                 }
734                                                 errors += CompileFiles (args [++i], true);
735                                                 continue;
736                                                 
737                                         case "--timestamp":
738                                                 timestamps = true;
739                                                 last_time = DateTime.Now;
740                                                 continue;
741
742                                         case "--debug": case "-g":
743                                                 want_debugging_support = true;
744                                                 continue;
745
746                                         case "--noconfig":
747                                                 load_default_config = false;
748                                                 continue;
749
750                                         default:
751                                                 Console.WriteLine ("Unknown option: " + arg);
752                                                 errors++;
753                                                 continue;
754                                         }
755                                 }
756
757                                 CompileFiles (arg, false); 
758                         }
759
760                         if (tokenize)
761                                 return;
762                         
763                         if (first_source == null){
764                                 Report.Error (2008, "No files to compile were specified");
765                                 return;
766                         }
767
768                         if (Report.Errors > 0)
769                                 return;
770                         
771                         if (parse_only)
772                                 return;
773                         
774                         //
775                         // Load Core Library for default compilation
776                         //
777                         if (RootContext.StdLib)
778                                 references.Insert (0, "mscorlib");
779
780                         if (load_default_config)
781                                 DefineDefaultConfig ();
782
783                         if (errors > 0){
784                                 error ("Parsing failed");
785                                 return;
786                         }
787
788                         //
789                         // Load assemblies required
790                         //
791                         if (timestamps)
792                                 ShowTime ("Loading references");
793                         errors += LoadReferences ();
794                         if (timestamps)
795                                 ShowTime ("   References loaded");
796                         
797                         if (errors > 0){
798                                 error ("Could not load one or more assemblies");
799                                 return;
800                         }
801
802                         error_count = errors;
803
804                         //
805                         // Quick hack
806                         //
807                         if (output_file == null){
808                                 int pos = first_source.LastIndexOf (".");
809
810                                 if (pos > 0)
811                                         output_file = first_source.Substring (0, pos) + target_ext;
812                                 else
813                                         output_file = first_source + target_ext;
814                         }
815
816                         CodeGen.Init (output_file, output_file, want_debugging_support);
817
818                         TypeManager.AddModule (CodeGen.ModuleBuilder);
819
820                         //
821                         // Before emitting, we need to get the core
822                         // types emitted from the user defined types
823                         // or from the system ones.
824                         //
825                         if (timestamps)
826                                 ShowTime ("Initializing Core Types");
827                         if (!RootContext.StdLib){
828                                 RootContext.ResolveCore ();
829                                 if (Report.Errors > 0)
830                                         return;
831                         }
832                         
833                         TypeManager.InitCoreTypes ();
834                         if (timestamps)
835                                 ShowTime ("   Core Types done");
836
837                         //
838                         // The second pass of the compiler
839                         //
840                         if (timestamps)
841                                 ShowTime ("Resolving tree");
842                         RootContext.ResolveTree ();
843                         if (timestamps)
844                                 ShowTime ("Populate tree");
845                         if (!RootContext.StdLib)
846                                 RootContext.BootCorlib_PopulateCoreTypes ();
847                         RootContext.PopulateTypes ();
848                         
849                         TypeManager.InitCodeHelpers ();
850                                 
851                         if (Report.Errors > 0){
852                                 error ("Compilation failed");
853                                 return;
854                         }
855                         
856                         //
857                         // The code generator
858                         //
859                         if (timestamps)
860                                 ShowTime ("Emitting code");
861                         RootContext.EmitCode ();
862                         if (timestamps)
863                                 ShowTime ("   done");
864
865                         if (Report.Errors > 0){
866                                 error ("Compilation failed");
867                                 return;
868                         }
869
870                         if (timestamps)
871                                 ShowTime ("Closing types");
872                         
873                         RootContext.CloseTypes ();
874
875                         PEFileKinds k = PEFileKinds.ConsoleApplication;
876                                 
877                         if (target == Target.Library || target == Target.Module)
878                                 k = PEFileKinds.Dll;
879                         else if (target == Target.Exe)
880                                 k = PEFileKinds.ConsoleApplication;
881                         else if (target == Target.WinExe)
882                                 k = PEFileKinds.WindowApplication;
883
884                         if (target == Target.Exe || target == Target.WinExe){
885                                 MethodInfo ep = RootContext.EntryPoint;
886
887                                 if (ep == null){
888                                         Report.Error (5001, "Program " + output_file +
889                                                               " does not have an entry point defined");
890                                         return;
891                                 }
892                                 
893                                 CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
894                         }
895
896                         //
897                         // Add the resources
898                         //
899                         if (resources != null){
900                                 foreach (string file in resources)
901                                         CodeGen.AssemblyBuilder.AddResourceFile (file, file);
902                         }
903                         
904                         CodeGen.Save (output_file);
905                         if (timestamps)
906                                 ShowTime ("Saved output");
907
908                         if (want_debugging_support) {
909                                 CodeGen.SaveSymbols ();
910                                 if (timestamps)
911                                         ShowTime ("Saved symbols");
912                         }
913
914                         if (Report.Errors > 0){
915                                 error ("Compilation failed");
916                                 return;
917                         } else if (Report.ProbeCode != 0){
918                                 error ("Failed to report code " + Report.ProbeCode);
919                                 Environment.Exit (124);
920                         }
921                 }
922
923         }
924 }