gwenhywfar  5.11.1beta
buildctx_run.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Mon Feb 08 2021
3  copyright : (C) 2021 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * Please see toplevel file COPYING for license details *
8  ***************************************************************************/
9 
10 #ifdef HAVE_CONFIG_H
11 # include <config.h>
12 #endif
13 
14 #define DISABLE_DEBUGLOG
15 
16 
17 #include "gwenbuild/buildctx/buildctx_p.h"
21 
22 #include <gwenhywfar/debug.h>
23 #include <gwenhywfar/text.h>
24 #include <gwenhywfar/directory.h>
25 
26 #include <unistd.h>
27 #include <ctype.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <errno.h>
31 #include <string.h>
32 
33 
34 
35 #define GWB_BUILDCTX_PROCESS_WAIT_TIMEOUT 10.0
36 
37 
38 static void _setupCommands(GWB_BUILD_CONTEXT *bctx, int forPrepareCommands);
39 static void _createCommandQueues(GWB_BUILD_CONTEXT *bctx);
40 static int _checkWaitingQueue(GWB_BUILD_CONTEXT *bctx, int maxStartAllowed);
41 static int _startCommand(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slOutFiles);
42 static int _checkRunningQueue(GWB_BUILD_CONTEXT *bctx);
43 static void _signalJobFinished(GWB_BUILD_CMD *bcmd);
44 static void _decBlockingFilesInWaitingBuildCommands(GWB_BUILD_CMD_LIST2 *waitingCommands);
46 
47 static int _waitForRunningJobs(GWB_BUILD_CONTEXT *bctx);
48 static void _abortAllCommands(GWB_BUILD_CONTEXT *bctx);
49 static void _abortCommandsInQueue(GWB_BUILD_CMD_LIST2 *cmdList);
50 
51 static int _needRunCurrentCommand(GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles);
52 static void _finishCurrentCommand(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *currentCommand);
53 
54 static int _checkDependencies(GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *subCmd, const char *firstOutFileName);
55 static int _checkDatesOfFileAgainstList(const char *fileName, const GWEN_STRINGLIST *sl);
56 
57 static int _inFilesNewerThanOutFiles(const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles);
58 static time_t _getHighestModificationTime(const GWEN_STRINGLIST *slFiles);
59 static time_t _getLowestModificationTime(const GWEN_STRINGLIST *slFiles);
60 static void _unlinkFilesInStringList(const GWEN_STRINGLIST *slFiles);
61 
62 
63 
64 
65 
66 int GWB_BuildCtx_Run(GWB_BUILD_CONTEXT *bctx, int maxConcurrentJobs, int usePrepareCommands, const char *builderName)
67 {
68  int rv;
69  int waitingJobs;
70  int runningJobs;
71 
73  _setupCommands(bctx, usePrepareCommands);
75  rv=GWB_BuildCtx_FillWaitingQueue(bctx, builderName);
76  if (rv<0) {
77  DBG_INFO(NULL, "here (%d)", rv);
78  return rv;
79  }
80 
81  if (GWB_BuildCmd_List2_GetSize(bctx->waitingQueue)==0) {
82  fprintf(stdout, "Nothing to do.\n");
83  return 0;
84  }
85 
86  waitingJobs=GWB_BuildCmd_List2_GetSize(bctx->waitingQueue);
87  runningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
88  while(waitingJobs+runningJobs) {
89  int startedCommands;
90  int changedCommands;
91 
92  startedCommands=_checkWaitingQueue(bctx, maxConcurrentJobs-runningJobs);
93  if (startedCommands<0) {
94  _waitForRunningJobs(bctx);
95  _abortAllCommands(bctx);
96  return GWEN_ERROR_GENERIC;
97  }
98 
99  changedCommands=_checkRunningQueue(bctx);
100  if (changedCommands<0) { /* error */
101  _waitForRunningJobs(bctx);
102  _abortAllCommands(bctx);
103  return GWEN_ERROR_GENERIC;
104  }
105 
106  if (startedCommands==0 && changedCommands==0) {
107  if (runningJobs==0) {
108  DBG_ERROR(NULL, "ERROR: No running jobs and none could be started, maybe circular dependencies?");
109  _waitForRunningJobs(bctx);
110  _abortAllCommands(bctx);
111  return GWEN_ERROR_GENERIC;
112  }
113  DBG_DEBUG(NULL, "Nothing changed, sleeping...");
114  sleep(3);
115  }
116 
117  waitingJobs=GWB_BuildCmd_List2_GetSize(bctx->waitingQueue);
118  runningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
119  } /* while */
120 
121  GWB_BuildCmd_List2_free(bctx->waitingQueue);
122  bctx->waitingQueue=NULL;
123  GWB_BuildCmd_List2_free(bctx->runningQueue);
124  bctx->runningQueue=NULL;
125  GWB_BuildCmd_List2_free(bctx->finishedQueue);
126  bctx->finishedQueue=NULL;
127 
128  return 0;
129 }
130 
131 
132 
134 {
135  int numRunningJobs;
136  time_t startTime;
137 
138  startTime=time(0);
139  numRunningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
140  if (numRunningJobs)
141  fprintf(stderr, "NOTICE: Waiting for %d jobs.\n", numRunningJobs);
142  while(numRunningJobs) {
143  int numChangedCommands;
144  time_t currentTime;
145 
146  numChangedCommands=_checkRunningQueue(bctx);
147  if (numChangedCommands<0) { /* error */
148  DBG_INFO(NULL, "Some jobs had errors");
149  }
150  numRunningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
151 
152  if (numRunningJobs>0) {
153  double delta;
154 
155  currentTime=time(0);
156  delta=difftime(currentTime, startTime);
158  DBG_ERROR(NULL, "%d jobs still running after %f.1 seconds, aborting", numRunningJobs, delta);
159  return GWEN_ERROR_TIMEOUT;
160  }
161  DBG_DEBUG(NULL, "Jobs still running, sleeping...");
162  sleep(1);
163  }
164 
165  } /* while */
166 
167  return 0;
168 }
169 
170 
171 
173 {
174  _abortCommandsInQueue(bctx->waitingQueue);
175  GWB_BuildCmd_List2_free(bctx->waitingQueue);
176  bctx->waitingQueue=NULL;
177 
178  _abortCommandsInQueue(bctx->runningQueue);
179  GWB_BuildCmd_List2_free(bctx->runningQueue);
180  bctx->runningQueue=NULL;
181 
182  _abortCommandsInQueue(bctx->finishedQueue);
183  GWB_BuildCmd_List2_free(bctx->finishedQueue);
184  bctx->finishedQueue=NULL;
185 }
186 
187 
188 
189 void _abortCommandsInQueue(GWB_BUILD_CMD_LIST2 *cmdList)
190 {
191  GWB_BUILD_CMD *bcmd;
192 
193  while( (bcmd=GWB_BuildCmd_List2_GetFront(cmdList)) ) {
194  GWB_BuildCmd_List2_PopFront(cmdList);
196  } /* while */
197 }
198 
199 
200 
201 
202 void _setupCommands(GWB_BUILD_CONTEXT *bctx, int forPrepareCommands)
203 {
204  GWB_BUILD_CMD_LIST2_ITERATOR *it;
205 
206  it=GWB_BuildCmd_List2_First(bctx->commandList);
207  if (it) {
208  GWB_BUILD_CMD *bcmd;
209 
210  bcmd=GWB_BuildCmd_List2Iterator_Data(it);
211  while(bcmd) {
212  GWB_BUILD_SUBCMD_LIST *cmdList;
213 
214  if (forPrepareCommands)
216  else
217  cmdList=GWB_BuildCmd_GetBuildCommandList(bcmd);
218  if (cmdList)
219  GWB_BuildCmd_SetCurrentCommand(bcmd, GWB_BuildSubCmd_List_First(cmdList));
220  bcmd=GWB_BuildCmd_List2Iterator_Next(it);
221  }
222  GWB_BuildCmd_List2Iterator_free(it);
223  }
224 }
225 
226 
227 
229 {
230  bctx->waitingQueue=GWB_BuildCmd_List2_new();
231  bctx->finishedQueue=GWB_BuildCmd_List2_new();
232  bctx->runningQueue=GWB_BuildCmd_List2_new();
233 }
234 
235 
236 
237 int _checkWaitingQueue(GWB_BUILD_CONTEXT *bctx, int maxStartAllowed)
238 {
239  GWB_BUILD_CMD_LIST2 *oldQueue;
240  GWB_BUILD_CMD *bcmd;
241  int started=0;
242  int errors=0;
243 
244  oldQueue=bctx->waitingQueue;
245  bctx->waitingQueue=GWB_BuildCmd_List2_new();
246 
247  while( (bcmd=GWB_BuildCmd_List2_GetFront(oldQueue)) ) {
248 
249  GWB_BuildCmd_List2_PopFront(oldQueue);
250  if (started<maxStartAllowed) {
251  if (GWB_BuildCmd_GetBlockingFiles(bcmd)==0) {
252  int rv;
253  GWEN_STRINGLIST *slInFiles;
254  GWEN_STRINGLIST *slOutFiles;
255 
257  bctx->initialSourceDir);
259  bctx->initialSourceDir);
260  if (_needRunCurrentCommand(bcmd, slInFiles, slOutFiles)) {
261 
262  rv=_startCommand(bctx, bcmd, slOutFiles);
263  if (rv<0) {
264  GWB_BuildCmd_List2_PushBack(bctx->finishedQueue, bcmd);
265  errors++;
266  }
267  else {
268  GWB_BuildCmd_List2_PushBack(bctx->runningQueue, bcmd);
269  started++;
270  }
271  }
272  else {
274  started++;
275  }
276  GWEN_StringList_free(slOutFiles);
277  GWEN_StringList_free(slInFiles);
278  }
279  else
280  GWB_BuildCmd_List2_PushBack(bctx->waitingQueue, bcmd);
281  }
282  else
283  GWB_BuildCmd_List2_PushBack(bctx->waitingQueue, bcmd);
284  } /* while */
285  GWB_BuildCmd_List2_free(oldQueue);
286 
287  if (errors)
288  return GWEN_ERROR_GENERIC;
289  return started;
290 }
291 
292 
293 
294 GWEN_STRINGLIST *_fileListToTopBuildDirStringList(const char *initialSourceDir, GWB_FILE_LIST2 *fileList)
295 {
296  GWB_FILE_LIST2_ITERATOR *it;
297 
298  it=GWB_File_List2_First(fileList);
299  if (it) {
300  GWEN_STRINGLIST *sl;
301  GWB_FILE *file;
302  GWEN_BUFFER *fbuf;
303 
304  sl=GWEN_StringList_new();
305  fbuf=GWEN_Buffer_new(0, 256, 0, 1);
306  file=GWB_File_List2Iterator_Data(it);
307  while(file) {
308  GWB_File_WriteFileNameToTopBuildDirString(file, initialSourceDir, fbuf);
310  GWEN_Buffer_Reset(fbuf);
311  file=GWB_File_List2Iterator_Next(it);
312  } /* while */
313  GWEN_Buffer_Reset(fbuf);
314  GWB_File_List2Iterator_free(it);
315 
316  if (GWEN_StringList_Count(sl)==0) {
318  return NULL;
319  }
320  return sl;
321  }
322 
323  return NULL;
324 }
325 
326 
327 
328 int _needRunCurrentCommand(GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles)
329 {
330  GWB_BUILD_SUBCMD *currentCommand;
331 
332  currentCommand=GWB_BuildCmd_GetCurrentCommand(bcmd);
333  if (currentCommand) {
334  uint32_t cmdFlags;
335  uint32_t subCmdFlags;
336 
337  cmdFlags=GWB_BuildCmd_GetFlags(bcmd);
338  subCmdFlags=GWB_BuildSubCmd_GetFlags(currentCommand);
339 
340  if (cmdFlags & GWB_BUILD_CMD_FLAGS_CHECK_DATES) {
341  if (_inFilesNewerThanOutFiles(slInFiles, slOutFiles)) {
342  /* need rebuild */
343  DBG_INFO(NULL, "Input files newer than output files, rebuild needed");
344  return 1;
345  }
346  }
347  else
348  /* dont check dates, always rebuild */
349  return 1;
350 
351  if (subCmdFlags & GWB_BUILD_SUBCMD_FLAGS_CHECK_DEPENDS) {
352  int rv;
353 
354  rv=_checkDependencies(bcmd, currentCommand, GWEN_StringList_FirstString(slOutFiles));
355  if (rv==-1) {
356  DBG_INFO(NULL, "Dependencies flag NO rebuild needed (%d)", rv);
357  return 0;
358  }
359  DBG_INFO(NULL, "Dependencies flag rebuild needed (%d)", rv);
360  return 1;
361  }
362  }
363 
364  DBG_INFO(NULL, "Rebuild not needed");
365  return 0;
366 }
367 
368 
369 
370 /* return 0: no rebuild needed; 1: rebuild needed */
371 int _inFilesNewerThanOutFiles(const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles)
372 {
373  time_t tiHighestInFileTime;
374  time_t tiLowestOutFileTime;
375 
376  tiHighestInFileTime=_getHighestModificationTime(slInFiles);
377  tiLowestOutFileTime=_getLowestModificationTime(slOutFiles);
378  if (tiHighestInFileTime==0 || tiLowestOutFileTime==0) {
379  DBG_INFO(NULL, "Either input or output time not available");
380  return 1;
381  }
382  if (tiHighestInFileTime>tiLowestOutFileTime)
383  return 1;
384  return 0;
385 }
386 
387 
388 
390 {
391  time_t tiLowest=0;
392 
393  if (slFiles) {
395 
396  se=GWEN_StringList_FirstEntry(slFiles);
397  while(se) {
398  const char *s;
399 
401  if (s && *s) {
402  time_t tiFile;
403 
405  if (tiFile>0) {
406  if (tiLowest==0)
407  tiLowest=tiFile;
408  else if (tiFile<tiLowest)
409  tiLowest=tiFile;
410  }
411  else {
412  DBG_INFO(NULL, "No modification time for \"%s\"", s);
413  return 0;
414  }
415  }
416 
418  }
419  }
420 
421  return tiLowest;
422 }
423 
424 
425 
427 {
428  time_t tiHighest=0;
429 
430  if (slFiles) {
432 
433  se=GWEN_StringList_FirstEntry(slFiles);
434  while(se) {
435  const char *s;
436 
438  if (s && *s) {
439  time_t tiFile;
440 
442  if (tiFile>0) {
443  if (tiHighest==0)
444  tiHighest=tiFile;
445  else if (tiFile>tiHighest)
446  tiHighest=tiFile;
447  }
448  else {
449  DBG_INFO(NULL, "No modification time for \"%s\"", s);
450  return 0;
451  }
452  }
453 
455  }
456  }
457 
458  return tiHighest;
459 }
460 
461 
462 
464 {
465  if (slFiles) {
467 
468  se=GWEN_StringList_FirstEntry(slFiles);
469  while(se) {
470  const char *s;
471 
473  if (s && *s) {
474  DBG_DEBUG(NULL, "Deleting \"%s\"", s);
475  unlink(s);
476  }
477 
479  }
480  }
481 }
482 
483 
484 
485 /* return 1: need rebuild, -1: Need no rebuild, 0: undecided */
486 int _checkDependencies(GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *subCmd, const char *firstOutFileName)
487 {
488  const char *depFileName;
489 
490  depFileName=GWB_BuildSubCmd_GetDepFilePath(subCmd);
491  if (depFileName && firstOutFileName) {
492  GWEN_STRINGLIST *sl;
493 
494  DBG_DEBUG(NULL, "Checking depend file \"%s\"", depFileName);
496  if (sl) {
497  int rv;
498 
499  //GWBUILD_Debug_PrintStringList(depFileName, sl, 2);
500  rv=_checkDatesOfFileAgainstList(firstOutFileName, sl);
502  return rv;
503  }
504  else {
505  DBG_DEBUG(NULL, "Could not load depend file \"%s\"", depFileName);
506  }
507  }
508  else {
509  if (depFileName==NULL) {
510  DBG_DEBUG(NULL, "No depFileName for %s", firstOutFileName?firstOutFileName:"<no outfile name>");
511  }
512  if (firstOutFileName==NULL) {
513  DBG_DEBUG(NULL, "No outFileName");
514  }
515  }
516 
517  return 0; /* indeterminate */
518 }
519 
520 
521 
522 int _checkDatesOfFileAgainstList(const char *fileName, const GWEN_STRINGLIST *sl)
523 {
524  time_t tFile;
526 
527  tFile=GWBUILD_GetModificationTimeOfFile(fileName);
528  if (tFile==0) {
529  DBG_DEBUG(NULL, "%s: No modification time, need rebuild", fileName);
530  return 1; /* need rebuild */
531  }
533  if (se) {
534  while(se) {
535  const char *s;
536 
538  if (s && *s) {
539  time_t tCurrent;
540 
541  DBG_DEBUG(NULL, " Checking dep: %s", s);
543  if (tCurrent==0) {
544  DBG_DEBUG(NULL, "No modification time for dependency \"%s\", need rebuild", s);
545  return 1; /* need rebuild */
546  }
547  if (difftime(tFile, tCurrent)<0.0) {
548  DBG_DEBUG(NULL, "File \"%s\" is newer than \"%s\", rebuild needed", s, fileName);
549  return 1; /* definately need rebuild */
550  }
551  }
552 
554  }
555 
556  DBG_DEBUG(NULL, "No dependency is newer than file \"%s\", NO rebuild needed", fileName);
557  return -1; /* definately no need for rebuild */
558  }
559  else {
560  DBG_DEBUG(NULL, "Empty dependency list, rebuild needed");
561  }
562 
563  return 0;
564 }
565 
566 
567 
568 int _startCommand(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slOutFiles)
569 {
570  GWB_BUILD_SUBCMD *currentCommand;
571 
572  currentCommand=GWB_BuildCmd_GetCurrentCommand(bcmd);
573  if (currentCommand) {
574  const char *folder;
575  const char *cmd;
576  const char *args;
577 
578  folder=GWB_BuildCmd_GetFolder(bcmd);
579  cmd=GWB_BuildSubCmd_GetCommand(currentCommand);
580  args=GWB_BuildSubCmd_GetArguments(currentCommand);
581 
582  if (cmd && *cmd) {
583  GWEN_PROCESS *process;
584  GWEN_PROCESS_STATE pstate;
585  const char *buildMessage;
586  int rv;
587 
588  if (GWB_BuildSubCmd_List_Previous(currentCommand)==NULL) {
589  /* first command */
590  if (slOutFiles && (GWB_BuildCmd_GetFlags(bcmd) & GWB_BUILD_CMD_FLAGS_DEL_OUTFILES)) {
591  _unlinkFilesInStringList(slOutFiles);
592  }
593  }
594 
595  buildMessage=GWB_BuildSubCmd_GetBuildMessage(currentCommand);
596  if (buildMessage)
597  fprintf(stdout, "%s [%s]\n", buildMessage, cmd);
598  else
599  fprintf(stdout, "%s %s\n", cmd, args);
600 
601  rv=GWB_BuildCtx_CreateAndSetLogFilenameForSubCmd(bctx, currentCommand);
602  if (rv<0) {
603  DBG_ERROR(NULL, "Error creating logfile path for output redirection (%d)", rv);
605  return GWEN_ERROR_GENERIC;
606  }
607 
608  process=GWEN_Process_new();
609  if (folder && *folder)
610  GWEN_Process_SetFolder(process, folder);
611 
614 
615  GWB_BuildCmd_SetCurrentProcess(bcmd, process);
616  pstate=GWEN_Process_Start(process, cmd, args);
617  if (pstate!=GWEN_ProcessStateRunning) {
618  DBG_ERROR(NULL, "Error starting command process (%d)", pstate);
620  return GWEN_ERROR_GENERIC;
621  }
622  DBG_DEBUG(NULL, "Process started");
623  return 0;
624  }
625  else {
626  DBG_ERROR(NULL, "No command in build command");
627  return GWEN_ERROR_GENERIC;
628  }
629  }
630  else {
631  DBG_ERROR(NULL, "No current command in build command");
632  return GWEN_ERROR_GENERIC;
633  }
634 }
635 
636 
637 
639 {
640  GWB_BUILD_CMD_LIST2 *oldRunningQueue;
641  GWB_BUILD_CMD *bcmd;
642  int changes=0;
643  int errors=0;
644 
645  oldRunningQueue=bctx->runningQueue;
646  bctx->runningQueue=GWB_BuildCmd_List2_new();
647 
648  while( (bcmd=GWB_BuildCmd_List2_GetFront(oldRunningQueue)) ) {
649  GWEN_PROCESS *process;
650  GWEN_PROCESS_STATE pstate;
651  GWB_BUILD_SUBCMD *currentCommand;
652 
653  GWB_BuildCmd_List2_PopFront(oldRunningQueue);
654  currentCommand=GWB_BuildCmd_GetCurrentCommand(bcmd);
655  process=GWB_BuildCmd_GetCurrentProcess(bcmd);
656  pstate=GWEN_Process_CheckState(process);
657  if (pstate!=GWEN_ProcessStateRunning) {
658  changes++;
659  if (pstate==GWEN_ProcessStateExited) {
660  int result;
661 
662  result=GWEN_Process_GetResult(process);
664  if (result) {
666  DBG_INFO(NULL, "Command exited with result %d, ignoring", result);
667  _finishCurrentCommand(bctx, bcmd, currentCommand);
668  }
669  else {
670  DBG_INFO(NULL, "Command exited with result %d", result);
671  errors++;
672  }
673  //_printCmdOutput(currentCommand);
674  }
675  else {
676  _finishCurrentCommand(bctx, bcmd, currentCommand);
677  }
678  }
679  else {
680  DBG_ERROR(NULL, "Command aborted (status: %d)", pstate);
681  GWB_BuildCmd_List2_PushBack(bctx->finishedQueue, bcmd);
682  errors++;
683  }
684  GWB_BuildCmd_SetCurrentProcess(bcmd, NULL); /* no longer running */
685  }
686  else
687  GWB_BuildCmd_List2_PushBack(bctx->runningQueue, bcmd); /* still running, put back */
688  } /* while still commands in running queue */
689 
690  GWB_BuildCmd_List2_free(oldRunningQueue);
691 
692  if (errors)
693  return GWEN_ERROR_GENERIC;
694  return changes;
695 }
696 
697 
698 
700 {
701  GWB_BUILD_SUBCMD *nextCommand;
702 
703  nextCommand=GWB_BuildSubCmd_List_Next(currentCommand);
704  GWB_BuildCmd_SetCurrentCommand(bcmd, nextCommand);
705  if (nextCommand)
706  GWB_BuildCmd_List2_PushBack(bctx->waitingQueue, bcmd);
707  else {
708  _signalJobFinished(bcmd);
709  GWB_BuildCmd_List2_PushBack(bctx->finishedQueue, bcmd);
710  }
711 }
712 
713 
714 
716 {
717  GWB_FILE_LIST2 *outFileList;
718 
719  outFileList=GWB_BuildCmd_GetOutFileList2(bcmd);
720  if (outFileList) {
721  GWB_FILE_LIST2_ITERATOR *it;
722 
723  it=GWB_File_List2_First(outFileList);
724  if (it) {
725  GWB_FILE *file;
726 
727  file=GWB_File_List2Iterator_Data(it);
728  while(file) {
729  GWB_BUILD_CMD_LIST2 *waitingCommands;
730 
731  waitingCommands=GWB_File_GetWaitingBuildCmdList2(file);
732  if (waitingCommands)
734  file=GWB_File_List2Iterator_Next(it);
735  }
736  GWB_File_List2Iterator_free(it);
737  }
738  }
739 
740 }
741 
742 
743 
744 void _decBlockingFilesInWaitingBuildCommands(GWB_BUILD_CMD_LIST2 *waitingCommands)
745 {
746  GWB_BUILD_CMD_LIST2_ITERATOR *it;
747 
748  it=GWB_BuildCmd_List2_First(waitingCommands);
749  if (it) {
750  GWB_BUILD_CMD *bcmd;
751 
752  bcmd=GWB_BuildCmd_List2Iterator_Data(it);
753  while(bcmd) {
755  bcmd=GWB_BuildCmd_List2Iterator_Next(it);
756  }
757 
758  GWB_BuildCmd_List2Iterator_free(it);
759  }
760 }
761 
762 
763 
765 {
766  const char *fileName;
767 
768  fileName=GWB_BuildSubCmd_GetLogFilename(cmd);
769  if (fileName) {
770  struct stat sb;
771 
772  if (stat(fileName, &sb)==-1) {
773  DBG_ERROR(GWEN_LOGDOMAIN, "stat(%s): %d [%s]", fileName, errno, strerror(errno));
774  }
775  else {
776  if (sb.st_size>0) {
777  int rv;
778  GWEN_BUFFER *dbuf;
779 
780  dbuf=GWEN_Buffer_new(0, 256, 0, 1);
781  rv=GWEN_SyncIo_Helper_ReadFile(fileName, dbuf);
782  if (rv<0) {
783  DBG_ERROR(GWEN_LOGDOMAIN, "Error reading command output from file \"%s\": %d", fileName, rv);
784  }
785  else {
786  const char *buildMessage;
787  const char *exe;
788 
789  buildMessage=GWB_BuildSubCmd_GetBuildMessage(cmd);
791  fprintf(stderr, "Output from [%s]\n", buildMessage?buildMessage:(exe?exe:"NONE"));
792  fprintf(stderr, "%s\n", GWEN_Buffer_GetStart(dbuf));
793  fflush(stderr);
794  }
795  GWEN_Buffer_free(dbuf);
796  }
797  unlink(fileName);
798  }
799  }
800 }
801 
802 
803 
804 
const char * GWB_BuildSubCmd_GetCommand(const GWB_BUILD_SUBCMD *cmd)
Definition: buildsubcmd.c:116
static time_t _getHighestModificationTime(const GWEN_STRINGLIST *slFiles)
Definition: buildctx_run.c:426
GWB_FILE_LIST2 * GWB_BuildCmd_GetInFileList2(const GWB_BUILD_CMD *bcmd)
Definition: buildcmd.c:255
static int _checkDependencies(GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *subCmd, const char *firstOutFileName)
Definition: buildctx_run.c:486
#define DBG_ERROR(dbg_logger, format,...)
Definition: debug.h:97
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
struct GWEN_STRINGLISTENTRYSTRUCT GWEN_STRINGLISTENTRY
Definition: stringlist.h:53
GWB_BUILD_SUBCMD_LIST * GWB_BuildCmd_GetPrepareCommandList(const GWB_BUILD_CMD *bcmd)
Definition: buildcmd.c:196
int GWB_BuildCtx_CreateAndSetLogFilenameForSubCmd(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_SUBCMD *cmd)
Definition: buildctx.c:220
#define DBG_DEBUG(dbg_logger, format,...)
Definition: debug.h:214
const char * GWB_BuildSubCmd_GetDepFilePath(const GWB_BUILD_SUBCMD *cmd)
Definition: buildsubcmd.c:161
void GWB_BuildCmd_SetCurrentProcess(GWB_BUILD_CMD *bcmd, GWEN_PROCESS *process)
Definition: buildcmd.c:292
#define GWB_BUILD_SUBCMD_FLAGS_CHECK_DEPENDS
Definition: buildsubcmd.h:24
struct GWB_FILE GWB_FILE
Definition: file.h:18
struct GWB_BUILD_CONTEXT GWB_BUILD_CONTEXT
Definition: buildctx.h:16
static int _checkWaitingQueue(GWB_BUILD_CONTEXT *bctx, int maxStartAllowed)
Definition: buildctx_run.c:237
#define NULL
Definition: binreloc.c:300
int GWEN_SyncIo_Helper_ReadFile(const char *fName, GWEN_BUFFER *dbuf)
Definition: syncio.c:524
static void _finishCurrentCommand(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *currentCommand)
Definition: buildctx_run.c:699
static int _checkRunningQueue(GWB_BUILD_CONTEXT *bctx)
Definition: buildctx_run.c:638
int GWB_BuildCtx_FillWaitingQueue(GWB_BUILD_CONTEXT *bctx, const char *builderName)
const char * GWB_BuildCmd_GetFolder(const GWB_BUILD_CMD *bcmd)
Definition: buildcmd.c:166
#define GWEN_LOGDOMAIN
Definition: logger.h:35
#define GWB_BUILD_CMD_FLAGS_CHECK_DATES
Definition: buildcmd.h:25
GWB_BUILD_CMD_LIST2 * GWB_File_GetWaitingBuildCmdList2(const GWB_FILE *f)
Definition: file.c:246
#define GWB_BUILDCTX_PROCESS_WAIT_TIMEOUT
Definition: buildctx_run.c:35
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
static char * exe
Definition: binreloc.c:303
GWEN_STRINGLISTENTRY * GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:390
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:653
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:406
GWEN_PROCESS_STATE
Definition: process.h:54
GWEN_STRINGLIST * GWB_BuildCtx_ReadAndTranslateDepfile(const char *folder, const char *fileName)
void GWEN_StringList_free(GWEN_STRINGLIST *sl)
Definition: stringlist.c:62
const char * GWB_BuildSubCmd_GetArguments(const GWB_BUILD_SUBCMD *cmd)
Definition: buildsubcmd.c:131
static int _inFilesNewerThanOutFiles(const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles)
Definition: buildctx_run.c:371
GWENHYWFAR_API GWEN_PROCESS_STATE GWEN_Process_CheckState(GWEN_PROCESS *pr)
GWEN_PROCESS * GWB_BuildCmd_GetCurrentProcess(const GWB_BUILD_CMD *bcmd)
Definition: buildcmd.c:285
int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl, const char *s, int take, int checkDouble)
Definition: stringlist.c:245
int GWB_BuildCmd_DecBlockingFiles(GWB_BUILD_CMD *bcmd)
Definition: buildcmd.c:245
GWENHYWFAR_API void GWEN_Process_SetFilenameStdOut(GWEN_PROCESS *pr, const char *s)
#define GWB_BUILD_CMD_FLAGS_DEL_OUTFILES
Definition: buildcmd.h:26
GWB_FILE_LIST2 * GWB_BuildCmd_GetOutFileList2(const GWB_BUILD_CMD *bcmd)
Definition: buildcmd.c:270
struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST
Definition: stringlist.h:56
static void _abortCommandsInQueue(GWB_BUILD_CMD_LIST2 *cmdList)
Definition: buildctx_run.c:189
#define GWEN_ERROR_GENERIC
Definition: error.h:62
const char * GWB_BuildSubCmd_GetBuildMessage(const GWB_BUILD_SUBCMD *cmd)
Definition: buildsubcmd.c:146
#define GWB_BUILD_SUBCMD_FLAGS_IGNORE_RESULT
Definition: buildsubcmd.h:23
GWENHYWFAR_API int GWEN_Process_GetResult(GWEN_PROCESS *pr)
GWB_BUILD_SUBCMD_LIST * GWB_BuildCmd_GetBuildCommandList(const GWB_BUILD_CMD *bcmd)
Definition: buildcmd.c:210
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
struct GWB_BUILD_SUBCMD GWB_BUILD_SUBCMD
Definition: buildsubcmd.h:16
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
static int _checkDatesOfFileAgainstList(const char *fileName, const GWEN_STRINGLIST *sl)
Definition: buildctx_run.c:522
static time_t _getLowestModificationTime(const GWEN_STRINGLIST *slFiles)
Definition: buildctx_run.c:389
unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:427
static void _abortAllCommands(GWB_BUILD_CONTEXT *bctx)
Definition: buildctx_run.c:172
GWENHYWFAR_API GWEN_PROCESS * GWEN_Process_new(void)
static int _waitForRunningJobs(GWB_BUILD_CONTEXT *bctx)
Definition: buildctx_run.c:133
const char * GWEN_StringList_FirstString(const GWEN_STRINGLIST *l)
Definition: stringlist.c:576
const char * GWB_BuildSubCmd_GetLogFilename(const GWB_BUILD_SUBCMD *cmd)
Definition: buildsubcmd.c:73
struct GWEN_PROCESS GWEN_PROCESS
Definition: process.h:49
static void _decBlockingFilesInWaitingBuildCommands(GWB_BUILD_CMD_LIST2 *waitingCommands)
Definition: buildctx_run.c:744
GWB_BUILD_SUBCMD * GWB_BuildCmd_GetCurrentCommand(const GWB_BUILD_CMD *bcmd)
Definition: buildcmd.c:306
uint32_t GWB_BuildSubCmd_GetFlags(const GWB_BUILD_SUBCMD *cmd)
Definition: buildsubcmd.c:88
time_t GWBUILD_GetModificationTimeOfFile(const char *filename)
Definition: gwenbuild.c:891
int GWB_BuildCtx_SetupDependencies(GWB_BUILD_CONTEXT *bctx)
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:398
void GWB_File_WriteFileNameToTopBuildDirString(const GWB_FILE *file, const char *initialSourceDir, GWEN_BUFFER *fbuf)
Definition: file.c:474
struct GWB_BUILD_CMD GWB_BUILD_CMD
Definition: buildcmd.h:20
GWEN_STRINGLIST * _fileListToTopBuildDirStringList(const char *initialSourceDir, GWB_FILE_LIST2 *fileList)
Definition: buildctx_run.c:294
GWENHYWFAR_API GWEN_PROCESS_STATE GWEN_Process_Start(GWEN_PROCESS *pr, const char *prg, const char *args)
static void _setupCommands(GWB_BUILD_CONTEXT *bctx, int forPrepareCommands)
Definition: buildctx_run.c:202
static void _printCmdOutputIfNotEmptyAndDeleteFile(GWB_BUILD_SUBCMD *cmd)
Definition: buildctx_run.c:764
static int _startCommand(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slOutFiles)
Definition: buildctx_run.c:568
#define GWEN_ERROR_TIMEOUT
Definition: error.h:71
static int _needRunCurrentCommand(GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles)
Definition: buildctx_run.c:328
#define DBG_INFO(dbg_logger, format,...)
Definition: debug.h:181
GWEN_STRINGLIST * GWB_File_FileListToTopBuildDirStringList(const GWB_FILE_LIST2 *fileList, const char *initialSourceDir)
Definition: file.c:495
static void _createCommandQueues(GWB_BUILD_CONTEXT *bctx)
Definition: buildctx_run.c:228
GWENHYWFAR_API void GWEN_Process_SetFilenameStdErr(GWEN_PROCESS *pr, const char *s)
uint32_t GWB_BuildCmd_GetFlags(const GWB_BUILD_CMD *bcmd)
Definition: buildcmd.c:120
GWEN_STRINGLIST * GWEN_StringList_new(void)
Definition: stringlist.c:50
int GWB_BuildCmd_GetBlockingFiles(const GWB_BUILD_CMD *bcmd)
Definition: buildcmd.c:224
int GWB_BuildCtx_Run(GWB_BUILD_CONTEXT *bctx, int maxConcurrentJobs, int usePrepareCommands, const char *builderName)
Definition: buildctx_run.c:66
static void _unlinkFilesInStringList(const GWEN_STRINGLIST *slFiles)
Definition: buildctx_run.c:463
GWENHYWFAR_API void GWEN_Process_SetFolder(GWEN_PROCESS *pr, const char *s)
static void _signalJobFinished(GWB_BUILD_CMD *bcmd)
Definition: buildctx_run.c:715
void GWB_BuildCmd_SetCurrentCommand(GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *cmd)
Definition: buildcmd.c:313