2 // IKVMCompilerManager.cs
5 // Mike Krüger <mkrueger@novell.com>
7 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
30 using System
.CodeDom
.Compiler
;
31 using System
.Diagnostics
;
35 using MonoDevelop
.Core
;
36 using MonoDevelop
.Core
.Execution
;
37 using MonoDevelop
.Core
.ProgressMonitoring
;
38 using MonoDevelop
.Projects
;
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
))
68 StringBuilder files
= new StringBuilder ();
69 foreach (ProjectFile finfo
in projectItems
.GetAll
<ProjectFile
> ()) {
70 if (finfo
.Subtype
!= Subtype
.Directory
&& finfo
.BuildAction
== BuildAction
.Compile
) {
72 files
.Append (finfo
.Name
);
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
)
85 if (classpath
.Length
!= 0) {
86 args
.Append (" -classpath ");
87 args
.Append (classpath
.ToString ());
89 args
.Append (files
.ToString ());
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
);
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
)
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);
136 if (p
.ExitCode
!= 0) {
137 monitor
.ReportError ("Stub generation failed.", null);
138 if (File
.Exists (outputName
)) {
140 File
.Delete (outputName
);
147 AppendClasspath (result
, outputName
);
149 return result
.ToString ();
151 static string TargetToString (CompileTarget target
)
154 case CompileTarget
.WinExe
:
156 case CompileTarget
.Library
:
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
);
221 while ((line
= reader
.ReadLine ()) != null) {
222 CompilerError error
= CreateJavaErrorFromString (compiler
, line
);
224 cr
.Errors
.Add (error
);
229 private static CompilerError
CreateJavaErrorFromString (JavaCompiler compiler
, string next
)
231 CompilerError result
= new CompilerError ();
234 string col
= next
.Trim ();
235 if (col
.Length
== 1 && col
== "^")
236 errorCol
= next
.IndexOf ("^");
238 int index1
= next
.IndexOf (".java:");
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
;
248 result
.ErrorText
= next
.Substring (index1
+ index2
+ 7);
249 result
.FileName
= Path
.GetFullPath (next
.Substring (0, index1
) + ".java");
253 static void ParseIkvmOutput (JavaCompiler compiler
, string errorStr
, CompilerResults cr
)
255 TextReader reader
= new StringReader (errorStr
);
257 while ((line
= reader
.ReadLine ()) != null) {
258 CompilerError error
= CreateIkvmErrorFromString (line
);
260 cr
.Errors
.Add (error
);
265 static CompilerError
CreateIkvmErrorFromString (string error
)
267 if (error
.StartsWith ("Note") || error
.StartsWith ("Warning"))
269 string trimmed
= error
.Trim ();
270 if (trimmed
.StartsWith ("(to avoid this warning add"))
273 CompilerError cerror
= new CompilerError ();
274 cerror
.ErrorText
= error
;