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