gwenhywfar 5.12.0
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
38static int _commandLogNum=0;
39
40static void _setupCommands(GWB_BUILD_CONTEXT *bctx, int forPrepareCommands);
42static int _checkWaitingQueue(GWB_BUILD_CONTEXT *bctx, int maxStartAllowed);
43static int _startCommand(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slOutFiles);
45static void _signalJobFinished(GWB_BUILD_CMD *bcmd);
46static void _decBlockingFilesInWaitingBuildCommands(GWB_BUILD_CMD_LIST2 *waitingCommands);
48
50static void _abortAllCommands(GWB_BUILD_CONTEXT *bctx);
51static void _abortCommandsInQueue(GWB_BUILD_CMD_LIST2 *cmdList);
52
53static int _needRunCurrentCommand(GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles);
54static void _finishCurrentCommand(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *currentCommand);
55
56static int _checkDependencies(GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *subCmd, const char *firstOutFileName);
57static int _checkDatesOfFileAgainstList(const char *fileName, const GWEN_STRINGLIST *sl);
58
59static int _inFilesNewerThanOutFiles(const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles);
60static time_t _getHighestModificationTime(const GWEN_STRINGLIST *slFiles);
61static time_t _getLowestModificationTime(const GWEN_STRINGLIST *slFiles);
62static void _unlinkFilesInStringList(const GWEN_STRINGLIST *slFiles);
63
64
65
66
67
68int 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) {
98 return GWEN_ERROR_GENERIC;
99 }
100
101 changedCommands=_checkRunningQueue(bctx);
102 if (changedCommands<0) { /* error */
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?");
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
191void _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
204void _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
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
239int _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
296GWEN_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
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
330int _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 */
373int _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 */
488int _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
524int _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
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
746void _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
#define NULL
Definition binreloc.c:300
static char * exe
Definition binreloc.c:303
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition buffer.c:42
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition buffer.c:653
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition buffer.c:89
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition buffer.c:235
GWB_FILE_LIST2 * GWB_BuildCmd_GetOutFileList2(const GWB_BUILD_CMD *bcmd)
Definition buildcmd.c:270
GWB_BUILD_SUBCMD_LIST * GWB_BuildCmd_GetPrepareCommandList(const GWB_BUILD_CMD *bcmd)
Definition buildcmd.c:196
void GWB_BuildCmd_SetCurrentProcess(GWB_BUILD_CMD *bcmd, GWEN_PROCESS *process)
Definition buildcmd.c:292
void GWB_BuildCmd_SetCurrentCommand(GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *cmd)
Definition buildcmd.c:313
uint32_t GWB_BuildCmd_GetFlags(const GWB_BUILD_CMD *bcmd)
Definition buildcmd.c:120
GWB_FILE_LIST2 * GWB_BuildCmd_GetInFileList2(const GWB_BUILD_CMD *bcmd)
Definition buildcmd.c:255
int GWB_BuildCmd_DecBlockingFiles(GWB_BUILD_CMD *bcmd)
Definition buildcmd.c:245
GWB_BUILD_SUBCMD * GWB_BuildCmd_GetCurrentCommand(const GWB_BUILD_CMD *bcmd)
Definition buildcmd.c:306
GWB_BUILD_SUBCMD_LIST * GWB_BuildCmd_GetBuildCommandList(const GWB_BUILD_CMD *bcmd)
Definition buildcmd.c:210
const char * GWB_BuildCmd_GetFolder(const GWB_BUILD_CMD *bcmd)
Definition buildcmd.c:166
int GWB_BuildCmd_GetBlockingFiles(const GWB_BUILD_CMD *bcmd)
Definition buildcmd.c:224
GWEN_PROCESS * GWB_BuildCmd_GetCurrentProcess(const GWB_BUILD_CMD *bcmd)
Definition buildcmd.c:285
struct GWB_BUILD_CMD GWB_BUILD_CMD
Definition buildcmd.h:20
#define GWB_BUILD_CMD_FLAGS_CHECK_DATES
Definition buildcmd.h:25
#define GWB_BUILD_CMD_FLAGS_DEL_OUTFILES
Definition buildcmd.h:26
int GWB_BuildCtx_CreateAndSetLogFilenameForSubCmd(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_SUBCMD *cmd)
Definition buildctx.c:220
struct GWB_BUILD_CONTEXT GWB_BUILD_CONTEXT
Definition buildctx.h:16
int GWB_BuildCtx_FillWaitingQueue(GWB_BUILD_CONTEXT *bctx, const char *builderName)
int GWB_BuildCtx_SetupDependencies(GWB_BUILD_CONTEXT *bctx)
GWEN_STRINGLIST * GWB_BuildCtx_ReadAndTranslateDepfile(const char *folder, const char *fileName)
static int _startCommand(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slOutFiles)
static int _checkWaitingQueue(GWB_BUILD_CONTEXT *bctx, int maxStartAllowed)
static void _abortCommandsInQueue(GWB_BUILD_CMD_LIST2 *cmdList)
static void _signalJobFinished(GWB_BUILD_CMD *bcmd)
static int _needRunCurrentCommand(GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles)
static void _finishCurrentCommand(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *currentCommand)
int GWB_BuildCtx_Run(GWB_BUILD_CONTEXT *bctx, int maxConcurrentJobs, int usePrepareCommands, const char *builderName)
static void _createCommandQueues(GWB_BUILD_CONTEXT *bctx)
static time_t _getLowestModificationTime(const GWEN_STRINGLIST *slFiles)
static time_t _getHighestModificationTime(const GWEN_STRINGLIST *slFiles)
static void _printCmdOutputIfNotEmptyAndDeleteFile(GWB_BUILD_CMD *cmd, GWB_BUILD_SUBCMD *subCmd)
static void _unlinkFilesInStringList(const GWEN_STRINGLIST *slFiles)
static void _decBlockingFilesInWaitingBuildCommands(GWB_BUILD_CMD_LIST2 *waitingCommands)
static int _inFilesNewerThanOutFiles(const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles)
static int _checkDatesOfFileAgainstList(const char *fileName, const GWEN_STRINGLIST *sl)
static int _checkRunningQueue(GWB_BUILD_CONTEXT *bctx)
static void _abortAllCommands(GWB_BUILD_CONTEXT *bctx)
static int _commandLogNum
static int _waitForRunningJobs(GWB_BUILD_CONTEXT *bctx)
GWEN_STRINGLIST * _fileListToTopBuildDirStringList(const char *initialSourceDir, GWB_FILE_LIST2 *fileList)
static int _checkDependencies(GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *subCmd, const char *firstOutFileName)
static void _setupCommands(GWB_BUILD_CONTEXT *bctx, int forPrepareCommands)
#define GWB_BUILDCTX_PROCESS_WAIT_TIMEOUT
uint32_t GWB_BuildSubCmd_GetFlags(const GWB_BUILD_SUBCMD *cmd)
Definition buildsubcmd.c:88
const char * GWB_BuildSubCmd_GetArguments(const GWB_BUILD_SUBCMD *cmd)
const char * GWB_BuildSubCmd_GetDepFilePath(const GWB_BUILD_SUBCMD *cmd)
const char * GWB_BuildSubCmd_GetLogFilename(const GWB_BUILD_SUBCMD *cmd)
Definition buildsubcmd.c:73
const char * GWB_BuildSubCmd_GetCommand(const GWB_BUILD_SUBCMD *cmd)
const char * GWB_BuildSubCmd_GetBuildMessage(const GWB_BUILD_SUBCMD *cmd)
#define GWB_BUILD_SUBCMD_FLAGS_CHECK_DEPENDS
Definition buildsubcmd.h:24
struct GWB_BUILD_SUBCMD GWB_BUILD_SUBCMD
Definition buildsubcmd.h:16
#define GWB_BUILD_SUBCMD_FLAGS_IGNORE_RESULT
Definition buildsubcmd.h:23
#define DBG_INFO(dbg_logger, format,...)
Definition debug.h:181
#define DBG_ERROR(dbg_logger, format,...)
Definition debug.h:97
#define DBG_DEBUG(dbg_logger, format,...)
Definition debug.h:214
#define GWEN_ERROR_TIMEOUT
Definition error.h:71
#define GWEN_ERROR_GENERIC
Definition error.h:62
void GWB_File_WriteFileNameToTopBuildDirString(const GWB_FILE *file, const char *initialSourceDir, GWEN_BUFFER *fbuf)
Definition file.c:474
GWEN_STRINGLIST * GWB_File_FileListToTopBuildDirStringList(const GWB_FILE_LIST2 *fileList, const char *initialSourceDir)
Definition file.c:495
GWB_BUILD_CMD_LIST2 * GWB_File_GetWaitingBuildCmdList2(const GWB_FILE *f)
Definition file.c:246
struct GWB_FILE GWB_FILE
Definition file.h:18
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition buffer.h:38
time_t GWBUILD_GetModificationTimeOfFile(const char *filename)
Definition gwenbuild.c:891
#define GWEN_LOGDOMAIN
Definition logger.h:35
GWENHYWFAR_API int GWEN_Process_GetResult(GWEN_PROCESS *pr)
GWENHYWFAR_API void GWEN_Process_SetFolder(GWEN_PROCESS *pr, const char *s)
GWENHYWFAR_API GWEN_PROCESS * GWEN_Process_new(void)
GWENHYWFAR_API GWEN_PROCESS_STATE GWEN_Process_Start(GWEN_PROCESS *pr, const char *prg, const char *args)
GWENHYWFAR_API void GWEN_Process_SetFilenameStdOut(GWEN_PROCESS *pr, const char *s)
GWENHYWFAR_API GWEN_PROCESS_STATE GWEN_Process_CheckState(GWEN_PROCESS *pr)
GWENHYWFAR_API void GWEN_Process_SetFilenameStdErr(GWEN_PROCESS *pr, const char *s)
struct GWEN_PROCESS GWEN_PROCESS
Definition process.h:49
GWEN_PROCESS_STATE
Definition process.h:54
@ GWEN_ProcessStateRunning
Definition process.h:58
@ GWEN_ProcessStateExited
Definition process.h:60
void GWEN_StringList_free(GWEN_STRINGLIST *sl)
Definition stringlist.c:62
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
Definition stringlist.c:406
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
Definition stringlist.c:398
unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
Definition stringlist.c:427
int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl, const char *s, int take, int checkDouble)
Definition stringlist.c:245
const char * GWEN_StringList_FirstString(const GWEN_STRINGLIST *l)
Definition stringlist.c:576
GWEN_STRINGLISTENTRY * GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl)
Definition stringlist.c:390
GWEN_STRINGLIST * GWEN_StringList_new(void)
Definition stringlist.c:50
struct GWEN_STRINGLISTENTRYSTRUCT GWEN_STRINGLISTENTRY
Definition stringlist.h:53
struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST
Definition stringlist.h:56
int GWEN_SyncIo_Helper_ReadFile(const char *fName, GWEN_BUFFER *dbuf)
Definition syncio.c:524