14 #define DISABLE_DEBUGLOG 17 #include "gwenbuild/buildctx/buildctx_p.h" 22 #include <gwenhywfar/debug.h> 23 #include <gwenhywfar/text.h> 24 #include <gwenhywfar/directory.h> 28 #include <sys/types.h> 35 #define GWB_BUILDCTX_PROCESS_WAIT_TIMEOUT 10.0 81 if (GWB_BuildCmd_List2_GetSize(bctx->waitingQueue)==0) {
82 fprintf(stdout,
"Nothing to do.\n");
86 waitingJobs=GWB_BuildCmd_List2_GetSize(bctx->waitingQueue);
87 runningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
88 while(waitingJobs+runningJobs) {
93 if (startedCommands<0) {
100 if (changedCommands<0) {
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?");
117 waitingJobs=GWB_BuildCmd_List2_GetSize(bctx->waitingQueue);
118 runningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
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;
139 numRunningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
141 fprintf(stderr,
"NOTICE: Waiting for %d jobs.\n", numRunningJobs);
142 while(numRunningJobs) {
143 int numChangedCommands;
147 if (numChangedCommands<0) {
150 numRunningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
152 if (numRunningJobs>0) {
156 delta=difftime(currentTime, startTime);
158 DBG_ERROR(
NULL,
"%d jobs still running after %f.1 seconds, aborting", numRunningJobs, delta);
175 GWB_BuildCmd_List2_free(bctx->waitingQueue);
176 bctx->waitingQueue=
NULL;
179 GWB_BuildCmd_List2_free(bctx->runningQueue);
180 bctx->runningQueue=
NULL;
183 GWB_BuildCmd_List2_free(bctx->finishedQueue);
184 bctx->finishedQueue=
NULL;
193 while( (bcmd=GWB_BuildCmd_List2_GetFront(cmdList)) ) {
194 GWB_BuildCmd_List2_PopFront(cmdList);
204 GWB_BUILD_CMD_LIST2_ITERATOR *it;
206 it=GWB_BuildCmd_List2_First(bctx->commandList);
210 bcmd=GWB_BuildCmd_List2Iterator_Data(it);
212 GWB_BUILD_SUBCMD_LIST *cmdList;
214 if (forPrepareCommands)
220 bcmd=GWB_BuildCmd_List2Iterator_Next(it);
222 GWB_BuildCmd_List2Iterator_free(it);
230 bctx->waitingQueue=GWB_BuildCmd_List2_new();
231 bctx->finishedQueue=GWB_BuildCmd_List2_new();
232 bctx->runningQueue=GWB_BuildCmd_List2_new();
239 GWB_BUILD_CMD_LIST2 *oldQueue;
244 oldQueue=bctx->waitingQueue;
245 bctx->waitingQueue=GWB_BuildCmd_List2_new();
247 while( (bcmd=GWB_BuildCmd_List2_GetFront(oldQueue)) ) {
249 GWB_BuildCmd_List2_PopFront(oldQueue);
250 if (started<maxStartAllowed) {
257 bctx->initialSourceDir);
259 bctx->initialSourceDir);
264 GWB_BuildCmd_List2_PushBack(bctx->finishedQueue, bcmd);
268 GWB_BuildCmd_List2_PushBack(bctx->runningQueue, bcmd);
280 GWB_BuildCmd_List2_PushBack(bctx->waitingQueue, bcmd);
283 GWB_BuildCmd_List2_PushBack(bctx->waitingQueue, bcmd);
285 GWB_BuildCmd_List2_free(oldQueue);
296 GWB_FILE_LIST2_ITERATOR *it;
298 it=GWB_File_List2_First(fileList);
306 file=GWB_File_List2Iterator_Data(it);
311 file=GWB_File_List2Iterator_Next(it);
314 GWB_File_List2Iterator_free(it);
333 if (currentCommand) {
335 uint32_t subCmdFlags;
343 DBG_INFO(
NULL,
"Input files newer than output files, rebuild needed");
356 DBG_INFO(
NULL,
"Dependencies flag NO rebuild needed (%d)", rv);
359 DBG_INFO(
NULL,
"Dependencies flag rebuild needed (%d)", rv);
373 time_t tiHighestInFileTime;
374 time_t tiLowestOutFileTime;
378 if (tiHighestInFileTime==0 || tiLowestOutFileTime==0) {
379 DBG_INFO(
NULL,
"Either input or output time not available");
382 if (tiHighestInFileTime>tiLowestOutFileTime)
408 else if (tiFile<tiLowest)
445 else if (tiFile>tiHighest)
488 const char *depFileName;
491 if (depFileName && firstOutFileName) {
505 DBG_DEBUG(
NULL,
"Could not load depend file \"%s\"", depFileName);
509 if (depFileName==
NULL) {
510 DBG_DEBUG(
NULL,
"No depFileName for %s", firstOutFileName?firstOutFileName:
"<no outfile name>");
512 if (firstOutFileName==
NULL) {
529 DBG_DEBUG(
NULL,
"%s: No modification time, need rebuild", fileName);
544 DBG_DEBUG(
NULL,
"No modification time for dependency \"%s\", need rebuild", s);
547 if (difftime(tFile, tCurrent)<0.0) {
548 DBG_DEBUG(
NULL,
"File \"%s\" is newer than \"%s\", rebuild needed", s, fileName);
556 DBG_DEBUG(
NULL,
"No dependency is newer than file \"%s\", NO rebuild needed", fileName);
573 if (currentCommand) {
585 const char *buildMessage;
588 if (GWB_BuildSubCmd_List_Previous(currentCommand)==
NULL) {
597 fprintf(stdout,
"%s [%s]\n", buildMessage, cmd);
599 fprintf(stdout,
"%s %s\n", cmd, args);
603 DBG_ERROR(
NULL,
"Error creating logfile path for output redirection (%d)", rv);
609 if (folder && *folder)
618 DBG_ERROR(
NULL,
"Error starting command process (%d)", pstate);
640 GWB_BUILD_CMD_LIST2 *oldRunningQueue;
645 oldRunningQueue=bctx->runningQueue;
646 bctx->runningQueue=GWB_BuildCmd_List2_new();
648 while( (bcmd=GWB_BuildCmd_List2_GetFront(oldRunningQueue)) ) {
653 GWB_BuildCmd_List2_PopFront(oldRunningQueue);
666 DBG_INFO(
NULL,
"Command exited with result %d, ignoring", result);
670 DBG_INFO(
NULL,
"Command exited with result %d", result);
681 GWB_BuildCmd_List2_PushBack(bctx->finishedQueue, bcmd);
687 GWB_BuildCmd_List2_PushBack(bctx->runningQueue, bcmd);
690 GWB_BuildCmd_List2_free(oldRunningQueue);
703 nextCommand=GWB_BuildSubCmd_List_Next(currentCommand);
706 GWB_BuildCmd_List2_PushBack(bctx->waitingQueue, bcmd);
709 GWB_BuildCmd_List2_PushBack(bctx->finishedQueue, bcmd);
717 GWB_FILE_LIST2 *outFileList;
721 GWB_FILE_LIST2_ITERATOR *it;
723 it=GWB_File_List2_First(outFileList);
727 file=GWB_File_List2Iterator_Data(it);
729 GWB_BUILD_CMD_LIST2 *waitingCommands;
734 file=GWB_File_List2Iterator_Next(it);
736 GWB_File_List2Iterator_free(it);
746 GWB_BUILD_CMD_LIST2_ITERATOR *it;
748 it=GWB_BuildCmd_List2_First(waitingCommands);
752 bcmd=GWB_BuildCmd_List2Iterator_Data(it);
755 bcmd=GWB_BuildCmd_List2Iterator_Next(it);
758 GWB_BuildCmd_List2Iterator_free(it);
766 const char *fileName;
772 if (stat(fileName, &sb)==-1) {
786 const char *buildMessage;
791 fprintf(stderr,
"Output from [%s]\n", buildMessage?buildMessage:(
exe?
exe:
"NONE"));
const char * GWB_BuildSubCmd_GetCommand(const GWB_BUILD_SUBCMD *cmd)
static time_t _getHighestModificationTime(const GWEN_STRINGLIST *slFiles)
GWB_FILE_LIST2 * GWB_BuildCmd_GetInFileList2(const GWB_BUILD_CMD *bcmd)
static int _checkDependencies(GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *subCmd, const char *firstOutFileName)
#define DBG_ERROR(dbg_logger, format,...)
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
struct GWEN_STRINGLISTENTRYSTRUCT GWEN_STRINGLISTENTRY
GWB_BUILD_SUBCMD_LIST * GWB_BuildCmd_GetPrepareCommandList(const GWB_BUILD_CMD *bcmd)
int GWB_BuildCtx_CreateAndSetLogFilenameForSubCmd(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_SUBCMD *cmd)
#define DBG_DEBUG(dbg_logger, format,...)
const char * GWB_BuildSubCmd_GetDepFilePath(const GWB_BUILD_SUBCMD *cmd)
void GWB_BuildCmd_SetCurrentProcess(GWB_BUILD_CMD *bcmd, GWEN_PROCESS *process)
#define GWB_BUILD_SUBCMD_FLAGS_CHECK_DEPENDS
struct GWB_BUILD_CONTEXT GWB_BUILD_CONTEXT
static int _checkWaitingQueue(GWB_BUILD_CONTEXT *bctx, int maxStartAllowed)
int GWEN_SyncIo_Helper_ReadFile(const char *fName, GWEN_BUFFER *dbuf)
static void _finishCurrentCommand(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *currentCommand)
static int _checkRunningQueue(GWB_BUILD_CONTEXT *bctx)
int GWB_BuildCtx_FillWaitingQueue(GWB_BUILD_CONTEXT *bctx, const char *builderName)
const char * GWB_BuildCmd_GetFolder(const GWB_BUILD_CMD *bcmd)
#define GWB_BUILD_CMD_FLAGS_CHECK_DATES
GWB_BUILD_CMD_LIST2 * GWB_File_GetWaitingBuildCmdList2(const GWB_FILE *f)
#define GWB_BUILDCTX_PROCESS_WAIT_TIMEOUT
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
GWEN_STRINGLISTENTRY * GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl)
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
GWEN_STRINGLIST * GWB_BuildCtx_ReadAndTranslateDepfile(const char *folder, const char *fileName)
void GWEN_StringList_free(GWEN_STRINGLIST *sl)
const char * GWB_BuildSubCmd_GetArguments(const GWB_BUILD_SUBCMD *cmd)
static int _inFilesNewerThanOutFiles(const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles)
GWENHYWFAR_API GWEN_PROCESS_STATE GWEN_Process_CheckState(GWEN_PROCESS *pr)
GWEN_PROCESS * GWB_BuildCmd_GetCurrentProcess(const GWB_BUILD_CMD *bcmd)
int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl, const char *s, int take, int checkDouble)
int GWB_BuildCmd_DecBlockingFiles(GWB_BUILD_CMD *bcmd)
GWENHYWFAR_API void GWEN_Process_SetFilenameStdOut(GWEN_PROCESS *pr, const char *s)
#define GWB_BUILD_CMD_FLAGS_DEL_OUTFILES
GWB_FILE_LIST2 * GWB_BuildCmd_GetOutFileList2(const GWB_BUILD_CMD *bcmd)
struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST
static void _abortCommandsInQueue(GWB_BUILD_CMD_LIST2 *cmdList)
#define GWEN_ERROR_GENERIC
const char * GWB_BuildSubCmd_GetBuildMessage(const GWB_BUILD_SUBCMD *cmd)
#define GWB_BUILD_SUBCMD_FLAGS_IGNORE_RESULT
GWENHYWFAR_API int GWEN_Process_GetResult(GWEN_PROCESS *pr)
GWB_BUILD_SUBCMD_LIST * GWB_BuildCmd_GetBuildCommandList(const GWB_BUILD_CMD *bcmd)
void GWEN_Buffer_free(GWEN_BUFFER *bf)
struct GWB_BUILD_SUBCMD GWB_BUILD_SUBCMD
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
static int _checkDatesOfFileAgainstList(const char *fileName, const GWEN_STRINGLIST *sl)
static time_t _getLowestModificationTime(const GWEN_STRINGLIST *slFiles)
unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
static void _abortAllCommands(GWB_BUILD_CONTEXT *bctx)
GWENHYWFAR_API GWEN_PROCESS * GWEN_Process_new(void)
static int _waitForRunningJobs(GWB_BUILD_CONTEXT *bctx)
const char * GWEN_StringList_FirstString(const GWEN_STRINGLIST *l)
const char * GWB_BuildSubCmd_GetLogFilename(const GWB_BUILD_SUBCMD *cmd)
struct GWEN_PROCESS GWEN_PROCESS
static void _decBlockingFilesInWaitingBuildCommands(GWB_BUILD_CMD_LIST2 *waitingCommands)
GWB_BUILD_SUBCMD * GWB_BuildCmd_GetCurrentCommand(const GWB_BUILD_CMD *bcmd)
uint32_t GWB_BuildSubCmd_GetFlags(const GWB_BUILD_SUBCMD *cmd)
time_t GWBUILD_GetModificationTimeOfFile(const char *filename)
int GWB_BuildCtx_SetupDependencies(GWB_BUILD_CONTEXT *bctx)
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
void GWB_File_WriteFileNameToTopBuildDirString(const GWB_FILE *file, const char *initialSourceDir, GWEN_BUFFER *fbuf)
struct GWB_BUILD_CMD GWB_BUILD_CMD
GWEN_STRINGLIST * _fileListToTopBuildDirStringList(const char *initialSourceDir, GWB_FILE_LIST2 *fileList)
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)
static void _printCmdOutputIfNotEmptyAndDeleteFile(GWB_BUILD_SUBCMD *cmd)
static int _startCommand(GWB_BUILD_CONTEXT *bctx, GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slOutFiles)
#define GWEN_ERROR_TIMEOUT
static int _needRunCurrentCommand(GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles)
#define DBG_INFO(dbg_logger, format,...)
GWEN_STRINGLIST * GWB_File_FileListToTopBuildDirStringList(const GWB_FILE_LIST2 *fileList, const char *initialSourceDir)
static void _createCommandQueues(GWB_BUILD_CONTEXT *bctx)
GWENHYWFAR_API void GWEN_Process_SetFilenameStdErr(GWEN_PROCESS *pr, const char *s)
uint32_t GWB_BuildCmd_GetFlags(const GWB_BUILD_CMD *bcmd)
GWEN_STRINGLIST * GWEN_StringList_new(void)
int GWB_BuildCmd_GetBlockingFiles(const GWB_BUILD_CMD *bcmd)
int GWB_BuildCtx_Run(GWB_BUILD_CONTEXT *bctx, int maxConcurrentJobs, int usePrepareCommands, const char *builderName)
static void _unlinkFilesInStringList(const GWEN_STRINGLIST *slFiles)
GWENHYWFAR_API void GWEN_Process_SetFolder(GWEN_PROCESS *pr, const char *s)
static void _signalJobFinished(GWB_BUILD_CMD *bcmd)
void GWB_BuildCmd_SetCurrentCommand(GWB_BUILD_CMD *bcmd, GWB_BUILD_SUBCMD *cmd)