// Compile a number of source files. public static CompilerError[] Compile (String[] sourceTexts, String[] sourceTextNames, String target, String[] imports, IDictionary options) { // Validate the parameters. if (sourceTexts == null) { throw new ArgumentNullException("sourceTexts"); } if (sourceTextNames == null) { throw new ArgumentNullException("sourceTextNames"); } if (target == null) { throw new ArgumentNullException("target"); } if (sourceTexts.Length == 0) { throw new ArgumentOutOfRangeException("sourceTexts"); } if (sourceTexts.Length != sourceTextNames.Length) { throw new ArgumentOutOfRangeException("sourceTextNames"); } #if CONFIG_CODEDOM // Build the compiler parameter block. CompilerParameters paramBlock; paramBlock = new CompilerParameters (imports, target, OptionSet(options, "debug")); int len = target.Length; if (len > 4 && target[len - 4] == '.' && (target[len - 3] == 'd' || target[len - 3] == 'D') && (target[len - 2] == 'l' || target[len - 2] == 'L') && (target[len - 1] == 'l' || target[len - 1] == 'L')) { paramBlock.GenerateExecutable = false; } else { paramBlock.GenerateExecutable = true; } if (OptionSet(options, "warnaserror")) { paramBlock.TreatWarningsAsErrors = true; } StringBuilder opts = new StringBuilder(); if (OptionSet(options, "o")) { opts.Append(" /optimize"); } if (OptionSet(options, "checked")) { opts.Append(" /checked"); } String opt = (String)(options["d"]); if (opt != null) { opts.AppendFormat(" /define:{0}", opt); } opt = (String)(options["m"]); if (opt != null) { opts.AppendFormat(" /m:{0}", opt); } if (OptionSet(options, "nostdlib")) { opts.Append(" /nostdlib"); } opt = (String)(options["res"]); if (opt != null) { opts.AppendFormat(" /resource:{0}", opt); } opt = (String)(options["target"]); if (opt != null) { paramBlock.GenerateExecutable = (opt != "library"); } if (OptionSet(options, "unsafe")) { opts.Append(" /unsafe"); } paramBlock.CompilerOptions = opts.ToString(); // Build a new set of source texts, with the filename // information from "sourceTextNames" prepended. String[] sources = new String [sourceTexts.Length]; int posn; for (posn = 0; posn < sourceTexts.Length; ++posn) { if (sourceTextNames[posn] == null) { sources[posn] = sourceTexts[posn]; } else { sources[posn] = "#line 1 \"" + sourceTextNames[posn] + "\"" + Environment.NewLine + sourceTexts[posn]; } } // Compile the source texts. ICodeCompiler compiler = (new CSharpCodeProvider()).CreateCompiler(); CompilerResults results = compiler.CompileAssemblyFromSourceBatch (paramBlock, sources); // Convert the errors into the correct format and return them. CompilerErrorCollection errors = results.Errors; CompilerError[] newErrors = new CompilerError [errors.Count]; posn = 0; foreach (System.CodeDom.Compiler.CompilerError error in errors) { newErrors[posn] = new CompilerError(); newErrors[posn].ErrorLevel = (error.IsWarning ? ErrorLevel.Warning : ErrorLevel.Error); newErrors[posn].ErrorMessage = error.ErrorText; if (error.ErrorNumber != null && error.ErrorNumber.StartsWith("CS")) { newErrors[posn].ErrorNumber = Int32.Parse(error.ErrorNumber.Substring(2)); } newErrors[posn].SourceColumn = error.Column; newErrors[posn].SourceFile = error.FileName; newErrors[posn].SourceLine = error.Line; ++posn; } return(newErrors); #else // We don't have the necessary CodeDom API's. throw new NotImplementedException(); #endif }
/// <summary> /// Converts an error string into a CompilerError object /// Return null if the line was not an error string /// </summary> private static CompilerError CreateErrorFromString(string error_string) { CompilerError error = new CompilerError(); Regex reg = new Regex (@"^((?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)\s){0,}(?<level>\w+)\sCS(?<number>\d*):\s(?<message>.*)", RegexOptions.Compiled | RegexOptions.ExplicitCapture); Match match = reg.Match (error_string); if (!match.Success) return null; if (String.Empty != match.Result ("${file}")) error.SourceFile = match.Result ("${file}"); if (String.Empty != match.Result ("${line}")) error.SourceLine = Int32.Parse (match.Result ("${line}")); if (String.Empty != match.Result ("${column}")) error.SourceColumn = Int32.Parse (match.Result ("${column}")); error.ErrorLevel = (ErrorLevel)Enum.Parse (typeof(ErrorLevel), match.Result ("${level}"), true); error.ErrorNumber = Int32.Parse (match.Result ("${number}")); error.ErrorMessage = match.Result ("${message}"); return error; }
private CompilerResults FromFileBatch(CompilerParameters options, string[] fileNames) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (fileNames == null) { throw new ArgumentNullException(nameof(fileNames)); } CompilerResults results = new CompilerResults(options.TempFiles); Process mcs = new Process(); // FIXME: these lines had better be platform independent. if (Path.DirectorySeparatorChar == '\\') { mcs.StartInfo.FileName = MonoToolsLocator.Mono; mcs.StartInfo.Arguments = "\"" + MonoToolsLocator.McsCSharpCompiler + "\" "; } else { mcs.StartInfo.FileName = MonoToolsLocator.McsCSharpCompiler; } mcs.StartInfo.Arguments += BuildArgs(options, fileNames, _provOptions); var stderr_completed = new ManualResetEvent(false); var stdout_completed = new ManualResetEvent(false); /* * string monoPath = Environment.GetEnvironmentVariable ("MONO_PATH"); * if (monoPath != null) * monoPath = String.Empty; * * string privateBinPath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath; * if (privateBinPath != null && privateBinPath.Length > 0) * monoPath = String.Format ("{0}:{1}", privateBinPath, monoPath); * * if (monoPath.Length > 0) { * StringDictionary dict = mcs.StartInfo.EnvironmentVariables; * if (dict.ContainsKey ("MONO_PATH")) * dict ["MONO_PATH"] = monoPath; * else * dict.Add ("MONO_PATH", monoPath); * } */ /* * reset MONO_GC_PARAMS - we are invoking compiler possibly with another GC that * may not handle some of the options causing compilation failure */ mcs.StartInfo.EnvironmentVariables.Remove("MONO_GC_PARAMS"); #if XAMMAC_4_5 /*/ * reset MONO_CFG_DIR - we don't want to propagate the current config to another mono * since it's specific to the XM application and won't work on system mono. */ mcs.StartInfo.EnvironmentVariables.Remove("MONO_CFG_DIR"); #endif mcs.StartInfo.CreateNoWindow = true; mcs.StartInfo.UseShellExecute = false; mcs.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; mcs.StartInfo.RedirectStandardOutput = true; mcs.StartInfo.RedirectStandardError = true; mcs.ErrorDataReceived += new DataReceivedEventHandler((sender, args) => { if (args.Data != null) { results.Output.Add(args.Data); } else { stderr_completed.Set(); } }); mcs.OutputDataReceived += new DataReceivedEventHandler((sender, args) => { if (args.Data == null) { stdout_completed.Set(); } }); // Use same text decoder as mcs and not user set values in Console mcs.StartInfo.StandardOutputEncoding = mcs.StartInfo.StandardErrorEncoding = Encoding.UTF8; try { mcs.Start(); } catch (Exception e) { Win32Exception exc = e as Win32Exception; if (exc != null) { throw new SystemException(String.Format("Error running {0}: {1}", mcs.StartInfo.FileName, Win32Exception.GetErrorMessage(exc.NativeErrorCode))); } throw; } try { mcs.BeginOutputReadLine(); mcs.BeginErrorReadLine(); mcs.WaitForExit(); results.NativeCompilerReturnValue = mcs.ExitCode; } finally { stderr_completed.WaitOne(TimeSpan.FromSeconds(30)); stdout_completed.WaitOne(TimeSpan.FromSeconds(30)); mcs.Close(); } bool loadIt = true; foreach (string error_line in results.Output) { CompilerError error = CreateErrorFromString(error_line); if (error != null) { results.Errors.Add(error); if (!error.IsWarning) { loadIt = false; } } } if (results.Output.Count > 0) { results.Output.Insert(0, mcs.StartInfo.FileName + " " + mcs.StartInfo.Arguments + Environment.NewLine); } if (loadIt) { if (!File.Exists(options.OutputAssembly)) { StringBuilder sb = new StringBuilder(); foreach (string s in results.Output) { sb.Append(s + Environment.NewLine); } throw new Exception("Compiler failed to produce the assembly. Output: '" + sb.ToString() + "'"); } if (options.GenerateInMemory) { using (FileStream fs = File.OpenRead(options.OutputAssembly)) { byte[] buffer = new byte[fs.Length]; fs.Read(buffer, 0, buffer.Length); results.CompiledAssembly = Assembly.Load(buffer, null); fs.Close(); } } else { // Avoid setting CompiledAssembly right now since the output might be a netmodule results.PathToAssembly = options.OutputAssembly; } } else { results.CompiledAssembly = null; } return(results); }