Beispiel #1
0
        // 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
        }
Beispiel #2
0
		/// <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);
        }