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