798bf04c0a360da620f86a31e4328a8211bb128b
[roobuilder] / src / Palete / ValaCompileRequest.vala
1
2
3
4 namespace Palete {
5         public enum ValaCompileRequestType {
6                 PROP_CHANGE,
7                 FILE_CHANGE,
8                 PROJECT,
9                 RUN
10         }
11                 
12         public class ValaCompileRequest  : Object
13         {
14                 ValaCompileRequestType requestType;
15                 
16                 public JsRender.JsRender? file = null;
17                 JsRender.Node? node = null;
18                 JsRender.NodeProp? prop = null;
19                 string alt_code = "";
20                 string tmpfile = "";
21                 Spawn? compiler  = null;
22         ///     ValaCompileQueue? queue = null;
23  
24                 
25         
26                 public Gee.HashMap<string,GLib.ListStore>? errorByType = null;
27                 public Gee.HashMap<string,GLib.ListStore>? errorByFile  = null;
28                         
29         
30                 public ValaCompileRequest (
31                         ValaCompileRequestType requestType,
32                         JsRender.JsRender file ,
33                         JsRender.Node? node,
34                         JsRender.NodeProp? prop,
35                         string alt_code = ""
36                          
37                 ) {
38                         this.requestType = requestType;
39                         this.file = file;
40                         this.node = node;
41                         this.prop = prop;
42                         this.alt_code = alt_code;
43                 }
44                 public bool eq(ValaCompileRequest c) {
45                         var neq = false;
46                         if (this.node == null && c.node == null) {
47                                 neq = true;
48                         } else if (this.node == null || c.node == null) {
49                                 neq = false;
50                         } else {
51                                 neq = this.node.oid == c.node.oid ;
52                         }
53                         
54                         var peq = false;                        
55                         if (this.prop == null && c.prop == null) {
56                                 peq = true;
57                         } else if (this.prop == null || c.prop == null) {
58                                 peq = false;
59                         } else {
60                                 peq = this.prop.name == c.prop.name ;
61                         }
62
63                         
64                         return 
65                                 this.requestType == c.requestType &&
66                                 this.file.path == c.file.path &&
67                                 neq && peq &&
68                                 this.alt_code == c.alt_code;
69                                 
70                                 
71                 
72                 }
73                 public string target()
74                 {
75                         var pr = (Project.Gtk) this.file.project;
76                         return pr.firstBuildModuleWith(this.file);
77                 
78                 }
79                 
80                 string generateTempContents() {
81                 
82                         var oldcode  = "";
83                         var contents = this.alt_code;
84                         if (this.requestType == ValaCompileRequestType.PROP_CHANGE) {
85                                 oldcode  = this.prop.val;
86                                 this.prop.val = this.alt_code;
87                                 contents = this.file.toSourceCode();
88                                 this.prop.val = oldcode;
89                         }
90                         return contents;
91                 }
92                 
93                 
94                 bool generateTempFile() {
95                  
96                         var contents = this.generateTempContents();
97                          
98                         var pr = this.file.project;
99                         
100                         this.tmpfile = pr.path + "/build/tmp-%u.vala".printf( (uint) GLib.get_real_time()) ;
101                         try {
102                                 GLib.FileUtils.set_contents(this.tmpfile,contents);
103                         } catch (GLib.FileError e) {
104                                 GLib.debug("Error creating temp build file %s : %s", tmpfile, e.message);
105                                 return false;
106                         }
107                         return true;
108                 }
109                 
110                 public bool run()
111                 {
112                         //this.queue = queue;
113                         if ( this.target() == "") {
114                                 GLib.debug("missing target");
115                                 this.onCompileFail();
116
117                                 return false;
118                         }
119                         string[] args = {};
120                         args += BuilderApplication._self;
121                         if (this.requestType != ValaCompileRequestType.RUN) {
122                                 args += "--skip-linking";
123                         }
124                         args += "--project";
125                         args += this.file.project.path;
126                         args += "--target";
127                         args +=  this.target();
128                         if  (this.requestType == ValaCompileRequestType.PROP_CHANGE || this.requestType == ValaCompileRequestType.FILE_CHANGE) {
129                                 
130                                 if (!this.generateTempFile()) {
131                                         GLib.debug("failed to make temp file");
132                                         this.onCompileFail();
133                                         return false;
134                                 }
135                                 args += "--add-file";
136                                 args +=  this.tmpfile;
137                                 args += "--skip-file";
138                                 args += this.file.targetName(); // ?? bjs???
139                         }
140                         var pr = (Project.Gtk)(file.project);
141                         try {
142                                 pr.makeProjectSubdir("build");
143                                 this.compiler = new Spawn(pr.path + "/build", args);
144                         } catch (GLib.Error e) {
145                                 GLib.debug("Spawn failed: %s", e.message);
146
147                                 this.onCompileFail();
148                                 return false;
149                         }
150                     this.compiler.output_line.connect(this.onOutput);
151                         this.compiler.complete.connect(this.onCompileComplete);
152                         try {
153                                 this.compiler.run(); 
154                         } catch (GLib.Error e) {
155                                 GLib.debug("Spawn error %s", e.message);
156                                 this.onCompileFail();
157                                 return false;
158                         }
159                         return true; // it's running..
160                 }
161                 void onCompileFail() // only called before we start (assumes spinner has nto started etc..
162                 {
163                         this.compiler = null;
164                         this.deleteTemp();
165                 }
166                 
167                 public void cancel() {
168                         if (this.compiler != null && this.compiler.pid > 0) {
169                                 Posix.kill(this.compiler.pid, 9);
170                         }
171                         this.compiler = null;
172                         this.deleteTemp();
173                 }
174                 
175                 public void deleteTemp()
176                 {
177                          if (this.tmpfile == "") {
178                                 return;
179                         }
180                         if (GLib.FileUtils.test(this.tmpfile, GLib.FileTest.EXISTS)) {
181                                 GLib.FileUtils.unlink(this.tmpfile);
182                         }
183                         var cf = this.tmpfile.substring(0, this.tmpfile.length-4) + "c";
184                         GLib.debug("try remove %s",cf);
185                         if (GLib.FileUtils.test(cf, GLib.FileTest.EXISTS)) {
186                                 GLib.FileUtils.unlink(cf);
187                         }
188                         var ccf = GLib.Path.get_dirname(cf) + "/build/" + GLib.Path.get_basename(cf);
189                         GLib.debug("try remove %s",ccf);
190                         if (GLib.FileUtils.test(ccf, GLib.FileTest.EXISTS)) {
191                                 GLib.FileUtils.unlink(ccf);
192                         }
193                         this.tmpfile = "";
194                 }
195                 public void onCompileComplete(int res, string output, string stderr) 
196                 {
197                         this.deleteTemp();
198                         this.compiler.isZombie();
199                         GLib.debug("compile got %s", output);
200                         if (output == "") {
201                 BuilderApplication.showSpinner("face-sad", "compile failed - no error message?");
202                                 return;
203                         }
204                         if (this.requestType == ValaCompileRequestType.RUN) {
205                 BuilderApplication.showSpinner("");
206                                 this.execResult();
207                                 return;
208                         }
209                         
210                         // below is not used anymore - as we dont use this
211                         try { 
212                                 //GLib.debug("GOT output %s", output);
213                                 
214                                 var pa = new Json.Parser();
215                                 pa.load_from_data(output);
216                                 var node = pa.get_root();
217
218                                 if (node.get_node_type () != Json.NodeType.OBJECT) {
219                                         BuilderApplication.showSpinner("");
220                                         return;
221                                 }
222                                 var ret = node.get_object ();   
223                                 //CompileError.parseCompileResults(this,ret);
224                                         BuilderApplication.showSpinner("");
225                                 
226                         
227                                 
228                                 
229                                 
230                         } catch (GLib.Error e) {
231                                 GLib.debug("parsing output got error %s", e.message);
232                                 BuilderApplication.showSpinner("");
233                                 return;
234                                 
235                         }
236                 }
237                  
238                 public void onOutput(string line)
239                 {
240                         // pass it to UI?
241                         
242                 }
243                 public int totalErrors(string type, JsRender.JsRender? file=null) 
244                 {
245                         var ar = this.errorByType.get(type);
246                         if (ar == null) {
247                                 GLib.debug("by type has no eroros %s", type);
248                                 return 0;
249                         }
250                         
251                         
252                         var ret =0;
253                         
254                         for(var i =0 ;i< ar.get_n_items();i++) {
255                                 var ce = (CompileError) ar.get_item(i);
256                                 if (file == null) {
257                                         ret += (int)ce.lines.get_n_items();
258                                         GLib.debug("got lines type has no eroros %s", type);
259                                         continue;
260                                 }
261                                 
262                                 
263                                 if (ce.file.path == file.path) {
264                                         ret += (int)ce.lines.get_n_items();
265                                 }
266                         }
267                         return ret;
268                 }
269                 
270                 public void runJavascript( )
271                 {
272                         //this.queue = queue;
273                  
274                         var contents = this.alt_code == "" ? this.file.toSourceCode() : this.generateTempContents();
275                         
276                         Javascript.singleton().validate(contents, this.file );
277                          
278                          
279                         BuilderApplication.showSpinner("");
280                         BuilderApplication.updateCompileResults();
281                         
282                         //this.queue.onCompileComplete(this);
283                                 
284                          
285                   // see pack file (from palete/palete..palete_palete_javascriptHasCompressionErrors.)
286                   
287                 }
288                 public void killChildren(int pid)
289                 {
290                         if (pid < 1) {
291                                 return;
292                         }
293                         var cn = "/proc/%d/task/%d/children".printf(pid,pid);
294                         if (!FileUtils.test(cn, GLib.FileTest.EXISTS)) {
295                                 GLib.debug("%s doesnt exist - killing %d", cn, pid);
296                                  Posix.kill(pid, 9);
297                                 return;
298                         }
299                         string cpids = "";
300                         try {
301                                 FileUtils.get_contents(cn, out cpids);
302                         
303
304                                 if (cpids.length > 0) {
305                                         this.killChildren(int.parse(cpids));
306                                 }
307
308                         } catch (GLib.FileError e) {
309                                 // skip
310                         }
311                         GLib.debug("killing %d", pid);  
312                         //Posix.kill(pid, 9);
313                 }
314                 
315                 public int terminal_pid = 0;
316                 public void execResult()
317                 {
318                                 
319                         this.killChildren(this.terminal_pid);
320                         this.terminal_pid = 0;
321                           
322                         var exe = this.target();
323                         var pr = (Project.Gtk) this.file.project;
324                         var cg =  pr.compilegroups.get(exe);
325                         
326                         var exbin = pr.path + "/build/" + exe;
327                         if (!GLib.FileUtils.test(exbin, GLib.FileTest.EXISTS)) {
328                                 GLib.debug("Missing output file: %s\n",exbin);
329                                 return;
330                         }
331                         var gdb_cfg = pr.path + "/build/.gdb-script";
332                         if (!GLib.FileUtils.test(gdb_cfg, GLib.FileTest.EXISTS)) {
333                                 pr.writeFile("build/.gdb-script", "set debuginfod enabled off\nr");
334                         }
335                          
336                         
337                         string[] args = "/usr/bin/gnome-terminal --disable-factory --wait -- /usr/bin/gdb -x".split(" ");
338
339                         args+= gdb_cfg;
340  
341                         args += exbin;
342                         if (cg.execute_args.length > 0) {
343                                 args+= "--args";
344                                 var aa = cg.execute_args.split(" ");
345                                 for (var i =0; i < aa.length; i++) {
346                                         args += aa[i];
347                                 }
348                         }
349
350                   
351                     
352                     // should be home directory...
353                     
354                     
355                     try {
356                     
357                         var exec = new Spawn(pr.path , args);
358                         exec.env = GLib.Environ.get();
359                          
360                         exec.detach = true;
361                                 exec.run(); 
362
363                                 this.terminal_pid = exec.pid;
364                                 GLib.debug("Child PID = %d", this.terminal_pid);
365                                 
366                     } catch(GLib.Error e) {
367                                 GLib.debug("Failed to spawn: %s", e.message);
368                                 return;
369                         }
370                         
371                 }
372                 
373         } 
374                 
375                 
376                 
377 }
378
379