2 // driver.cs: The compiler command line driver.
5 // Miguel de Icaza (miguel@gnu.org)
6 // Marek Safar (marek.safar@gmail.com)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004, 2005, 2006, 2007, 2008 Novell, Inc
15 using System.Reflection;
16 using System.Reflection.Emit;
17 using System.Collections.Generic;
20 using System.Globalization;
21 using System.Diagnostics;
26 /// The compiler driver.
30 readonly CompilerContext ctx;
32 public Driver (CompilerContext ctx)
43 void tokenize_file (CompilationSourceFile file)
48 input = File.OpenRead (file.Name);
50 Report.Error (2001, "Source file `" + file.Name + "' could not be found");
55 SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding);
56 Tokenizer lexer = new Tokenizer (reader, file, ctx);
57 int token, tokens = 0, errors = 0;
59 while ((token = lexer.token ()) != Token.EOF){
61 if (token == Token.ERROR)
64 Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors");
70 void Parse (ModuleContainer module)
72 Location.Initialize (module.Compiler.SourceFiles);
74 bool tokenize_only = module.Compiler.Settings.TokenizeOnly;
75 var sources = module.Compiler.SourceFiles;
76 for (int i = 0; i < sources.Count; ++i) {
78 tokenize_file (sources[i]);
80 Parse (sources[i], module);
85 public void Parse (CompilationSourceFile file, ModuleContainer module)
90 input = File.OpenRead (file.Name);
92 Report.Error (2001, "Source file `{0}' could not be found", file.Name);
97 if (input.ReadByte () == 77 && input.ReadByte () == 90) {
98 Report.Error (2015, "Source file `{0}' is a binary file and not a text file", file.Name);
104 SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding);
106 Parse (reader, file, module);
111 public void Parse (SeekableStreamReader reader, CompilationSourceFile file, ModuleContainer module)
113 file.NamespaceContainer = new NamespaceContainer (null, module, null, file);
115 CSharpParser parser = new CSharpParser (reader, file);
119 public static int Main (string[] args)
121 Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
123 var r = new Report (new ConsoleReportPrinter ());
124 CommandLineParser cmd = new CommandLineParser (r);
125 var settings = cmd.ParseArguments (args);
126 if (settings == null || r.Errors > 0)
129 if (cmd.HasBeenStopped)
132 Driver d = new Driver (new CompilerContext (settings, r));
134 if (d.Compile () && d.Report.Errors == 0) {
135 if (d.Report.Warnings > 0) {
136 Console.WriteLine ("Compilation succeeded - {0} warning(s)", d.Report.Warnings);
138 Environment.Exit (0);
143 Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
144 d.Report.Errors, d.Report.Warnings);
145 Environment.Exit (1);
149 public static string GetPackageFlags (string packages, Report report)
151 ProcessStartInfo pi = new ProcessStartInfo ();
152 pi.FileName = "pkg-config";
153 pi.RedirectStandardOutput = true;
154 pi.UseShellExecute = false;
155 pi.Arguments = "--libs " + packages;
158 p = Process.Start (pi);
159 } catch (Exception e) {
163 report.Error (-27, "Couldn't run pkg-config: " + e.Message);
167 if (p.StandardOutput == null) {
169 throw new ApplicationException ("Specified package did not return any information");
171 report.Warning (-27, 1, "Specified package did not return any information");
176 string pkgout = p.StandardOutput.ReadToEnd ();
178 if (p.ExitCode != 0) {
180 throw new ApplicationException (pkgout);
182 report.Error (-27, "Error running pkg-config. Check the above output.");
192 // Main compilation method
194 public bool Compile ()
196 var settings = ctx.Settings;
199 // If we are an exe, require a source file for the entry point or
200 // if there is nothing to put in the assembly, and we are not a library
202 if (settings.FirstSourceFile == null &&
203 ((settings.Target == Target.Exe || settings.Target == Target.WinExe || settings.Target == Target.Module) ||
204 settings.Resources == null)) {
205 Report.Error (2008, "No files to compile were specified");
209 TimeReporter tr = new TimeReporter (settings.Timestamps);
210 ctx.TimeReporter = tr;
213 var module = new ModuleContainer (ctx);
214 RootContext.ToplevelTypes = module;
216 tr.Start (TimeReporter.TimerType.ParseTotal);
218 tr.Stop (TimeReporter.TimerType.ParseTotal);
220 if (Report.Errors > 0)
223 if (settings.TokenizeOnly || settings.ParseOnly) {
229 var output_file = settings.OutputFile;
230 string output_file_name;
231 if (output_file == null) {
232 var source_file = settings.FirstSourceFile;
234 if (source_file == null) {
235 Report.Error (1562, "If no source files are specified you must specify the output file with -out:");
239 output_file_name = source_file.Name;
240 int pos = output_file_name.LastIndexOf ('.');
243 output_file_name = output_file_name.Substring (0, pos);
245 output_file_name += settings.TargetExt;
246 output_file = output_file_name;
248 output_file_name = Path.GetFileName (output_file);
252 var importer = new StaticImporter (module);
253 var references_loader = new StaticLoader (importer, ctx);
255 tr.Start (TimeReporter.TimerType.AssemblyBuilderSetup);
256 var assembly = new AssemblyDefinitionStatic (module, references_loader, output_file_name, output_file);
257 assembly.Create (references_loader.Domain);
258 tr.Stop (TimeReporter.TimerType.AssemblyBuilderSetup);
260 // Create compiler types first even before any referenced
261 // assembly is loaded to allow forward referenced types from
262 // loaded assembly into compiled builder to be resolved
264 tr.Start (TimeReporter.TimerType.CreateTypeTotal);
265 module.CreateType ();
266 importer.AddCompiledAssembly (assembly);
267 tr.Stop (TimeReporter.TimerType.CreateTypeTotal);
269 references_loader.LoadReferences (module);
271 tr.Start (TimeReporter.TimerType.PredefinedTypesInit);
272 if (!ctx.BuiltinTypes.CheckDefinitions (module))
275 tr.Stop (TimeReporter.TimerType.PredefinedTypesInit);
277 references_loader.LoadModules (assembly, module.GlobalRootNamespace);
279 var assembly = new AssemblyDefinitionDynamic (module, output_file_name, output_file);
280 module.SetDeclaringAssembly (assembly);
282 var importer = new ReflectionImporter (module, ctx.BuiltinTypes);
283 assembly.Importer = importer;
285 var loader = new DynamicLoader (importer, ctx);
286 loader.LoadReferences (module);
288 if (!ctx.BuiltinTypes.CheckDefinitions (module))
291 if (!assembly.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.Save))
294 module.CreateType ();
296 loader.LoadModules (assembly, module.GlobalRootNamespace);
298 module.InitializePredefinedTypes ();
300 tr.Start (TimeReporter.TimerType.UsingResolve);
301 foreach (var source_file in ctx.SourceFiles) {
302 source_file.NamespaceContainer.Resolve ();
304 tr.Stop (TimeReporter.TimerType.UsingResolve);
306 tr.Start (TimeReporter.TimerType.ModuleDefinitionTotal);
308 tr.Stop (TimeReporter.TimerType.ModuleDefinitionTotal);
310 if (Report.Errors > 0)
313 if (settings.DocumentationFile != null) {
314 var doc = new DocumentationBuilder (module);
315 doc.OutputDocComment (output_file, settings.DocumentationFile);
320 if (Report.Errors > 0)
324 tr.Start (TimeReporter.TimerType.EmitTotal);
326 tr.Stop (TimeReporter.TimerType.EmitTotal);
328 if (Report.Errors > 0){
332 tr.Start (TimeReporter.TimerType.CloseTypes);
334 tr.Stop (TimeReporter.TimerType.CloseTypes);
336 tr.Start (TimeReporter.TimerType.Resouces);
337 assembly.EmbedResources ();
338 tr.Stop (TimeReporter.TimerType.Resouces);
340 if (Report.Errors > 0)
346 references_loader.Dispose ();
351 return Report.Errors == 0;
356 // This is the only public entry point
358 public class CompilerCallableEntryPoint : MarshalByRefObject {
359 public static bool InvokeCompiler (string [] args, TextWriter error)
362 var r = new Report (new StreamReportPrinter (error));
363 CommandLineParser cmd = new CommandLineParser (r, error);
364 var setting = cmd.ParseArguments (args);
365 if (setting == null || r.Errors > 0)
368 var d = new Driver (new CompilerContext (setting, r));
375 public static int[] AllWarningNumbers {
377 return Report.AllWarnings;
381 public static void Reset ()
386 public static void PartialReset ()
391 public static void Reset (bool full_flag)
393 CSharpParser.yacc_verbose_flag = 0;
399 AnonymousTypeClass.Reset ();
400 AnonymousMethodBody.Reset ();
401 AnonymousMethodStorey.Reset ();
402 SymbolWriter.Reset ();
404 Linq.QueryBlock.TransparentParameter.Reset ();