static CSharpCodeCompiler ()
{
if (Path.DirectorySeparatorChar == '\\') {
- // FIXME: right now we use "fixed" version 1.0
- // mcs at any time.
PropertyInfo gac = typeof (Environment).GetProperty ("GacPath", BindingFlags.Static|BindingFlags.NonPublic);
MethodInfo get_gac = gac.GetGetMethod (true);
string p = Path.GetDirectoryName (
Path.GetDirectoryName (
Path.GetDirectoryName (p)),
"bin\\mono.exe");
+#if NET_2_0
+ windowsMcsPath =
+ Path.Combine (p, "2.0\\gmcs.exe");
+#else
windowsMcsPath =
Path.Combine (p, "1.0\\mcs.exe");
+#endif
}
}
//
// Methods
//
- [MonoTODO]
- public CompilerResults CompileAssemblyFromDom (
- CompilerParameters options,CodeCompileUnit e)
+ public CompilerResults CompileAssemblyFromDom (CompilerParameters options, CodeCompileUnit e)
{
- return CompileAssemblyFromDomBatch(options,new CodeCompileUnit[]{e});
+ return CompileAssemblyFromDomBatch (options, new CodeCompileUnit[] { e });
}
- public CompilerResults CompileAssemblyFromDomBatch (
- CompilerParameters options,CodeCompileUnit[] ea)
- {
- string[] fileNames=new string[ea.Length];
- int i=0;
- if (options == null)
- options = new CompilerParameters ();
-
- StringCollection assemblies = options.ReferencedAssemblies;
- foreach (CodeCompileUnit e in ea) {
- fileNames [i] = GetTempFileNameWithExtension (options.TempFiles, i.ToString () + ".cs");
- FileStream f=new FileStream(fileNames[i],FileMode.OpenOrCreate);
- StreamWriter s=new StreamWriter(f, Encoding.UTF8);
- if (e.ReferencedAssemblies != null) {
- foreach (string str in e.ReferencedAssemblies) {
- if (!assemblies.Contains (str))
- assemblies.Add (str);
- }
- }
+ public CompilerResults CompileAssemblyFromDomBatch (CompilerParameters options, CodeCompileUnit[] ea)
+ {
+ if (options == null) {
+ throw new ArgumentNullException ("options");
+ }
- ((ICodeGenerator)this).GenerateCodeFromCompileUnit (e, s, new CodeGeneratorOptions());
- s.Close();
- f.Close();
- i++;
+ try {
+ return CompileFromDomBatch (options, ea);
+ } finally {
+ options.TempFiles.Delete ();
}
- return CompileAssemblyFromFileBatch (options, fileNames);
}
-
- public CompilerResults CompileAssemblyFromFile (
- CompilerParameters options,string fileName)
+
+ public CompilerResults CompileAssemblyFromFile (CompilerParameters options, string fileName)
{
- return CompileAssemblyFromFileBatch (options, new string []{fileName});
+ return CompileAssemblyFromFileBatch (options, new string[] { fileName });
}
public CompilerResults CompileAssemblyFromFileBatch (CompilerParameters options, string[] fileNames)
+ {
+ if (options == null) {
+ throw new ArgumentNullException ("options");
+ }
+
+ try {
+ return CompileFromFileBatch (options, fileNames);
+ } finally {
+ options.TempFiles.Delete ();
+ }
+ }
+
+ public CompilerResults CompileAssemblyFromSource (CompilerParameters options, string source)
+ {
+ return CompileAssemblyFromSourceBatch (options, new string[] { source });
+ }
+
+ public CompilerResults CompileAssemblyFromSourceBatch (CompilerParameters options, string[] sources)
+ {
+ if (options == null) {
+ throw new ArgumentNullException ("options");
+ }
+
+ try {
+ return CompileFromSourceBatch (options, sources);
+ } finally {
+ options.TempFiles.Delete ();
+ }
+ }
+
+ private CompilerResults CompileFromFileBatch (CompilerParameters options, string[] fileNames)
{
if (null == options)
throw new ArgumentNullException("options");
// FIXME: these lines had better be platform independent.
if (Path.DirectorySeparatorChar == '\\') {
mcs.StartInfo.FileName = windowsMonoPath;
- mcs.StartInfo.Arguments = windowsMcsPath + ' ' + BuildArgs (options, fileNames);
- }
- else {
+ mcs.StartInfo.Arguments = "\"" + windowsMcsPath + "\" " + BuildArgs (options, fileNames);
+ } else {
+#if NET_2_0
+ // FIXME: This is a temporary hack to make code genaration work in 2.0
+ mcs.StartInfo.FileName="gmcs";
+#else
mcs.StartInfo.FileName="mcs";
+#endif
mcs.StartInfo.Arguments=BuildArgs(options,fileNames);
}
mcs.StartInfo.CreateNoWindow=true;
mcs.StartInfo.UseShellExecute=false;
mcs.StartInfo.RedirectStandardOutput=true;
+ mcs.StartInfo.RedirectStandardError=true;
try {
mcs.Start();
- mcs_output=mcs.StandardOutput.ReadToEnd();
+ // If there are a few kB in stdout, we might lock
+ mcs_output=mcs.StandardError.ReadToEnd();
+ mcs.StandardOutput.ReadToEnd ();
mcs.WaitForExit();
- } finally {
results.NativeCompilerReturnValue = mcs.ExitCode;
+ } finally {
mcs.Close();
}
mcs_output_lines=mcs_output.Split(
if (!error.IsWarning) loadIt=false;
}
}
- if (loadIt)
- results.CompiledAssembly=Assembly.LoadFrom(options.OutputAssembly);
- else
- results.CompiledAssembly=null;
+ if (loadIt) {
+ 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 {
+ results.CompiledAssembly = Assembly.LoadFrom(options.OutputAssembly);
+ results.PathToAssembly = options.OutputAssembly;
+ }
+ } else {
+ results.CompiledAssembly = null;
+ }
return results;
}
- public CompilerResults CompileAssemblyFromSource (
- CompilerParameters options,string source)
- {
- return CompileAssemblyFromSourceBatch(options,new string[]{source});
- }
- public CompilerResults CompileAssemblyFromSourceBatch (
- CompilerParameters options,string[] sources)
- {
- string[] fileNames=new string[sources.Length];
- int i=0;
- foreach (string source in sources) {
- fileNames [i] = GetTempFileNameWithExtension (options.TempFiles, i.ToString () + ".cs");
- FileStream f=new FileStream(fileNames[i],FileMode.OpenOrCreate);
- StreamWriter s=new StreamWriter(f);
- s.Write(source);
- s.Close();
- f.Close();
- i++;
- }
- return CompileAssemblyFromFileBatch (options, fileNames);
- }
- private static string BuildArgs(
- CompilerParameters options,string[] fileNames)
+
+ private static string BuildArgs(CompilerParameters options,string[] fileNames)
{
StringBuilder args=new StringBuilder();
if (options.GenerateExecutable)
- args.AppendFormat("/target:exe ");
+ args.Append("/target:exe ");
else
- args.AppendFormat("/target:library ");
+ args.Append("/target:library ");
+
+ if (options.Win32Resource != null)
+ args.AppendFormat("/win32res:\"{0}\" ",
+ options.Win32Resource);
+
if (options.IncludeDebugInformation)
- args.AppendFormat("/debug ");
+ args.Append("/debug+ /optimize- ");
+ else
+ args.Append("/debug- /optimize+ ");
+
if (options.TreatWarningsAsErrors)
- args.AppendFormat("/warnaserror ");
+ args.Append("/warnaserror ");
- if (options.WarningLevel != -1)
+ if (options.WarningLevel >= 0)
args.AppendFormat ("/warn:{0} ", options.WarningLevel);
if (options.OutputAssembly==null)
- options.OutputAssembly = GetTempFileNameWithExtension (options.TempFiles, "dll");
+ options.OutputAssembly = GetTempFileNameWithExtension (options.TempFiles, "dll", !options.GenerateInMemory);
args.AppendFormat("/out:\"{0}\" ",options.OutputAssembly);
+
if (null != options.ReferencedAssemblies)
{
foreach (string import in options.ReferencedAssemblies)
args.AppendFormat("/r:\"{0}\" ",import);
}
+
+ if (options.CompilerOptions != null) {
+ args.Append (options.CompilerOptions);
+ args.Append (" ");
+ }
args.Append (" -- ");
foreach (string source in fileNames)
}
private static CompilerError CreateErrorFromString(string error_string)
{
- // When IncludeDebugInformation is true, prevents the debug symbols stats from braeking this.
- if (error_string.StartsWith ("WROTE SYMFILE") || error_string.StartsWith ("OffsetTable"))
+#if NET_2_0
+ if (error_string.StartsWith ("BETA"))
+ return null;
+#endif
+ if (error_string == null || error_string == "")
return null;
CompilerError error=new CompilerError();
- Regex reg = new Regex (@"^(\s*(?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)\s+)*(?<level>\w+)\s*(?<number>.*):\s(?<message>.*)",
+ Regex reg = new Regex (@"^(\s*(?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)(:)?\s+)*(?<level>\w+)\s*(?<number>.*):\s(?<message>.*)",
RegexOptions.Compiled | RegexOptions.ExplicitCapture);
Match match=reg.Match(error_string);
if (!match.Success) return null;
error.Line=Int32.Parse(match.Result("${line}"));
if (String.Empty != match.Result("${column}"))
error.Column=Int32.Parse(match.Result("${column}"));
- if (match.Result("${level}")=="warning")
- error.IsWarning=true;
+
+ string level = match.Result ("${level}");
+ if (level == "warning")
+ error.IsWarning = true;
+ else if (level != "error")
+ return null; // error CS8028 will confuse the regex.
+
error.ErrorNumber=match.Result("${number}");
error.ErrorText=match.Result("${message}");
return error;
}
- static string GetTempFileNameWithExtension (TempFileCollection temp_files, string extension)
+ private static string GetTempFileNameWithExtension (TempFileCollection temp_files, string extension, bool keepFile)
+ {
+ return temp_files.AddExtension (extension, keepFile);
+ }
+
+ private static string GetTempFileNameWithExtension (TempFileCollection temp_files, string extension)
{
return temp_files.AddExtension (extension);
}
+
+ private CompilerResults CompileFromDomBatch (CompilerParameters options, CodeCompileUnit[] ea)
+ {
+ if (options == null) {
+ throw new ArgumentNullException ("options");
+ }
+
+ if (ea == null) {
+ throw new ArgumentNullException ("ea");
+ }
+
+ string[] fileNames = new string[ea.Length];
+ StringCollection assemblies = options.ReferencedAssemblies;
+
+ for (int i = 0; i < ea.Length; i++) {
+ CodeCompileUnit compileUnit = ea[i];
+ fileNames[i] = GetTempFileNameWithExtension (options.TempFiles, i + ".cs");
+ FileStream f = new FileStream (fileNames[i], FileMode.OpenOrCreate);
+ StreamWriter s = new StreamWriter (f, Encoding.UTF8);
+ if (compileUnit.ReferencedAssemblies != null) {
+ foreach (string str in compileUnit.ReferencedAssemblies) {
+ if (!assemblies.Contains (str))
+ assemblies.Add (str);
+ }
+ }
+
+ ((ICodeGenerator) this).GenerateCodeFromCompileUnit (compileUnit, s, new CodeGeneratorOptions ());
+ s.Close ();
+ f.Close ();
+ }
+ return CompileAssemblyFromFileBatch (options, fileNames);
+ }
+
+ private CompilerResults CompileFromSourceBatch (CompilerParameters options, string[] sources)
+ {
+ if (options == null) {
+ throw new ArgumentNullException ("options");
+ }
+
+ if (sources == null) {
+ throw new ArgumentNullException ("sources");
+ }
+
+ string[] fileNames = new string[sources.Length];
+
+ for (int i = 0; i < sources.Length; i++) {
+ fileNames[i] = GetTempFileNameWithExtension (options.TempFiles, i + ".cs");
+ FileStream f = new FileStream (fileNames[i], FileMode.OpenOrCreate);
+ using (StreamWriter s = new StreamWriter (f, Encoding.UTF8)) {
+ s.Write (sources[i]);
+ s.Close ();
+ }
+ f.Close ();
+ }
+ return CompileFromFileBatch (options, fileNames);
+ }
}
}