Modified build system to detect pch changes *gemini

This commit is contained in:
2026-08-16 13:13:51 -04:00
parent 5566f76a94
commit 3e7216f57d
4 changed files with 220 additions and 78 deletions
-2
View File
@@ -22,11 +22,9 @@
#include <list>
#include <memory>
#include <mutex>
#include <new>
#include <queue>
#include <source_location>
#include <stdexcept>
#include <string>
#include <thread>
#include <type_traits>
#include <vector>
+2 -2
View File
@@ -15,5 +15,5 @@ namespace Juliet
namespace Juliet::Internal
{
extern JULIET_API IOStream* IOFromFile(String filename, String mode);
}
IOStream* IOFromFile(String filename, String mode);
} // namespace Juliet::Internal
+16 -16
View File
@@ -9,7 +9,7 @@ cd /d "%~dp0\.."
set BUILD_TOOL=misc\build_system.exe
set BUILD_SRC=tools\build_system.c
set BUILD_TOOL_VER=1.5
set BUILD_TOOL_VER=1.6
set COMMAND_GEN_VS=0
@@ -189,13 +189,13 @@ if defined IMGUI_UNITY_SRCS set IMGUI_OBJS=Intermediate\x64-!CFG!\ImGui_Unity*.o
:: --- Juliet PCH ---
echo STEP Building Juliet PCH [!CFG!]>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\Juliet_PCH.obj>>"!PLAN_FILE!"
echo DEPENDS Juliet\src\Core\PCH.cpp>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\Juliet_PCH.obj^|Intermediate\x64-!CFG!\Juliet.pch>>"!PLAN_FILE!"
echo DEPENDS Juliet\src\Core\PCH.cpp^|Juliet\include\Core\PCH.h>>"!PLAN_FILE!"
echo COMMAND %COMPILER% %COMPILER_FLAGS% /DIMGUI_API=__declspec^(dllexport^) /DJULIET_EXPORT /Yc"Core/PCH.h" /Fp"Intermediate\x64-!CFG!\Juliet.pch" /c Juliet\src\Core\PCH.cpp /Fo"Intermediate\x64-!CFG!\Juliet_PCH.obj">>"!PLAN_FILE!"
echo STEP Compiling Juliet Objs [!CFG!]>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\Juliet_Objs>>"!PLAN_FILE!"
echo DEPENDS Juliet>>"!PLAN_FILE!"
echo DEPENDS Juliet^|Intermediate\x64-!CFG!\Juliet.pch>>"!PLAN_FILE!"
echo INC_SRC Intermediate\Juliet>>"!PLAN_FILE!"
echo INC_OBJ Intermediate\x64-!CFG!\Juliet_Objs>>"!PLAN_FILE!"
echo COMMAND %COMPILER% %COMPILER_FLAGS% /MP /DIMGUI_API=__declspec^(dllexport^) /DJULIET_EXPORT /FI"Core/PCH.h" /Yu"Core/PCH.h" /Fp"Intermediate\x64-!CFG!\Juliet.pch" /c /Fo"Intermediate\x64-!CFG!\Juliet_Objs\\">>"!PLAN_FILE!"
@@ -215,13 +215,13 @@ if !BUILD_GAME_DLL! equ 1 (
:: --- Game PCH ---
echo STEP Building Game PCH [!CFG!]>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\Game_PCH.obj>>"!PLAN_FILE!"
echo DEPENDS Juliet\src\Core\PCH.cpp>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\Game_PCH.obj^|Intermediate\x64-!CFG!\Game.pch>>"!PLAN_FILE!"
echo DEPENDS Juliet\src\Core\PCH.cpp^|Juliet\include\Core\PCH.h>>"!PLAN_FILE!"
echo COMMAND %COMPILER% %COMPILER_FLAGS% /DIMGUI_API=__declspec^(dllimport^) /DJULIET_EXPORT /Yc"Core/PCH.h" /Fp"Intermediate\x64-!CFG!\Game.pch" /c Juliet\src\Core\PCH.cpp /Fo"Intermediate\x64-!CFG!\Game_PCH.obj">>"!PLAN_FILE!"
echo STEP Compiling Game Objs [!CFG!]>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\Game_Objs>>"!PLAN_FILE!"
echo DEPENDS Game^|Juliet>>"!PLAN_FILE!"
echo DEPENDS Game^|Juliet^|Intermediate\x64-!CFG!\Game.pch>>"!PLAN_FILE!"
echo INC_SRC Intermediate\Game>>"!PLAN_FILE!"
echo INC_OBJ Intermediate\x64-!CFG!\Game_Objs>>"!PLAN_FILE!"
echo COMMAND %COMPILER% %COMPILER_FLAGS% /MP /DIMGUI_API=__declspec^(dllimport^) /DJULIET_EXPORT /FI"Core/PCH.h" /Yu"Core/PCH.h" /Fp"Intermediate\x64-!CFG!\Game.pch" /c /Fo"Intermediate\x64-!CFG!\Game_Objs\\">>"!PLAN_FILE!"
@@ -238,13 +238,13 @@ if !BUILD_GAME_DLL! equ 1 (
if !TARGET_JULIET! equ 1 (
:: --- JulietApp PCH ---
echo STEP Building JulietApp PCH [!CFG!]>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\JulietApp_PCH.obj>>"!PLAN_FILE!"
echo DEPENDS Juliet\src\Core\PCH.cpp>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\JulietApp_PCH.obj^|Intermediate\x64-!CFG!\JulietApp.pch>>"!PLAN_FILE!"
echo DEPENDS Juliet\src\Core\PCH.cpp^|Juliet\include\Core\PCH.h>>"!PLAN_FILE!"
echo COMMAND %COMPILER% %COMPILER_FLAGS% /DIMGUI_API=__declspec^(dllimport^) /Yc"Core/PCH.h" /Fp"Intermediate\x64-!CFG!\JulietApp.pch" /c Juliet\src\Core\PCH.cpp /Fo"Intermediate\x64-!CFG!\JulietApp_PCH.obj">>"!PLAN_FILE!"
echo STEP Compiling JulietApp Objs [!CFG!]>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\JulietApp_Objs>>"!PLAN_FILE!"
echo DEPENDS JulietApp^|Juliet>>"!PLAN_FILE!"
echo DEPENDS JulietApp^|Juliet^|Intermediate\x64-!CFG!\JulietApp.pch>>"!PLAN_FILE!"
echo INC_SRC Intermediate\JulietApp>>"!PLAN_FILE!"
echo INC_OBJ Intermediate\x64-!CFG!\JulietApp_Objs>>"!PLAN_FILE!"
echo COMMAND %COMPILER% %COMPILER_FLAGS% /MP /DIMGUI_API=__declspec^(dllimport^) /FI"Core/PCH.h" /Yu"Core/PCH.h" /Fp"Intermediate\x64-!CFG!\JulietApp.pch" /c /Fo"Intermediate\x64-!CFG!\JulietApp_Objs\\">>"!PLAN_FILE!"
@@ -261,13 +261,13 @@ if !TARGET_JULIET! equ 1 (
if !TARGET_ROMEO! equ 1 (
:: --- Romeo PCH ---
echo STEP Building Romeo PCH [!CFG!]>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\Romeo_PCH.obj>>"!PLAN_FILE!"
echo DEPENDS Juliet\src\Core\PCH.cpp>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\Romeo_PCH.obj^|Intermediate\x64-!CFG!\Romeo.pch>>"!PLAN_FILE!"
echo DEPENDS Juliet\src\Core\PCH.cpp^|Juliet\include\Core\PCH.h>>"!PLAN_FILE!"
echo COMMAND %COMPILER% %COMPILER_FLAGS% /DIMGUI_API=__declspec^(dllimport^) /Yc"Core/PCH.h" /Fp"Intermediate\x64-!CFG!\Romeo.pch" /c Juliet\src\Core\PCH.cpp /Fo"Intermediate\x64-!CFG!\Romeo_PCH.obj">>"!PLAN_FILE!"
echo STEP Compiling Romeo Objs [!CFG!]>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\Romeo_Objs>>"!PLAN_FILE!"
echo DEPENDS Romeo^|Juliet>>"!PLAN_FILE!"
echo DEPENDS Romeo^|Juliet^|Intermediate\x64-!CFG!\Romeo.pch>>"!PLAN_FILE!"
echo INC_SRC Intermediate\Romeo>>"!PLAN_FILE!"
echo INC_OBJ Intermediate\x64-!CFG!\Romeo_Objs>>"!PLAN_FILE!"
echo COMMAND %COMPILER% %COMPILER_FLAGS% /MP /DIMGUI_API=__declspec^(dllimport^) /FI"Core/PCH.h" /Yu"Core/PCH.h" /Fp"Intermediate\x64-!CFG!\Romeo.pch" /c /Fo"Intermediate\x64-!CFG!\Romeo_Objs\\">>"!PLAN_FILE!"
@@ -284,13 +284,13 @@ if !TARGET_ROMEO! equ 1 (
if !TARGET_SHADER! equ 1 (
:: --- JulietShaderCompiler PCH ---
echo STEP Building JulietShaderCompiler PCH [!CFG!]>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\JulietShaderCompiler_PCH.obj>>"!PLAN_FILE!"
echo DEPENDS Juliet\src\Core\PCH.cpp>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\JulietShaderCompiler_PCH.obj^|Intermediate\x64-!CFG!\JulietShaderCompiler.pch>>"!PLAN_FILE!"
echo DEPENDS Juliet\src\Core\PCH.cpp^|Juliet\include\Core\PCH.h>>"!PLAN_FILE!"
echo COMMAND %COMPILER% %COMPILER_FLAGS% /DIMGUI_API=__declspec^(dllimport^) /IJulietShaderCompiler /Yc"Core/PCH.h" /Fp"Intermediate\x64-!CFG!\JulietShaderCompiler.pch" /c Juliet\src\Core\PCH.cpp /Fo"Intermediate\x64-!CFG!\JulietShaderCompiler_PCH.obj">>"!PLAN_FILE!"
echo STEP Compiling JulietShaderCompiler Objs [!CFG!]>>"!PLAN_FILE!"
echo OUTPUT Intermediate\x64-!CFG!\JulietShaderCompiler_Objs>>"!PLAN_FILE!"
echo DEPENDS JulietShaderCompiler^|Juliet>>"!PLAN_FILE!"
echo DEPENDS JulietShaderCompiler^|Juliet^|Intermediate\x64-!CFG!\JulietShaderCompiler.pch>>"!PLAN_FILE!"
echo INC_SRC Intermediate\JulietShaderCompiler>>"!PLAN_FILE!"
echo INC_OBJ Intermediate\x64-!CFG!\JulietShaderCompiler_Objs>>"!PLAN_FILE!"
echo COMMAND %COMPILER% %COMPILER_FLAGS% /MP /DIMGUI_API=__declspec^(dllimport^) /IJulietShaderCompiler /FI"Core/PCH.h" /Yu"Core/PCH.h" /Fp"Intermediate\x64-!CFG!\JulietShaderCompiler.pch" /c /Fo"Intermediate\x64-!CFG!\JulietShaderCompiler_Objs\\">>"!PLAN_FILE!"
+202 -58
View File
@@ -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;
}
}