X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem%2FMicrosoft.CSharp%2FCSharpCodeCompiler.cs;h=986e2bd47301df983db04f72403409b01d8fd6ec;hb=fe32d6af839d57a65ddc7ad7b7ef968a9a251964;hp=edc8da68872c2f07ed256887de71772f4d8162e6;hpb=b7c17c47e6b3c02192e64175cb5ee0ce7f7dda1b;p=mono.git diff --git a/mcs/class/System/Microsoft.CSharp/CSharpCodeCompiler.cs b/mcs/class/System/Microsoft.CSharp/CSharpCodeCompiler.cs index edc8da68872..986e2bd4730 100644 --- a/mcs/class/System/Microsoft.CSharp/CSharpCodeCompiler.cs +++ b/mcs/class/System/Microsoft.CSharp/CSharpCodeCompiler.cs @@ -50,8 +50,6 @@ namespace Mono.CSharp 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 ( @@ -65,8 +63,13 @@ namespace Mono.CSharp 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 } } @@ -80,48 +83,61 @@ namespace Mono.CSharp // // 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"); @@ -136,21 +152,28 @@ namespace Mono.CSharp // 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( @@ -165,58 +188,62 @@ namespace Mono.CSharp 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) @@ -225,12 +252,15 @@ namespace Mono.CSharp } 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*(?.*)\((?\d*)(,(?\d*))?\)\s+)*(?\w+)\s*(?.*):\s(?.*)", + Regex reg = new Regex (@"^(\s*(?.*)\((?\d*)(,(?\d*))?\)(:)?\s+)*(?\w+)\s*(?.*):\s(?.*)", RegexOptions.Compiled | RegexOptions.ExplicitCapture); Match match=reg.Match(error_string); if (!match.Success) return null; @@ -240,16 +270,82 @@ namespace Mono.CSharp 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); + } } }