Merge pull request #487 from mayerwin/patch-1
[mono.git] / mcs / class / System / Microsoft.CSharp / CSharpCodeCompiler.cs
index b05bb44bc1dc1c4df6453567ccf43c800ed5e6ba..26039bdd79b3de87fccd138b2345b4f809967f16 100644 (file)
@@ -34,6 +34,7 @@ namespace Mono.CSharp
        using System;
        using System.CodeDom;
        using System.CodeDom.Compiler;
+       using System.ComponentModel;
        using System.IO;
        using System.Text;
        using System.Reflection;
@@ -41,21 +42,16 @@ namespace Mono.CSharp
        using System.Collections.Specialized;
        using System.Diagnostics;
        using System.Text.RegularExpressions;
-       
-#if NET_2_0
        using System.Threading;
        using System.Collections.Generic;
-#endif
        
        internal class CSharpCodeCompiler : CSharpCodeGenerator, ICodeCompiler
        {
                static string windowsMcsPath;
                static string windowsMonoPath;
 
-#if NET_2_0
                Mutex mcsOutMutex;
                StringCollection mcsOutput;
-#endif
                
                static CSharpCodeCompiler ()
                {
@@ -81,25 +77,11 @@ namespace Mono.CSharp
                                                "mono\\mono\\mini\\mono.exe");
                                if (!File.Exists (windowsMonoPath))
                                        throw new FileNotFoundException ("Windows mono path not found: " + windowsMonoPath);
-#if NET_2_0
-                               windowsMcsPath =
-                                       Path.Combine (p, "2.0\\gmcs.exe");
-#else
-                               windowsMcsPath =
-                                       Path.Combine (p, "1.0\\mcs.exe");
-#endif
+
+                               windowsMcsPath = Path.Combine (p, "4.5\\mcs.exe");
                                if (!File.Exists (windowsMcsPath))
-#if NET_2_0
-                                       windowsMcsPath = 
-                                               Path.Combine(
-                                                       Path.GetDirectoryName (p),
-                                                       "lib\\net_2_0\\gmcs.exe");
-#else
-                                       windowsMcsPath = 
-                                               Path.Combine(
-                                                       Path.GetDirectoryName (p),
-                                                       "lib\\default\\mcs.exe");
-#endif
+                                       windowsMcsPath = Path.Combine(Path.GetDirectoryName (p), "lib\\build\\mcs.exe");
+                               
                                if (!File.Exists (windowsMcsPath))
                                        throw new FileNotFoundException ("Windows mcs path not found: " + windowsMcsPath);
                        }
@@ -112,12 +94,10 @@ namespace Mono.CSharp
                {
                }
 
-#if NET_2_0
-               public CSharpCodeCompiler (Dictionary <string, string> providerOptions) :
+               public CSharpCodeCompiler (IDictionary <string, string> providerOptions) :
                        base (providerOptions)
                {
                }
-#endif
                
                //
                // Methods
@@ -186,81 +166,95 @@ namespace Mono.CSharp
                        CompilerResults results=new CompilerResults(options.TempFiles);
                        Process mcs=new Process();
 
-#if !NET_2_0
-                       string mcs_output;
-                       string mcs_stdout;
-                       string[] mcsOutput;
-#endif
-                       
                        // FIXME: these lines had better be platform independent.
                        if (Path.DirectorySeparatorChar == '\\') {
                                mcs.StartInfo.FileName = windowsMonoPath;
                                mcs.StartInfo.Arguments = "\"" + windowsMcsPath + "\" " +
-#if NET_2_0
                                        BuildArgs (options, fileNames, ProviderOptions);
-#else
-                                       BuildArgs (options, fileNames);
-#endif
                        } else {
-#if NET_2_0
-                               // FIXME: This is a temporary hack to make code genaration work in 2.0
-                               mcs.StartInfo.FileName="gmcs";
-                               mcs.StartInfo.Arguments=BuildArgs(options, fileNames, ProviderOptions);
-#else
                                mcs.StartInfo.FileName="mcs";
-                               mcs.StartInfo.Arguments=BuildArgs(options, fileNames);
-#endif
+                               mcs.StartInfo.Arguments=BuildArgs(options, fileNames, ProviderOptions);
                        }
 
-#if NET_2_0
                        mcsOutput = new StringCollection ();
                        mcsOutMutex = new Mutex ();
+#if !NET_4_0
+                       /*
+                        * !:. KLUDGE WARNING .:!
+                        *
+                        * When running the 2.0 test suite some assemblies will invoke mcs via
+                        * CodeDOM and the new mcs process will find the MONO_PATH variable in its
+                        * environment pointing to the net_2_0 library which will cause the runtime
+                        * to attempt to load the 2.0 corlib into 4.0 process and thus mcs will
+                        * fail. At the same time, we must not touch MONO_PATH when running outside
+                        * the test suite, thus the kludge.
+                        *
+                        * !:. KLUDGE WARNING .:!
+                        */
+                       if (Environment.GetEnvironmentVariable ("MONO_TESTS_IN_PROGRESS") != null) {
+                               string monoPath = Environment.GetEnvironmentVariable ("MONO_PATH");
+                               if (!String.IsNullOrEmpty (monoPath)) {
+                                       monoPath = monoPath.Replace ("/class/lib/net_2_0", "/class/lib/net_4_0");
+                                       mcs.StartInfo.EnvironmentVariables ["MONO_PATH"] = monoPath;
+                               }
+                       }
 #endif
-                       
+/*                    
+                       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 ["MONO_GC_PARAMS"] = String.Empty;
+
                        mcs.StartInfo.CreateNoWindow=true;
                        mcs.StartInfo.UseShellExecute=false;
                        mcs.StartInfo.RedirectStandardOutput=true;
                        mcs.StartInfo.RedirectStandardError=true;
-#if NET_2_0
-                       mcs.OutputDataReceived += new DataReceivedEventHandler (McsStdoutDataReceived);
                        mcs.ErrorDataReceived += new DataReceivedEventHandler (McsStderrDataReceived);
-#endif
                        
                        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.W32ErrorMessage (exc.NativeErrorCode)));
+                               }
+                               throw;
+                       }
 
-#if NET_2_0
+                       try {
                                mcs.BeginOutputReadLine ();
                                mcs.BeginErrorReadLine ();
-#else
-                               // If there are a few kB in stdout, we might lock
-                               mcs_output=mcs.StandardError.ReadToEnd();
-                               mcs_stdout=mcs.StandardOutput.ReadToEnd ();
-#endif
                                mcs.WaitForExit();
                                
                                results.NativeCompilerReturnValue = mcs.ExitCode;
                        } finally {
-#if NET_2_0
                                mcs.CancelErrorRead ();
                                mcs.CancelOutputRead ();
-#endif
-
                                mcs.Close();
                        }
 
-#if NET_2_0
                        StringCollection sc = mcsOutput;
-#else
-                       mcsOutput = mcs_output.Split (System.Environment.NewLine.ToCharArray ());
-                       StringCollection sc = new StringCollection ();
-#endif
                       
                        bool loadIt=true;
                        foreach (string error_line in mcsOutput) {
-#if !NET_2_0
-                               sc.Add (error_line);
-#endif
                                CompilerError error = CreateErrorFromString (error_line);
                                if (error != null) {
                                        results.Errors.Add (error);
@@ -287,7 +281,7 @@ namespace Mono.CSharp
                                        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, options.Evidence);
+                                               results.CompiledAssembly = Assembly.Load(buffer, null);
                                                fs.Close();
                                        }
                                } else {
@@ -301,25 +295,16 @@ namespace Mono.CSharp
                        return results;
                }
 
-#if NET_2_0
-               void McsStdoutDataReceived (object sender, DataReceivedEventArgs args)
-               {
-                       mcsOutMutex.WaitOne ();
-                       mcsOutput.Add (args.Data);
-                       mcsOutMutex.ReleaseMutex ();
-               }
-
                void McsStderrDataReceived (object sender, DataReceivedEventArgs args)
                {
-                       mcsOutMutex.WaitOne ();
-                       mcsOutput.Add (args.Data);
-                       mcsOutMutex.ReleaseMutex ();
+                       if (args.Data != null) {
+                               mcsOutMutex.WaitOne ();
+                               mcsOutput.Add (args.Data);
+                               mcsOutMutex.ReleaseMutex ();
+                       }
                }               
 
-               private static string BuildArgs(CompilerParameters options,string[] fileNames, Dictionary <string, string> providerOptions)
-#else
-               private static string BuildArgs(CompilerParameters options,string[] fileNames)
-#endif
+               private static string BuildArgs(CompilerParameters options,string[] fileNames, IDictionary <string, string> providerOptions)
                {
                        StringBuilder args=new StringBuilder();
                        if (options.GenerateExecutable)
@@ -327,6 +312,10 @@ namespace Mono.CSharp
                        else
                                args.Append("/target:library ");
 
+                       string privateBinPath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath;
+                       if (privateBinPath != null && privateBinPath.Length > 0)
+                               args.AppendFormat ("/lib:\"{0}\" ", privateBinPath);
+                       
                        if (options.Win32Resource != null)
                                args.AppendFormat("/win32res:\"{0}\" ",
                                        options.Win32Resource);
@@ -361,7 +350,6 @@ namespace Mono.CSharp
                                args.Append (" ");
                        }
 
-#if NET_2_0
                        foreach (string embeddedResource in options.EmbeddedResources) {
                                args.AppendFormat("/resource:\"{0}\" ", embeddedResource);
                        }
@@ -374,14 +362,18 @@ namespace Mono.CSharp
                                string langver;
 
                                if (!providerOptions.TryGetValue ("CompilerVersion", out langver))
+#if NET_4_0
+                                       langver = "3.5";
+#else
                                        langver = "2.0";
+#endif
 
                                if (langver.Length >= 1 && langver [0] == 'v')
                                        langver = langver.Substring (1);
 
                                switch (langver) {
                                        case "2.0":
-                                               args.Append ("/langversion:ISO-2");
+                                               args.Append ("/langversion:ISO-2 ");
                                                break;
 
                                        case "3.5":
@@ -389,6 +381,13 @@ namespace Mono.CSharp
                                                break;
                                }
                        }
+
+#if NET_4_5                    
+                       args.Append("/sdk:4.5");
+#elif NET_4_0
+                       args.Append("/sdk:4");
+#else
+                       args.Append("/sdk:2");
 #endif
 
                        args.Append (" -- ");
@@ -398,10 +397,9 @@ namespace Mono.CSharp
                }
                private static CompilerError CreateErrorFromString(string error_string)
                {
-#if NET_2_0
                        if (error_string.StartsWith ("BETA"))
                                return null;
-#endif
+
                        if (error_string == null || error_string == "")
                                return null;