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