Modified build system to detect pch changes *gemini
This commit is contained in:
+202
-58
@@ -185,19 +185,26 @@ static int64_t GetNewestSourceTimeRecursive(const char* dirPath)
|
||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
int64_t subNewest = GetNewestSourceTimeRecursive(fullPath);
|
||||
if (subNewest > newest) newest = subNewest;
|
||||
if (subNewest > newest)
|
||||
{
|
||||
newest = subNewest;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EndsWithNoCase(findData.cFileName, ".cpp") || EndsWithNoCase(findData.cFileName, ".h") ||
|
||||
EndsWithNoCase(findData.cFileName, ".hpp") || EndsWithNoCase(findData.cFileName, ".inl") ||
|
||||
EndsWithNoCase(findData.cFileName, ".c"))
|
||||
EndsWithNoCase(findData.cFileName, ".c") || EndsWithNoCase(findData.cFileName, ".obj") ||
|
||||
EndsWithNoCase(findData.cFileName, ".pch") || EndsWithNoCase(findData.cFileName, ".lib"))
|
||||
{
|
||||
ULARGE_INTEGER li;
|
||||
li.LowPart = findData.ftLastWriteTime.dwLowDateTime;
|
||||
li.HighPart = findData.ftLastWriteTime.dwHighDateTime;
|
||||
int64_t ft = (int64_t)li.QuadPart;
|
||||
if (ft > newest) newest = ft;
|
||||
if (ft > newest)
|
||||
{
|
||||
newest = ft;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -510,23 +517,41 @@ typedef struct
|
||||
{
|
||||
char Path[MAX_PATH_LEN];
|
||||
int64_t Time;
|
||||
} DirCacheEntry;
|
||||
} PathCacheEntry;
|
||||
|
||||
static DirCacheEntry g_DirCache[64];
|
||||
static int g_DirCacheCount = 0;
|
||||
static PathCacheEntry g_PathCache[256];
|
||||
static int g_PathCacheCount = 0;
|
||||
|
||||
static int64_t GetDirTime(const char* dir)
|
||||
static void ClearPathCache(void)
|
||||
{
|
||||
for (int k = 0; k < g_DirCacheCount; k++)
|
||||
g_PathCacheCount = 0;
|
||||
}
|
||||
|
||||
static int64_t GetPathTime(const char* path)
|
||||
{
|
||||
for (int k = 0; k < g_PathCacheCount; k++)
|
||||
{
|
||||
if (_stricmp(g_DirCache[k].Path, dir) == 0) return g_DirCache[k].Time;
|
||||
if (_stricmp(g_PathCache[k].Path, path) == 0)
|
||||
{
|
||||
return g_PathCache[k].Time;
|
||||
}
|
||||
}
|
||||
int64_t t = GetNewestSourceTimeRecursive(dir);
|
||||
if (g_DirCacheCount < 64)
|
||||
|
||||
int64_t t = 0;
|
||||
if (DirectoryExists(path))
|
||||
{
|
||||
strncpy_s(g_DirCache[g_DirCacheCount].Path, MAX_PATH_LEN, dir, _TRUNCATE);
|
||||
g_DirCache[g_DirCacheCount].Time = t;
|
||||
g_DirCacheCount++;
|
||||
t = GetNewestSourceTimeRecursive(path);
|
||||
}
|
||||
else if (FileExists(path))
|
||||
{
|
||||
t = GetFileModTimeInt64(path);
|
||||
}
|
||||
|
||||
if (g_PathCacheCount < 256)
|
||||
{
|
||||
strncpy_s(g_PathCache[g_PathCacheCount].Path, MAX_PATH_LEN, path, _TRUNCATE);
|
||||
g_PathCache[g_PathCacheCount].Time = t;
|
||||
g_PathCacheCount++;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
@@ -552,34 +577,58 @@ static int ExecuteIncrementalCompile(const char* srcDir, const char* objDir, con
|
||||
snprintf(objSearchPath, sizeof(objSearchPath), "%s\\*.obj", objDir);
|
||||
WIN32_FIND_DATAA findData;
|
||||
HANDLE hFind = FindFirstFileA(objSearchPath, &findData);
|
||||
if (hFind != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
char baseName[256];
|
||||
strcpy_s(baseName, sizeof(baseName), findData.cFileName);
|
||||
char* ext = strrchr(baseName, '.');
|
||||
if (ext) *ext = '\0';
|
||||
if (ext)
|
||||
{
|
||||
*ext = '\0';
|
||||
}
|
||||
|
||||
bool foundSrc = false;
|
||||
for (int i = 0; i < cppFiles->Count; i++) {
|
||||
for (int i = 0; i < cppFiles->Count; i++)
|
||||
{
|
||||
const char* srcPath = cppFiles->Paths[i];
|
||||
const char* srcFile = strrchr(srcPath, '\\');
|
||||
if (!srcFile) srcFile = strrchr(srcPath, '/');
|
||||
if (!srcFile) srcFile = srcPath; else srcFile++;
|
||||
if (!srcFile)
|
||||
{
|
||||
srcFile = strrchr(srcPath, '/');
|
||||
}
|
||||
if (!srcFile)
|
||||
{
|
||||
srcFile = srcPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcFile++;
|
||||
}
|
||||
|
||||
char srcBase[256];
|
||||
strcpy_s(srcBase, sizeof(srcBase), srcFile);
|
||||
char* srcExt = strrchr(srcBase, '.');
|
||||
if (srcExt) *srcExt = '\0';
|
||||
if (srcExt)
|
||||
{
|
||||
*srcExt = '\0';
|
||||
}
|
||||
|
||||
if (_stricmp(baseName, srcBase) == 0) {
|
||||
if (_stricmp(baseName, srcBase) == 0)
|
||||
{
|
||||
foundSrc = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundSrc) {
|
||||
if (!foundSrc)
|
||||
{
|
||||
char fullObjPath[MAX_PATH_LEN];
|
||||
snprintf(fullObjPath, sizeof(fullObjPath), "%s\\%s", objDir, findData.cFileName);
|
||||
DeleteFileA(fullObjPath);
|
||||
@@ -596,32 +645,54 @@ static int ExecuteIncrementalCompile(const char* srcDir, const char* objDir, con
|
||||
{
|
||||
const char* srcPath = cppFiles->Paths[i];
|
||||
const char* fileName = strrchr(srcPath, '\\');
|
||||
if (!fileName) fileName = strrchr(srcPath, '/');
|
||||
if (!fileName) fileName = srcPath; else fileName++;
|
||||
if (!fileName)
|
||||
{
|
||||
fileName = strrchr(srcPath, '/');
|
||||
}
|
||||
if (!fileName)
|
||||
{
|
||||
fileName = srcPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
fileName++;
|
||||
}
|
||||
|
||||
char objPath[MAX_PATH_LEN];
|
||||
sprintf_s(objPath, sizeof(objPath), "%s\\%s", objDir, fileName);
|
||||
char* ext = strrchr(objPath, '.');
|
||||
if (ext) strcpy_s(ext, sizeof(objPath) - (ext - objPath), ".obj");
|
||||
if (ext)
|
||||
{
|
||||
strcpy_s(ext, sizeof(objPath) - (ext - objPath), ".obj");
|
||||
}
|
||||
|
||||
bool dirty = false;
|
||||
if (!FileExists(objPath)) {
|
||||
if (!FileExists(objPath))
|
||||
{
|
||||
dirty = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t objTime = GetFileModTimeInt64(objPath);
|
||||
if (GetFileModTimeInt64(srcPath) > objTime || maxDepTime > objTime) {
|
||||
if (GetFileModTimeInt64(srcPath) > objTime || maxDepTime > objTime)
|
||||
{
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
if (dirtyCount > 0) strcat_s(dirtyFiles, MAX_FILES, " ");
|
||||
if (dirty)
|
||||
{
|
||||
if (dirtyCount > 0)
|
||||
{
|
||||
strcat_s(dirtyFiles, MAX_FILES, " ");
|
||||
}
|
||||
strcat_s(dirtyFiles, MAX_FILES, srcPath);
|
||||
dirtyCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirtyCount == 0) {
|
||||
if (dirtyCount == 0)
|
||||
{
|
||||
printf("[SKIP / UP-TO-DATE] %s [All objects up to date]\n", objDir);
|
||||
return 0;
|
||||
}
|
||||
@@ -846,7 +917,7 @@ static int CommandRunPlan(int argc, char* argv[])
|
||||
printf("Compiling Targets [%s]...\n", cfg->Name);
|
||||
printf("==============================================================================\n");
|
||||
|
||||
g_DirCacheCount = 0;
|
||||
ClearPathCache();
|
||||
bool anyNeedBuild = false;
|
||||
|
||||
for (int j = 0; j < cfg->StepCount; j++)
|
||||
@@ -857,39 +928,81 @@ static int CommandRunPlan(int argc, char* argv[])
|
||||
while (*cur)
|
||||
{
|
||||
const char* nextPipe = strchr(cur, '|');
|
||||
char dirPath[MAX_PATH_LEN] = { 0 };
|
||||
char depPath[MAX_PATH_LEN] = { 0 };
|
||||
if (nextPipe)
|
||||
{
|
||||
int dLen = (int)(nextPipe - cur);
|
||||
if (dLen >= (int)sizeof(dirPath)) dLen = (int)sizeof(dirPath) - 1;
|
||||
memcpy(dirPath, cur, dLen);
|
||||
dirPath[dLen] = '\0';
|
||||
if (dLen >= (int)sizeof(depPath))
|
||||
{
|
||||
dLen = (int)sizeof(depPath) - 1;
|
||||
}
|
||||
memcpy(depPath, cur, dLen);
|
||||
depPath[dLen] = '\0';
|
||||
cur = nextPipe + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy_s(dirPath, sizeof(dirPath), cur);
|
||||
strcpy_s(depPath, sizeof(depPath), cur);
|
||||
cur += strlen(cur);
|
||||
}
|
||||
if (dirPath[0] != '\0')
|
||||
if (depPath[0] != '\0')
|
||||
{
|
||||
int64_t t = GetDirTime(dirPath);
|
||||
if (t > maxTime) maxTime = t;
|
||||
int64_t t = GetPathTime(depPath);
|
||||
if (t > maxTime)
|
||||
{
|
||||
maxTime = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool needCompile = unityChanged;
|
||||
if (!needCompile)
|
||||
{
|
||||
if (!FileExists(step->OutputFile))
|
||||
const char* outCur = step->OutputFile;
|
||||
int64_t minOutTime = 0x7FFFFFFFFFFFFFFFLL;
|
||||
bool hasOutputs = false;
|
||||
|
||||
while (*outCur)
|
||||
{
|
||||
const char* nextPipe = strchr(outCur, '|');
|
||||
char singleOut[MAX_PATH_LEN] = { 0 };
|
||||
if (nextPipe)
|
||||
{
|
||||
int oLen = (int)(nextPipe - outCur);
|
||||
if (oLen >= (int)sizeof(singleOut))
|
||||
{
|
||||
oLen = (int)sizeof(singleOut) - 1;
|
||||
}
|
||||
memcpy(singleOut, outCur, oLen);
|
||||
singleOut[oLen] = '\0';
|
||||
outCur = nextPipe + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy_s(singleOut, sizeof(singleOut), outCur);
|
||||
outCur += strlen(outCur);
|
||||
}
|
||||
|
||||
if (singleOut[0] != '\0')
|
||||
{
|
||||
hasOutputs = true;
|
||||
if (!FileExists(singleOut) && !DirectoryExists(singleOut))
|
||||
{
|
||||
needCompile = true;
|
||||
break;
|
||||
}
|
||||
int64_t oTime = GetPathTime(singleOut);
|
||||
if (oTime < minOutTime)
|
||||
{
|
||||
minOutTime = oTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!needCompile && hasOutputs && minOutTime < maxTime)
|
||||
{
|
||||
needCompile = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t outTime = GetFileModTimeInt64(step->OutputFile);
|
||||
if (outTime < maxTime) needCompile = true;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n--- %s ---\n", step->StepName);
|
||||
@@ -901,12 +1014,14 @@ static int CommandRunPlan(int argc, char* argv[])
|
||||
int res = ExecuteIncrementalCompile(step->IncSrc, step->IncObj, step->Command, maxTime);
|
||||
QueryPerformanceCounter(&tEnd);
|
||||
AppendTiming(step->StepName, (double)(tEnd.QuadPart - tStart.QuadPart) / (double)perfFreq.QuadPart);
|
||||
if (res != 0) {
|
||||
if (res != 0)
|
||||
{
|
||||
printf("[BUILD FAILED] Command failed with exit code %d.\n", res);
|
||||
return res;
|
||||
}
|
||||
ClearPathCache();
|
||||
anyNeedBuild = true;
|
||||
anyBuilt = true;
|
||||
anyBuilt = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -932,17 +1047,46 @@ static int CommandRunPlan(int argc, char* argv[])
|
||||
return res;
|
||||
}
|
||||
|
||||
char builtOut[MAX_PATH_LEN + 2];
|
||||
sprintf_s(builtOut, sizeof(builtOut), "%s\n", step->OutputFile);
|
||||
ClearPathCache();
|
||||
|
||||
HANDLE hFile = CreateFileA("Intermediate\\built_outputs.tmp", FILE_APPEND_DATA, FILE_SHARE_READ, NULL,
|
||||
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
const char* outCur = step->OutputFile;
|
||||
while (*outCur)
|
||||
{
|
||||
DWORD written = 0;
|
||||
WriteFile(hFile, builtOut, (DWORD)strlen(builtOut), &written, NULL);
|
||||
CloseHandle(hFile);
|
||||
const char* nextPipe = strchr(outCur, '|');
|
||||
char singleOut[MAX_PATH_LEN] = { 0 };
|
||||
if (nextPipe)
|
||||
{
|
||||
int oLen = (int)(nextPipe - outCur);
|
||||
if (oLen >= (int)sizeof(singleOut))
|
||||
{
|
||||
oLen = (int)sizeof(singleOut) - 1;
|
||||
}
|
||||
memcpy(singleOut, outCur, oLen);
|
||||
singleOut[oLen] = '\0';
|
||||
outCur = nextPipe + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy_s(singleOut, sizeof(singleOut), outCur);
|
||||
outCur += strlen(outCur);
|
||||
}
|
||||
|
||||
if (singleOut[0] != '\0')
|
||||
{
|
||||
char builtOut[MAX_PATH_LEN + 2];
|
||||
sprintf_s(builtOut, sizeof(builtOut), "%s\n", singleOut);
|
||||
|
||||
HANDLE hFile = CreateFileA("Intermediate\\built_outputs.tmp", FILE_APPEND_DATA, FILE_SHARE_READ, NULL,
|
||||
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD written = 0;
|
||||
WriteFile(hFile, builtOut, (DWORD)strlen(builtOut), &written, NULL);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
anyBuilt = true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user