* Makefile.am:
[monodevelop.git] / extras / JavaBinding / IKVMCompilerManager.cs
blob414fd43a734bbae7f2f6a24dbea097828205d492
1 //
2 // IKVMCompilerManager.cs
3 //
4 // Author:
5 // Mike Krüger <mkrueger@novell.com>
6 //
7 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System;
30 using System.CodeDom.Compiler;
31 using System.Diagnostics;
32 using System.IO;
33 using System.Text;
35 using MonoDevelop.Core;
36 using MonoDevelop.Core.Execution;
37 using MonoDevelop.Core.ProgressMonitoring;
38 using MonoDevelop.Projects;
40 namespace JavaBinding
42 public static class IKVMCompilerManager
44 static string GenerateOptionString (DotNetProjectConfiguration configuration)
46 JavaCompilerParameters parameters = (configuration.CompilationParameters as JavaCompilerParameters) ?? new JavaCompilerParameters ();
47 StringBuilder result = new StringBuilder ();
48 result.Append (configuration.DebugMode ? " -g " : " -g:none ");
49 if (parameters.Optimize)
50 result.Append (" -O ");
51 if (parameters.Deprecation)
52 result.Append (" -deprecation ");
53 if (parameters.GenWarnings)
54 result.Append (" -nowarn ");
55 result.Append (" -encoding utf8 ");
56 return result.ToString ();
59 public static BuildResult Compile (ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, IProgressMonitor monitor)
61 JavaCompilerParameters parameters = (configuration.CompilationParameters as JavaCompilerParameters) ?? new JavaCompilerParameters ();
62 string outdir = configuration.OutputDirectory;
63 string options = GenerateOptionString (configuration);
64 string compiler = parameters.CompilerPath;
65 if (String.IsNullOrEmpty (compiler))
66 compiler = "javac";
68 StringBuilder files = new StringBuilder ();
69 foreach (ProjectFile finfo in projectItems.GetAll<ProjectFile> ()) {
70 if (finfo.Subtype != Subtype.Directory && finfo.BuildAction == BuildAction.Compile) {
71 files.Append (" \"");
72 files.Append (finfo.Name);
73 files.Append ("\"");
77 StringBuilder classpath = new StringBuilder (parameters.ClassPath);
78 AppendClasspath (classpath, GenerateReferenceStubs (monitor, configuration, parameters, projectItems));
79 AppendClasspath (classpath, GenerateReferenceStub (monitor, configuration, new ProjectReference(ReferenceType.Gac, "mscorlib")));
81 StringBuilder args = new StringBuilder ();
82 args.Append (options.ToString ());
83 if (parameters.Compiler == JavaCompiler.Gcj)
84 args.Append ("-C ");
85 if (classpath.Length != 0) {
86 args.Append (" -classpath ");
87 args.Append (classpath.ToString ());
89 args.Append (files.ToString ());
90 args.Append (" -d ");
91 args.Append (outdir);
93 CompilerResults results = new CompilerResults (new TempFileCollection ());
94 StringWriter output = new StringWriter ();
95 StringWriter error = new StringWriter ();
97 bool success = Compile (monitor, compiler, args.ToString (), configuration, parameters, output, error);
98 ParseJavaOutput (parameters.Compiler, error.ToString(), results);
100 if (success) {
101 output = new StringWriter ();
102 error = new StringWriter ();
103 CompileToAssembly (monitor, configuration, parameters, projectItems, output, error);
104 ParseIkvmOutput (parameters.Compiler, error.ToString(), results);
107 return new BuildResult (results, "");
110 static void AppendClasspath (StringBuilder path, string jar)
112 if (path.Length > 0)
113 path.Append (":");
114 path.Append (jar);
117 static string GenerateReferenceStubs (IProgressMonitor monitor, DotNetProjectConfiguration configuration, JavaCompilerParameters compilerparameters, ProjectItemCollection projectItems)
119 StringBuilder result = new StringBuilder ();
120 foreach (ProjectReference reference in projectItems.GetAll<ProjectReference> ()) {
121 AppendClasspath (result, GenerateReferenceStub (monitor, configuration, reference));
123 return result.ToString ();
126 static string GenerateReferenceStub (IProgressMonitor monitor,DotNetProjectConfiguration configuration, ProjectReference reference)
128 StringBuilder result = new StringBuilder ();
129 foreach (string fileName in reference.GetReferencedFileNames (configuration.Id)) {
130 string name = Path.GetFileNameWithoutExtension (Path.GetFileName (fileName));
131 string outputName = Path.Combine (configuration.OutputDirectory, name + ".jar");
132 if (!System.IO.File.Exists (outputName)) {
133 monitor.Log.WriteLine (String.Format (GettextCatalog.GetString ("Generating {0} reference stub ..."), name));
134 ProcessWrapper p = Runtime.ProcessService.StartProcess ("ikvmstub", "\"" + fileName + "\"", configuration.OutputDirectory, monitor.Log, monitor.Log, null);
135 p.WaitForExit ();
136 if (p.ExitCode != 0) {
137 monitor.ReportError ("Stub generation failed.", null);
138 if (File.Exists (outputName)) {
139 try {
140 File.Delete (outputName);
141 } catch {
142 // Ignore
147 AppendClasspath (result, outputName);
149 return result.ToString ();
151 static string TargetToString (CompileTarget target)
153 switch (target) {
154 case CompileTarget.WinExe:
155 return "winexe";
156 case CompileTarget.Library:
157 return "library";
159 return "exe";
162 static void CompileToAssembly (IProgressMonitor monitor, DotNetProjectConfiguration configuration, JavaCompilerParameters compilerparameters, ProjectItemCollection projectItems, TextWriter output, TextWriter error)
164 monitor.Log.WriteLine (GettextCatalog.GetString ("Generating assembly ..."));
166 LogTextWriter chainedError = new LogTextWriter ();
167 chainedError.ChainWriter (monitor.Log);
168 chainedError.ChainWriter (error);
170 LogTextWriter chainedOutput = new LogTextWriter ();
171 chainedOutput.ChainWriter (monitor.Log);
172 chainedOutput.ChainWriter (output);
174 string outdir = configuration.OutputDirectory;
175 string outclass = Path.Combine (outdir, configuration.OutputAssembly + ".class");
176 string asm = Path.GetFileNameWithoutExtension (outclass);
178 StringBuilder args = new StringBuilder ("*.class ");
180 args.Append ("-assembly:"); args.Append (asm);
181 args.Append (" -target:"); args.Append (TargetToString (configuration.CompileTarget));
182 if (configuration.DebugMode)
183 args.Append (" -debug");
184 args.Append (" -srcpath:"); args.Append (configuration.SourceDirectory);
186 foreach (ProjectReference lib in projectItems.GetAll<ProjectReference> ()) {
187 foreach (string fileName in lib.GetReferencedFileNames (configuration.Id)) {
188 args.Append (" -r:"); args.Append (fileName);
192 foreach (string fileName in new ProjectReference(ReferenceType.Gac, "mscorlib").GetReferencedFileNames (configuration.Id)) {
193 args.Append (" -r:"); args.Append (fileName);
196 Process process = Runtime.ProcessService.StartProcess ("ikvmc", args.ToString (), configuration.OutputDirectory, chainedOutput, chainedError, null);
197 process.WaitForExit ();
200 static bool Compile (IProgressMonitor monitor, string compiler, string args, DotNetProjectConfiguration configuration, JavaCompilerParameters compilerparameters, TextWriter output, TextWriter error)
202 LogTextWriter chainedError = new LogTextWriter ();
203 chainedError.ChainWriter (monitor.Log);
204 chainedError.ChainWriter (error);
206 LogTextWriter chainedOutput = new LogTextWriter ();
207 chainedOutput.ChainWriter (monitor.Log);
208 chainedOutput.ChainWriter (output);
210 monitor.Log.WriteLine (GettextCatalog.GetString ("Compiling Java source code ..."));
212 Process process = Runtime.ProcessService.StartProcess (compiler, args, null, chainedOutput, chainedError, null);
213 process.WaitForExit ();
214 return process.ExitCode == 0;
217 static void ParseJavaOutput (JavaCompiler compiler, string errorStr, CompilerResults cr)
219 TextReader reader = new StringReader (errorStr);
220 string line;
221 while ((line = reader.ReadLine ()) != null) {
222 CompilerError error = CreateJavaErrorFromString (compiler, line);
223 if (error != null)
224 cr.Errors.Add (error);
226 reader.Close ();
229 private static CompilerError CreateJavaErrorFromString (JavaCompiler compiler, string next)
231 CompilerError result = new CompilerError ();
233 int errorCol = 0;
234 string col = next.Trim ();
235 if (col.Length == 1 && col == "^")
236 errorCol = next.IndexOf ("^");
238 int index1 = next.IndexOf (".java:");
239 if (index1 < 0)
240 return null;
242 string s2 = next.Substring (index1 + 6);
243 int index2 = s2.IndexOf (":");
244 int line = Int32.Parse (next.Substring (index1 + 6, index2));
246 result.Column = errorCol;
247 result.Line = line;
248 result.ErrorText = next.Substring (index1 + index2 + 7);
249 result.FileName = Path.GetFullPath (next.Substring (0, index1) + ".java");
250 return result;
253 static void ParseIkvmOutput (JavaCompiler compiler, string errorStr, CompilerResults cr)
255 TextReader reader = new StringReader (errorStr);
256 string line;
257 while ((line = reader.ReadLine ()) != null) {
258 CompilerError error = CreateIkvmErrorFromString (line);
259 if (error != null)
260 cr.Errors.Add (error);
262 reader.Close ();
265 static CompilerError CreateIkvmErrorFromString (string error)
267 if (error.StartsWith ("Note") || error.StartsWith ("Warning"))
268 return null;
269 string trimmed = error.Trim ();
270 if (trimmed.StartsWith ("(to avoid this warning add"))
271 return null;
273 CompilerError cerror = new CompilerError ();
274 cerror.ErrorText = error;
275 return cerror;