private CompilerResults CompileFromFileBatch (CompilerParameters options, string[] fileNames)
{
if (null == options)
throw new ArgumentNullException("options");
if (null == fileNames)
throw new ArgumentNullException("fileNames");
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
}
#if NET_2_0
mcsOutput = new StringCollection ();
mcsOutMutex = new Mutex ();
#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);
}
mcs.StartInfo.CreateNoWindow=true;
mcs.StartInfo.UseShellExecute=false;
mcs.StartInfo.RedirectStandardOutput=true;
mcs.StartInfo.RedirectStandardError=true;
#if NET_2_0
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;
}
try {
#if NET_2_0
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);
if (!error.IsWarning)
loadIt = false;
}
}
if (sc.Count > 0) {
sc.Insert (0, mcs.StartInfo.FileName + " " + mcs.StartInfo.Arguments + Environment.NewLine);
results.Output = sc;
}
if (loadIt) {
if (!File.Exists (options.OutputAssembly)) {
StringBuilder sb = new StringBuilder ();
foreach (string s in sc)
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, options.Evidence);
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;
}