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> 30 #define GWB_BUILDCTX_PROCESS_WAIT_TIMEOUT 10.0 74 if (GWB_BuildCmd_List2_GetSize(bctx->waitingQueue)==0) {
75 fprintf(stdout,
"Nothing to do.\n");
79 waitingJobs=GWB_BuildCmd_List2_GetSize(bctx->waitingQueue);
80 runningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
81 while(waitingJobs+runningJobs) {
86 if (startedCommands<0) {
93 if (changedCommands<0) {
99 if (startedCommands==0 && changedCommands==0) {
100 if (runningJobs==0) {
101 DBG_ERROR(
NULL,
"ERROR: No running jobs and none could be started, maybe circular dependencies?");
110 waitingJobs=GWB_BuildCmd_List2_GetSize(bctx->waitingQueue);
111 runningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
114 GWB_BuildCmd_List2_free(bctx->waitingQueue);
115 bctx->waitingQueue=
NULL;
116 GWB_BuildCmd_List2_free(bctx->runningQueue);
117 bctx->runningQueue=
NULL;
118 GWB_BuildCmd_List2_free(bctx->finishedQueue);
119 bctx->finishedQueue=
NULL;
132 numRunningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
134 fprintf(stderr,
"NOTICE: Waiting for %d jobs.\n", numRunningJobs);
135 while(numRunningJobs) {
136 int numChangedCommands;
140 if (numChangedCommands<0) {
143 numRunningJobs=GWB_BuildCmd_List2_GetSize(bctx->runningQueue);
145 if (numRunningJobs>0) {
149 delta=difftime(currentTime, startTime);
151 DBG_ERROR(
NULL,
"%d jobs still running after %f.1 seconds, aborting", numRunningJobs, delta);
168 GWB_BuildCmd_List2_free(bctx->waitingQueue);
169 bctx->waitingQueue=
NULL;
172 GWB_BuildCmd_List2_free(bctx->runningQueue);
173 bctx->runningQueue=
NULL;
176 GWB_BuildCmd_List2_free(bctx->finishedQueue);
177 bctx->finishedQueue=
NULL;
186 while( (bcmd=GWB_BuildCmd_List2_GetFront(cmdList)) ) {
187 GWB_BuildCmd_List2_PopFront(cmdList);
197 GWB_BUILD_CMD_LIST2_ITERATOR *it;
199 it=GWB_BuildCmd_List2_First(bctx->commandList);
203 bcmd=GWB_BuildCmd_List2Iterator_Data(it);
205 GWB_BUILD_SUBCMD_LIST *cmdList;
207 if (forPrepareCommands)
213 bcmd=GWB_BuildCmd_List2Iterator_Next(it);
215 GWB_BuildCmd_List2Iterator_free(it);
223 bctx->waitingQueue=GWB_BuildCmd_List2_new();
224 bctx->finishedQueue=GWB_BuildCmd_List2_new();
225 bctx->runningQueue=GWB_BuildCmd_List2_new();
232 GWB_BUILD_CMD_LIST2 *oldQueue;
237 oldQueue=bctx->waitingQueue;
238 bctx->waitingQueue=GWB_BuildCmd_List2_new();
240 while( (bcmd=GWB_BuildCmd_List2_GetFront(oldQueue)) ) {
242 GWB_BuildCmd_List2_PopFront(oldQueue);
243 if (started<maxStartAllowed) {
250 bctx->initialSourceDir);
252 bctx->initialSourceDir);
257 GWB_BuildCmd_List2_PushBack(bctx->finishedQueue, bcmd);
261 GWB_BuildCmd_List2_PushBack(bctx->runningQueue, bcmd);
273 GWB_BuildCmd_List2_PushBack(bctx->waitingQueue, bcmd);
276 GWB_BuildCmd_List2_PushBack(bctx->waitingQueue, bcmd);
278 GWB_BuildCmd_List2_free(oldQueue);
289 GWB_FILE_LIST2_ITERATOR *it;
291 it=GWB_File_List2_First(fileList);
299 file=GWB_File_List2Iterator_Data(it);
304 file=GWB_File_List2Iterator_Next(it);
307 GWB_File_List2Iterator_free(it);
326 if (currentCommand) {
328 uint32_t subCmdFlags;
336 DBG_INFO(
NULL,
"Input files newer than output files, rebuild needed");
349 DBG_INFO(
NULL,
"Dependencies flag NO rebuild needed (%d)", rv);
352 DBG_INFO(
NULL,
"Dependencies flag rebuild needed (%d)", rv);
366 time_t tiHighestInFileTime;
367 time_t tiLowestOutFileTime;
371 if (tiHighestInFileTime==0 || tiLowestOutFileTime==0) {
372 DBG_INFO(
NULL,
"Either input or output time not available");
375 if (tiHighestInFileTime>tiLowestOutFileTime)
401 else if (tiFile<tiLowest)
438 else if (tiFile>tiHighest)
481 const char *depFileName;
484 if (depFileName && firstOutFileName) {
498 DBG_DEBUG(
NULL,
"Could not load depend file \"%s\"", depFileName);
502 if (depFileName==
NULL) {
503 DBG_DEBUG(
NULL,
"No depFileName for %s", firstOutFileName?firstOutFileName:
"<no outfile name>");
505 if (firstOutFileName==
NULL) {
522 DBG_DEBUG(
NULL,
"%s: No modification time, need rebuild", fileName);
537 DBG_DEBUG(
NULL,
"No modification time for dependency \"%s\", need rebuild", s);
540 if (difftime(tFile, tCurrent)<0.0) {
541 DBG_DEBUG(
NULL,
"File \"%s\" is newer than \"%s\", rebuild needed", s, fileName);
549 DBG_DEBUG(
NULL,
"No dependency is newer than file \"%s\", NO rebuild needed", fileName);
566 if (currentCommand) {
578 const char *buildMessage;
580 if (GWB_BuildSubCmd_List_Previous(currentCommand)==
NULL) {
589 fprintf(stdout,
"%s [%s]\n", buildMessage, cmd);
591 fprintf(stdout,
"%s %s\n", cmd, args);
594 if (folder && *folder)
599 DBG_ERROR(
NULL,
"Error starting command process (%d)", pstate);
621 GWB_BUILD_CMD_LIST2 *oldRunningQueue;
626 oldRunningQueue=bctx->runningQueue;
627 bctx->runningQueue=GWB_BuildCmd_List2_new();
629 while( (bcmd=GWB_BuildCmd_List2_GetFront(oldRunningQueue)) ) {
634 GWB_BuildCmd_List2_PopFront(oldRunningQueue);
645 DBG_INFO(
NULL,
"Command exited with result %d", result);
646 GWB_BuildCmd_List2_PushBack(bctx->finishedQueue, bcmd);
654 GWB_BuildCmd_List2_PushBack(bctx->finishedQueue, bcmd);
660 GWB_BuildCmd_List2_PushBack(bctx->runningQueue, bcmd);
663 GWB_BuildCmd_List2_free(oldRunningQueue);
676 nextCommand=GWB_BuildSubCmd_List_Next(currentCommand);
679 GWB_BuildCmd_List2_PushBack(bctx->waitingQueue, bcmd);
682 GWB_BuildCmd_List2_PushBack(bctx->finishedQueue, bcmd);
690 GWB_FILE_LIST2 *outFileList;
694 GWB_FILE_LIST2_ITERATOR *it;
696 it=GWB_File_List2_First(outFileList);
700 file=GWB_File_List2Iterator_Data(it);
702 GWB_BUILD_CMD_LIST2 *waitingCommands;
707 file=GWB_File_List2Iterator_Next(it);
709 GWB_File_List2Iterator_free(it);
719 GWB_BUILD_CMD_LIST2_ITERATOR *it;
721 it=GWB_BuildCmd_List2_First(waitingCommands);
725 bcmd=GWB_BuildCmd_List2Iterator_Data(it);
728 bcmd=GWB_BuildCmd_List2Iterator_Next(it);
731 GWB_BuildCmd_List2Iterator_free(it);
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)
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)
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)
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)
#define DBG_DEBUG(dbg_logger, format, args...)
int GWB_BuildCmd_DecBlockingFiles(GWB_BUILD_CMD *bcmd)
#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)
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)
static int _startCommand(GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slOutFiles)
unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
#define DBG_ERROR(dbg_logger, format, args...)
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)
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)
#define DBG_INFO(dbg_logger, format, args...)
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)
#define GWEN_ERROR_TIMEOUT
static int _needRunCurrentCommand(GWB_BUILD_CMD *bcmd, const GWEN_STRINGLIST *slInFiles, const GWEN_STRINGLIST *slOutFiles)
GWEN_STRINGLIST * GWB_File_FileListToTopBuildDirStringList(const GWB_FILE_LIST2 *fileList, const char *initialSourceDir)
static void _createCommandQueues(GWB_BUILD_CONTEXT *bctx)
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)