Made build_system create the unity build itself, removing fastbuild dependency for that
fastbuild still used for generating solution
This commit is contained in:
@@ -12,7 +12,13 @@ namespace Juliet
|
|||||||
constexpr global uint64 g_Arena_Default_Commit_Size = Kilobytes(64);
|
constexpr global uint64 g_Arena_Default_Commit_Size = Kilobytes(64);
|
||||||
constexpr global uint64 k_ArenaHeaderSize = 128;
|
constexpr global uint64 k_ArenaHeaderSize = 128;
|
||||||
|
|
||||||
struct ArenaFreeNode;
|
struct ArenaFreeNode
|
||||||
|
{
|
||||||
|
ArenaFreeNode* Next;
|
||||||
|
ArenaFreeNode* Previous;
|
||||||
|
index_t Position;
|
||||||
|
size_t Size;
|
||||||
|
};
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
struct ArenaDebugInfo;
|
struct ArenaDebugInfo;
|
||||||
|
|||||||
@@ -11,11 +11,7 @@
|
|||||||
#include <Graphics/Shader.h>
|
#include <Graphics/Shader.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
|
||||||
#define ALLOW_SHADER_HOT_RELOAD 1
|
|
||||||
#else
|
|
||||||
#define ALLOW_SHADER_HOT_RELOAD 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Graphics Interface
|
// Graphics Interface
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
|
#if JULIET_DEBUG
|
||||||
|
#define ALLOW_SHADER_HOT_RELOAD 1
|
||||||
|
#else
|
||||||
|
#define ALLOW_SHADER_HOT_RELOAD 0
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
enum class DriverType : uint8
|
enum class DriverType : uint8
|
||||||
@@ -11,6 +21,6 @@ namespace Juliet
|
|||||||
struct GraphicsConfig
|
struct GraphicsConfig
|
||||||
{
|
{
|
||||||
DriverType PreferredDriver = DriverType::DX12;
|
DriverType PreferredDriver = DriverType::DX12;
|
||||||
bool EnableDebug;
|
bool EnableDebug;
|
||||||
};
|
};
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
#include <Core/Container/Vector.h>
|
#include <Core/Container/Vector.h>
|
||||||
#include <Core/Math/Matrix.h>
|
#include <Core/Math/Matrix.h>
|
||||||
|
#include <Graphics/GraphicsConfig.h>
|
||||||
#include <Graphics/Lighting.h>
|
#include <Graphics/Lighting.h>
|
||||||
#include <Graphics/PushConstants.h>
|
#include <Graphics/PushConstants.h>
|
||||||
#include <Graphics/VertexData.h>
|
#include <Graphics/VertexData.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
struct GraphicsTransferBuffer;
|
struct GraphicsTransferBuffer;
|
||||||
@@ -40,8 +42,8 @@ namespace Juliet
|
|||||||
GraphicsTransferBuffer* StreamCopyBuffer;
|
GraphicsTransferBuffer* StreamCopyBuffer;
|
||||||
GraphicsTransferBuffer* LoadCopyBuffer;
|
GraphicsTransferBuffer* LoadCopyBuffer;
|
||||||
|
|
||||||
GraphicsBuffer* LightsBuffer;
|
GraphicsBuffer* LightsBuffer;
|
||||||
PointLight* MappedLights;
|
PointLight* MappedLights;
|
||||||
|
|
||||||
GraphicsDevice* Device;
|
GraphicsDevice* Device;
|
||||||
GraphicsPipeline* Pipeline;
|
GraphicsPipeline* Pipeline;
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Math/Matrix.h>
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
#include <Core/Common/NonNullPtr.h>
|
||||||
|
#include <Core/Math/Matrix.h>
|
||||||
|
#include <Graphics/GraphicsConfig.h>
|
||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
struct RenderPass;
|
struct RenderPass;
|
||||||
@@ -17,10 +20,9 @@ namespace Juliet
|
|||||||
GraphicsPipeline* Pipeline;
|
GraphicsPipeline* Pipeline;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] JULIET_API bool InitializeSkyboxRenderer(NonNullPtr<GraphicsDevice> device,
|
[[nodiscard]] JULIET_API bool InitializeSkyboxRenderer(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
|
||||||
NonNullPtr<Window> window);
|
JULIET_API void ShutdownSkyboxRenderer();
|
||||||
JULIET_API void ShutdownSkyboxRenderer();
|
JULIET_API void RenderSkybox(NonNullPtr<RenderPass> pass, NonNullPtr<CommandList> cmdList, const Matrix& viewProjection);
|
||||||
JULIET_API void RenderSkybox(NonNullPtr<RenderPass> pass, NonNullPtr<CommandList> cmdList, const Matrix& viewProjection);
|
|
||||||
|
|
||||||
#if ALLOW_SHADER_HOT_RELOAD
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
JULIET_API void ReloadSkyboxShaders();
|
JULIET_API void ReloadSkyboxShaders();
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
#include <Core/Logging/LogManager.h>
|
#include <Core/Logging/LogManager.h>
|
||||||
#include <Core/Logging/LogTypes.h>
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
|
||||||
|
#ifdef global
|
||||||
|
#undef global
|
||||||
|
#define RESTORE_GLOBAL
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
#ifdef RESTORE_GLOBAL
|
||||||
|
#define global static
|
||||||
|
#undef RESTORE_GLOBAL
|
||||||
|
#endif
|
||||||
|
|
||||||
// Begin Todo JULIET debug output
|
// Begin Todo JULIET debug output
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
|||||||
@@ -18,14 +18,6 @@ namespace Juliet
|
|||||||
constexpr uint64 k_PageSize = Kilobytes(4);
|
constexpr uint64 k_PageSize = Kilobytes(4);
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
struct ArenaFreeNode
|
|
||||||
{
|
|
||||||
ArenaFreeNode* Next;
|
|
||||||
ArenaFreeNode* Previous;
|
|
||||||
index_t Position;
|
|
||||||
size_t Size;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
static_assert(sizeof(ArenaFreeNode) == 32, "ArenaFreeNode should be 32 bytes and not more");
|
static_assert(sizeof(ArenaFreeNode) == 32, "ArenaFreeNode should be 32 bytes and not more");
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
// Windows uses a non standard header to define its socket types.
|
// Windows uses a non standard header to define its socket types.
|
||||||
// Because of that we need to include those in this header.
|
// Because of that we need to include those in this header.
|
||||||
// TODO : implement for other platforms
|
// TODO : implement for other platforms
|
||||||
// #if JULIET_WIN32
|
#if JULIET_WIN32
|
||||||
// #include <WinSock2.h>
|
#include <WinSock2.h>
|
||||||
// #else
|
#else
|
||||||
// // UNIMPLEMENT_SOCKETS
|
// UNIMPLEMENT_SOCKETS
|
||||||
// #endif
|
#endif
|
||||||
|
|
||||||
namespace Juliet::SocketImpl
|
namespace Juliet::SocketImpl
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
#include <Core/Common/String.h>
|
|
||||||
#include <Core/Container/Vector.h>
|
|
||||||
#include <Core/Memory/MemoryArena.h> // Added for Arena definition
|
|
||||||
#include <Core/Memory/MemoryArenaDebug.h>
|
|
||||||
#include <Engine/Debug/MemoryDebugger.h>
|
#include <Engine/Debug/MemoryDebugger.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <Core/Common/String.h>
|
||||||
|
#include <Core/Container/Vector.h>
|
||||||
|
#include <Core/Memory/MemoryArena.h>
|
||||||
|
#include <Core/Memory/MemoryArenaDebug.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Common/NonNullPtr.h>
|
||||||
#include <Core/Common/NonNullPtr.h>
|
|
||||||
#include <Graphics/GraphicsBuffer.h>
|
|
||||||
#include <Graphics/D3D12/D3D12DescriptorHeap.h>
|
#include <Graphics/D3D12/D3D12DescriptorHeap.h>
|
||||||
|
#include <Graphics/GraphicsBuffer.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
@@ -20,14 +20,18 @@ namespace Juliet::D3D12
|
|||||||
size_t Size;
|
size_t Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, size_t stride, BufferUsage usage, bool isDynamic);
|
extern GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, size_t stride,
|
||||||
|
BufferUsage usage, bool isDynamic);
|
||||||
extern void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer);
|
extern void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer);
|
||||||
|
|
||||||
extern GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GPUDriver> driver, size_t size, TransferBufferUsage usage);
|
extern GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GPUDriver> driver, size_t size, TransferBufferUsage usage);
|
||||||
extern void DestroyGraphicsTransferBuffer(NonNullPtr<GraphicsTransferBuffer> buffer);
|
extern void DestroyGraphicsTransferBuffer(NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||||
|
|
||||||
extern void* MapBuffer(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer);
|
extern void* MapBuffer(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||||
extern void UnmapBuffer(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer);
|
extern void UnmapBuffer(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||||
|
extern void* MapBuffer(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsBuffer> buffer);
|
||||||
|
extern void UnmapBuffer(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsBuffer> buffer);
|
||||||
|
|
||||||
extern uint32 GetDescriptorIndex(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsBuffer> buffer);
|
extern uint32 GetDescriptorIndex(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsBuffer> buffer);
|
||||||
extern void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
|
extern void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
|
||||||
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset, size_t srcOffset);
|
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset, size_t srcOffset);
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
#ifdef JULIET_ENABLE_IMGUI
|
#ifdef JULIET_ENABLE_IMGUI
|
||||||
|
|
||||||
#include <Graphics/ImGuiRenderer.h>
|
#include <Graphics/ImGuiRenderer.h>
|
||||||
|
|
||||||
|
#include <backends/imgui_impl_win32.h>
|
||||||
|
#include <Core/Common/EnumUtils.h>
|
||||||
|
#include <Core/HAL/Filesystem/Filesystem.h>
|
||||||
#include <Core/Logging/LogManager.h>
|
#include <Core/Logging/LogManager.h>
|
||||||
#include <Core/Logging/LogTypes.h>
|
#include <Core/Logging/LogTypes.h>
|
||||||
#include <Core/HAL/Filesystem/Filesystem.h>
|
|
||||||
#include <Core/Memory/MemoryArena.h>
|
#include <Core/Memory/MemoryArena.h>
|
||||||
#include <Graphics/GraphicsPipeline.h>
|
#include <Graphics/GraphicsPipeline.h>
|
||||||
|
#include <Graphics/PushConstants.h>
|
||||||
#include <backends/imgui_impl_win32.h>
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
|
|||||||
+13
-8
@@ -132,14 +132,19 @@ if not exist "Intermediate\x64-!CFG!" mkdir "Intermediate\x64-!CFG!"
|
|||||||
|
|
||||||
echo CONFIG !CFG!>>"!PLAN_FILE!"
|
echo CONFIG !CFG!>>"!PLAN_FILE!"
|
||||||
|
|
||||||
set FASTBUILD_TARGETS=Juliet-Unity
|
set UNITY_MAX_FILES=50
|
||||||
if /i not "!CFG!"=="Release" set FASTBUILD_TARGETS=!FASTBUILD_TARGETS! ImGui-Unity
|
|
||||||
if !TARGET_JULIET! equ 1 set FASTBUILD_TARGETS=!FASTBUILD_TARGETS! JulietApp-Unity Game-Unity
|
|
||||||
if !TARGET_GAME! equ 1 set FASTBUILD_TARGETS=!FASTBUILD_TARGETS! Game-Unity
|
|
||||||
if !TARGET_ROMEO! equ 1 set FASTBUILD_TARGETS=!FASTBUILD_TARGETS! Romeo-Unity
|
|
||||||
if !TARGET_SHADER! equ 1 set FASTBUILD_TARGETS=!FASTBUILD_TARGETS! JulietShaderCompiler-Unity
|
|
||||||
|
|
||||||
echo FASTBUILD !FASTBUILD_TARGETS!>>"!PLAN_FILE!"
|
echo UNITY Juliet Intermediate\Juliet Juliet_Unity !UNITY_MAX_FILES!>>"!PLAN_FILE!"
|
||||||
|
if /i not "!CFG!"=="Release" echo UNITY_EXPLICIT Intermediate\External\imgui ImGui_Unity 1 External\imgui\imgui.cpp^|External\imgui\imgui_demo.cpp^|External\imgui\imgui_draw.cpp^|External\imgui\imgui_tables.cpp^|External\imgui\imgui_widgets.cpp^|External\imgui\backends\imgui_impl_win32.cpp^|External\imgui\backends\imgui_impl_dx12.cpp>>"!PLAN_FILE!"
|
||||||
|
|
||||||
|
set ADD_GAME_UNITY=0
|
||||||
|
if !TARGET_JULIET! equ 1 set ADD_GAME_UNITY=1
|
||||||
|
if !TARGET_GAME! equ 1 set ADD_GAME_UNITY=1
|
||||||
|
|
||||||
|
if !TARGET_JULIET! equ 1 echo UNITY JulietApp Intermediate\JulietApp JulietApp_Unity !UNITY_MAX_FILES!>>"!PLAN_FILE!"
|
||||||
|
if !ADD_GAME_UNITY! equ 1 echo UNITY Game Intermediate\Game Game_Unity !UNITY_MAX_FILES!>>"!PLAN_FILE!"
|
||||||
|
if !TARGET_ROMEO! equ 1 echo UNITY Romeo Intermediate\Romeo Romeo_Unity !UNITY_MAX_FILES!>>"!PLAN_FILE!"
|
||||||
|
if !TARGET_SHADER! equ 1 echo UNITY JulietShaderCompiler Intermediate\JulietShaderCompiler JulietShaderCompiler_Unity !UNITY_MAX_FILES!>>"!PLAN_FILE!"
|
||||||
|
|
||||||
set COMMON_FLAGS=/nologo /std:c++20 /W4 /EHa- /utf-8 /DUNICODE /D_UNICODE /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /I"Juliet/include" /I"Juliet/src" /I"Game" /I"External/imgui" /I"External/imgui/backends" /DJULIET_WIN32 /wd5267 /wd4061 /wd4505 /wd4514 /wd4577 /wd4625 /wd4710 /wd4711 /wd4746 /wd4820 /wd5045 /wd5220 /wd5245 /wd4626 /wd5026 /wd5027 /wd4530
|
set COMMON_FLAGS=/nologo /std:c++20 /W4 /EHa- /utf-8 /DUNICODE /D_UNICODE /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /I"Juliet/include" /I"Juliet/src" /I"Game" /I"External/imgui" /I"External/imgui/backends" /DJULIET_WIN32 /wd5267 /wd4061 /wd4505 /wd4514 /wd4577 /wd4625 /wd4710 /wd4711 /wd4746 /wd4820 /wd5045 /wd5220 /wd5245 /wd4626 /wd5026 /wd5027 /wd4530
|
||||||
|
|
||||||
@@ -160,7 +165,7 @@ if defined IMGUI_UNITY_SRCS (
|
|||||||
echo STEP Compiling ImGui Shared Objs [!CFG!]>>"!PLAN_FILE!"
|
echo STEP Compiling ImGui Shared Objs [!CFG!]>>"!PLAN_FILE!"
|
||||||
echo OUTPUT Intermediate\x64-!CFG!\ImGui_Unity1.obj>>"!PLAN_FILE!"
|
echo OUTPUT Intermediate\x64-!CFG!\ImGui_Unity1.obj>>"!PLAN_FILE!"
|
||||||
echo DEPENDS External\imgui>>"!PLAN_FILE!"
|
echo DEPENDS External\imgui>>"!PLAN_FILE!"
|
||||||
echo COMMAND %COMPILER% %COMPILER_FLAGS% /c !IMGUI_UNITY_SRCS! /Fo"Intermediate\x64-!CFG!\\">>"!PLAN_FILE!"
|
echo COMMAND %COMPILER% %COMPILER_FLAGS% /DIMGUI_API=__declspec^(dllexport^) /c !IMGUI_UNITY_SRCS! /Fo"Intermediate\x64-!CFG!\\">>"!PLAN_FILE!"
|
||||||
)
|
)
|
||||||
|
|
||||||
set IMGUI_OBJS=
|
set IMGUI_OBJS=
|
||||||
|
|||||||
+192
-239
@@ -126,7 +126,19 @@ static bool DirectoryExists(const char* path)
|
|||||||
|
|
||||||
static void EnsureDirectoryExists(const char* path)
|
static void EnsureDirectoryExists(const char* path)
|
||||||
{
|
{
|
||||||
CreateDirectoryA(path, NULL);
|
char tmp[MAX_PATH_LEN];
|
||||||
|
strncpy_s(tmp, MAX_PATH_LEN, path, _TRUNCATE);
|
||||||
|
for (int i = 0; tmp[i]; i++)
|
||||||
|
{
|
||||||
|
if (tmp[i] == '\\' || tmp[i] == '/')
|
||||||
|
{
|
||||||
|
char c = tmp[i];
|
||||||
|
tmp[i] = '\0';
|
||||||
|
CreateDirectoryA(tmp, NULL);
|
||||||
|
tmp[i] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CreateDirectoryA(tmp, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t GetFileModTimeInt64(const char* path)
|
static int64_t GetFileModTimeInt64(const char* path)
|
||||||
@@ -142,187 +154,6 @@ static int64_t GetFileModTimeInt64(const char* path)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// FNV-1a hash
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
static uint64_t ComputeFnv1aHash(const char* data, long size)
|
|
||||||
{
|
|
||||||
uint64_t hash = 14695981039346656037ULL;
|
|
||||||
for (long i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
hash ^= (uint64_t)(unsigned char)data[i];
|
|
||||||
hash *= 1099511628211ULL;
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Hash cache
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char Path[MAX_PATH_LEN];
|
|
||||||
char HashStr[32];
|
|
||||||
} HashEntry;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HashEntry* Entries;
|
|
||||||
int Count;
|
|
||||||
} HashCache;
|
|
||||||
|
|
||||||
static HashCache* CreateHashCache()
|
|
||||||
{
|
|
||||||
HashCache* cache = (HashCache*)ArenaPush(sizeof(HashCache));
|
|
||||||
cache->Entries = (HashEntry*)ArenaPush(sizeof(HashEntry) * MAX_HASH_ENTRIES);
|
|
||||||
cache->Count = 0;
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* HashCacheFind(const HashCache* cache, const char* path)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < cache->Count; i++)
|
|
||||||
{
|
|
||||||
if (strcmp(cache->Entries[i].Path, path) == 0)
|
|
||||||
{
|
|
||||||
return cache->Entries[i].HashStr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void HashCacheAdd(HashCache* cache, const char* path, const char* hash)
|
|
||||||
{
|
|
||||||
if (cache->Count < MAX_HASH_ENTRIES)
|
|
||||||
{
|
|
||||||
strncpy_s(cache->Entries[cache->Count].Path, MAX_PATH_LEN, path, _TRUNCATE);
|
|
||||||
strncpy_s(cache->Entries[cache->Count].HashStr, 32, hash, _TRUNCATE);
|
|
||||||
cache->Count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void LoadHashCache(const char* cachePath, HashCache* cache)
|
|
||||||
{
|
|
||||||
FileContent content = ReadEntireFile(cachePath);
|
|
||||||
if (!content.Data) return;
|
|
||||||
|
|
||||||
const char* pos = content.Data;
|
|
||||||
while (*pos != '\0')
|
|
||||||
{
|
|
||||||
const char* lineStart = pos;
|
|
||||||
while (*pos != '\0' && *pos != '\n' && *pos != '\r')
|
|
||||||
pos++;
|
|
||||||
int lineLen = (int)(pos - lineStart);
|
|
||||||
|
|
||||||
if (lineLen > 0)
|
|
||||||
{
|
|
||||||
const char* sep = NULL;
|
|
||||||
for (const char* c = lineStart; c < lineStart + lineLen; c++)
|
|
||||||
{
|
|
||||||
if (*c == '=')
|
|
||||||
{
|
|
||||||
sep = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sep)
|
|
||||||
{
|
|
||||||
char key[MAX_PATH_LEN] = { 0 };
|
|
||||||
int keyLen = (int)(sep - lineStart);
|
|
||||||
if (keyLen >= MAX_PATH_LEN) keyLen = MAX_PATH_LEN - 1;
|
|
||||||
memcpy(key, lineStart, keyLen);
|
|
||||||
|
|
||||||
int valLen = (int)((lineStart + lineLen) - (sep + 1));
|
|
||||||
char val[32] = { 0 };
|
|
||||||
if (valLen > 0 && valLen < 32)
|
|
||||||
{
|
|
||||||
memcpy(val, sep + 1, valLen);
|
|
||||||
}
|
|
||||||
HashCacheAdd(cache, key, val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (*pos == '\n' || *pos == '\r')
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SaveHashCache(const char* cachePath, const HashCache* cache)
|
|
||||||
{
|
|
||||||
long bufSize = MAX_HASH_ENTRIES * (MAX_PATH_LEN + 32 + 2);
|
|
||||||
char* buffer = (char*)ArenaPush(bufSize);
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < cache->Count; i++)
|
|
||||||
{
|
|
||||||
int written = sprintf_s(buffer + offset, bufSize - offset, "%s=%s\n", cache->Entries[i].Path, cache->Entries[i].HashStr);
|
|
||||||
if (written > 0) offset += written;
|
|
||||||
}
|
|
||||||
WriteEntireFile(cachePath, buffer, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Clean #pragma message lines and compute hash for a unity file
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char HashStr[32];
|
|
||||||
bool WasCleaned;
|
|
||||||
} CleanResult;
|
|
||||||
|
|
||||||
static CleanResult CleanAndHashUnityFile(const char* filePath)
|
|
||||||
{
|
|
||||||
CleanResult result = { { 0 }, false };
|
|
||||||
FileContent content = ReadEntireFile(filePath);
|
|
||||||
if (!content.Data) return result;
|
|
||||||
|
|
||||||
if (StringContains(content.Data, "#pragma message"))
|
|
||||||
{
|
|
||||||
char* filtered = (char*)ArenaPush(content.Size + 1);
|
|
||||||
long filteredSize = 0;
|
|
||||||
|
|
||||||
const char* pos = content.Data;
|
|
||||||
while (*pos != '\0')
|
|
||||||
{
|
|
||||||
const char* lineStart = pos;
|
|
||||||
while (*pos != '\0' && *pos != '\n')
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
bool skipLine = false;
|
|
||||||
for (const char* c = lineStart; c < pos; c++)
|
|
||||||
{
|
|
||||||
if (c + 15 <= content.Data + content.Size && memcmp(c, "#pragma message", 15) == 0)
|
|
||||||
{
|
|
||||||
skipLine = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skipLine)
|
|
||||||
{
|
|
||||||
long lineLen = (long)(pos - lineStart);
|
|
||||||
memcpy(filtered + filteredSize, lineStart, lineLen);
|
|
||||||
filteredSize += lineLen;
|
|
||||||
if (*pos == '\n') filtered[filteredSize++] = '\n';
|
|
||||||
}
|
|
||||||
if (*pos == '\n') pos++;
|
|
||||||
}
|
|
||||||
filtered[filteredSize] = '\0';
|
|
||||||
|
|
||||||
WriteEntireFile(filePath, filtered, filteredSize);
|
|
||||||
uint64_t hashVal = ComputeFnv1aHash(filtered, filteredSize);
|
|
||||||
sprintf_s(result.HashStr, sizeof(result.HashStr), "%llu", hashVal);
|
|
||||||
result.WasCleaned = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint64_t hashVal = ComputeFnv1aHash(content.Data, content.Size);
|
|
||||||
sprintf_s(result.HashStr, sizeof(result.HashStr), "%llu", hashVal);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Recursive directory scan
|
// Recursive directory scan
|
||||||
@@ -403,7 +234,7 @@ static void FilePathListAdd(FilePathList* list, const char* path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CollectUnityFiles(const char* dirPath, FilePathList* list)
|
static void CollectFiles(const char* dirPath, const char* containsStr, const char* endsWithStr, FilePathList* list)
|
||||||
{
|
{
|
||||||
char searchPath[MAX_PATH_LEN];
|
char searchPath[MAX_PATH_LEN];
|
||||||
snprintf(searchPath, sizeof(searchPath), "%s\\*", dirPath);
|
snprintf(searchPath, sizeof(searchPath), "%s\\*", dirPath);
|
||||||
@@ -425,11 +256,14 @@ static void CollectUnityFiles(const char* dirPath, FilePathList* list)
|
|||||||
|
|
||||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
{
|
{
|
||||||
CollectUnityFiles(fullPath, list);
|
CollectFiles(fullPath, containsStr, endsWithStr, list);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (StringContains(findData.cFileName, "_Unity") && EndsWithNoCase(findData.cFileName, ".cpp"))
|
bool match = true;
|
||||||
|
if (containsStr && !StringContains(findData.cFileName, containsStr)) match = false;
|
||||||
|
if (endsWithStr && !EndsWithNoCase(findData.cFileName, endsWithStr)) match = false;
|
||||||
|
if (match)
|
||||||
{
|
{
|
||||||
FilePathListAdd(list, fullPath);
|
FilePathListAdd(list, fullPath);
|
||||||
}
|
}
|
||||||
@@ -440,6 +274,101 @@ static void CollectUnityFiles(const char* dirPath, FilePathList* list)
|
|||||||
FindClose(hFind);
|
FindClose(hFind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char SourceDir[MAX_PATH_LEN];
|
||||||
|
char OutputDir[MAX_PATH_LEN];
|
||||||
|
char Prefix[256];
|
||||||
|
char* ExplicitFiles[64];
|
||||||
|
int ExplicitFileCount;
|
||||||
|
int MaxFiles;
|
||||||
|
} UnityConfig;
|
||||||
|
|
||||||
|
static bool GenerateUnityFiles(const UnityConfig* ucfg)
|
||||||
|
{
|
||||||
|
FilePathList* srcFiles = CreateFilePathList();
|
||||||
|
if (ucfg->SourceDir[0] != '\0')
|
||||||
|
{
|
||||||
|
CollectFiles(ucfg->SourceDir, NULL, ".cpp", srcFiles);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ucfg->ExplicitFileCount; i++)
|
||||||
|
{
|
||||||
|
FilePathListAdd(srcFiles, ucfg->ExplicitFiles[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureDirectoryExists(ucfg->OutputDir);
|
||||||
|
|
||||||
|
int fileIdx = 0;
|
||||||
|
int unityCount = 1;
|
||||||
|
char currentUnityPath[MAX_PATH_LEN];
|
||||||
|
bool anyChanged = false;
|
||||||
|
|
||||||
|
char* memBuf = (char*)ArenaPush(1024 * 1024);
|
||||||
|
int memOffset = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < srcFiles->Count; i++)
|
||||||
|
{
|
||||||
|
if (StringContains(srcFiles->Paths[i], "_Unity")) continue;
|
||||||
|
|
||||||
|
if (fileIdx == 0)
|
||||||
|
{
|
||||||
|
memOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char absPath[MAX_PATH_LEN];
|
||||||
|
GetFullPathNameA(srcFiles->Paths[i], MAX_PATH_LEN, absPath, NULL);
|
||||||
|
for (int k = 0; absPath[k]; k++) {
|
||||||
|
if (absPath[k] == '\\') absPath[k] = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
memOffset += sprintf_s(memBuf + memOffset, (1024 * 1024) - memOffset, "#include \"%s\"\n", absPath);
|
||||||
|
fileIdx++;
|
||||||
|
|
||||||
|
if (fileIdx >= ucfg->MaxFiles || i == srcFiles->Count - 1)
|
||||||
|
{
|
||||||
|
snprintf(currentUnityPath, sizeof(currentUnityPath), "%s\\%s%d.cpp", ucfg->OutputDir, ucfg->Prefix, unityCount);
|
||||||
|
|
||||||
|
FileContent exist = ReadEntireFile(currentUnityPath);
|
||||||
|
bool write = true;
|
||||||
|
if (exist.Data && exist.Size == memOffset)
|
||||||
|
{
|
||||||
|
if (memcmp(exist.Data, memBuf, memOffset) == 0)
|
||||||
|
{
|
||||||
|
write = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (write)
|
||||||
|
{
|
||||||
|
WriteEntireFile(currentUnityPath, memBuf, memOffset);
|
||||||
|
anyChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unityCount++;
|
||||||
|
fileIdx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
snprintf(currentUnityPath, sizeof(currentUnityPath), "%s\\%s%d.cpp", ucfg->OutputDir, ucfg->Prefix, unityCount);
|
||||||
|
if (FileExists(currentUnityPath))
|
||||||
|
{
|
||||||
|
DeleteFileA(currentUnityPath);
|
||||||
|
anyChanged = true;
|
||||||
|
unityCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return anyChanged;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Commands
|
// Commands
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -454,10 +383,11 @@ typedef struct
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char Name[64];
|
char Name[64];
|
||||||
char FastBuildTargets[512];
|
UnityConfig UnitySteps[16];
|
||||||
BuildStep Steps[32];
|
int UnityStepCount;
|
||||||
int StepCount;
|
BuildStep Steps[32];
|
||||||
|
int StepCount;
|
||||||
} BuildConfig;
|
} BuildConfig;
|
||||||
|
|
||||||
static int ExecuteCmd(const char* cmdLine)
|
static int ExecuteCmd(const char* cmdLine)
|
||||||
@@ -544,8 +474,7 @@ static int CommandRunPlan(int argc, char* argv[])
|
|||||||
QueryPerformanceFrequency(&perfFreq);
|
QueryPerformanceFrequency(&perfFreq);
|
||||||
|
|
||||||
// Parse plan file
|
// Parse plan file
|
||||||
BuildConfig configs[4];
|
BuildConfig* configs = (BuildConfig*)ArenaPush(4 * sizeof(BuildConfig));
|
||||||
memset(configs, 0, sizeof(configs));
|
|
||||||
int configCount = 0;
|
int configCount = 0;
|
||||||
|
|
||||||
const char* pos = planContent.Data;
|
const char* pos = planContent.Data;
|
||||||
@@ -572,12 +501,65 @@ static int CommandRunPlan(int argc, char* argv[])
|
|||||||
else if (configCount > 0)
|
else if (configCount > 0)
|
||||||
{
|
{
|
||||||
BuildConfig* curCfg = &configs[configCount - 1];
|
BuildConfig* curCfg = &configs[configCount - 1];
|
||||||
if (lineLen > 10 && memcmp(lineStart, "FASTBUILD ", 10) == 0)
|
if (lineLen > 6 && memcmp(lineStart, "UNITY ", 6) == 0)
|
||||||
{
|
{
|
||||||
int nLen = lineLen - 10;
|
if (curCfg->UnityStepCount < 16)
|
||||||
if (nLen >= (int)sizeof(curCfg->FastBuildTargets)) nLen = (int)sizeof(curCfg->FastBuildTargets) - 1;
|
{
|
||||||
memcpy(curCfg->FastBuildTargets, lineStart + 10, nLen);
|
char lineBuf[1024];
|
||||||
curCfg->FastBuildTargets[nLen] = '\0';
|
int nLen = lineLen - 6;
|
||||||
|
if (nLen >= (int)sizeof(lineBuf)) nLen = (int)sizeof(lineBuf) - 1;
|
||||||
|
memcpy(lineBuf, lineStart + 6, nLen);
|
||||||
|
lineBuf[nLen] = '\0';
|
||||||
|
|
||||||
|
UnityConfig* ucfg = &curCfg->UnitySteps[curCfg->UnityStepCount];
|
||||||
|
ucfg->ExplicitFileCount = 0;
|
||||||
|
if (sscanf_s(lineBuf, "%s %s %s %d",
|
||||||
|
ucfg->SourceDir, (unsigned)_countof(ucfg->SourceDir),
|
||||||
|
ucfg->OutputDir, (unsigned)_countof(ucfg->OutputDir),
|
||||||
|
ucfg->Prefix, (unsigned)_countof(ucfg->Prefix),
|
||||||
|
&ucfg->MaxFiles) == 4)
|
||||||
|
{
|
||||||
|
curCfg->UnityStepCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lineLen > 15 && memcmp(lineStart, "UNITY_EXPLICIT ", 15) == 0)
|
||||||
|
{
|
||||||
|
if (curCfg->UnityStepCount < 16)
|
||||||
|
{
|
||||||
|
char lineBuf[2048];
|
||||||
|
int nLen = lineLen - 15;
|
||||||
|
if (nLen >= (int)sizeof(lineBuf)) nLen = (int)sizeof(lineBuf) - 1;
|
||||||
|
memcpy(lineBuf, lineStart + 15, nLen);
|
||||||
|
lineBuf[nLen] = '\0';
|
||||||
|
|
||||||
|
UnityConfig* ucfg = &curCfg->UnitySteps[curCfg->UnityStepCount];
|
||||||
|
ucfg->SourceDir[0] = '\0';
|
||||||
|
ucfg->ExplicitFileCount = 0;
|
||||||
|
|
||||||
|
char fileList[1024];
|
||||||
|
if (sscanf_s(lineBuf, "%s %s %d %s",
|
||||||
|
ucfg->OutputDir, (unsigned)_countof(ucfg->OutputDir),
|
||||||
|
ucfg->Prefix, (unsigned)_countof(ucfg->Prefix),
|
||||||
|
&ucfg->MaxFiles,
|
||||||
|
fileList, (unsigned)_countof(fileList)) == 4)
|
||||||
|
{
|
||||||
|
char* ctx = NULL;
|
||||||
|
char* token = strtok_s(fileList, "|", &ctx);
|
||||||
|
while(token)
|
||||||
|
{
|
||||||
|
if (ucfg->ExplicitFileCount < 64)
|
||||||
|
{
|
||||||
|
size_t tLen = strlen(token);
|
||||||
|
char* storedStr = (char*)ArenaPush(tLen + 1);
|
||||||
|
strcpy_s(storedStr, tLen + 1, token);
|
||||||
|
ucfg->ExplicitFiles[ucfg->ExplicitFileCount++] = storedStr;
|
||||||
|
}
|
||||||
|
token = strtok_s(NULL, "|", &ctx);
|
||||||
|
}
|
||||||
|
curCfg->UnityStepCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (lineLen > 5 && memcmp(lineStart, "STEP ", 5) == 0)
|
else if (lineLen > 5 && memcmp(lineStart, "STEP ", 5) == 0)
|
||||||
{
|
{
|
||||||
@@ -627,66 +609,37 @@ static int CommandRunPlan(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
BuildConfig* cfg = &configs[i];
|
BuildConfig* cfg = &configs[i];
|
||||||
printf("\n==============================================================================\n");
|
printf("\n==============================================================================\n");
|
||||||
printf("Generating Unity Files into Intermediate/ via FASTBuild [%s]...\n", cfg->Name);
|
printf("Generating Unity Files [%s]...\n", cfg->Name);
|
||||||
printf("==============================================================================\n");
|
printf("==============================================================================\n");
|
||||||
|
|
||||||
if (cfg->FastBuildTargets[0] != '\0')
|
bool unityChanged = false;
|
||||||
{
|
|
||||||
char fbuildCmd[MAX_PATH_LEN];
|
|
||||||
sprintf_s(fbuildCmd, sizeof(fbuildCmd), "misc\\fbuild.exe %s", cfg->FastBuildTargets);
|
|
||||||
|
|
||||||
|
if (cfg->UnityStepCount > 0)
|
||||||
|
{
|
||||||
LARGE_INTEGER tStart, tEnd;
|
LARGE_INTEGER tStart, tEnd;
|
||||||
QueryPerformanceCounter(&tStart);
|
QueryPerformanceCounter(&tStart);
|
||||||
int res = ExecuteCmd(fbuildCmd);
|
|
||||||
QueryPerformanceCounter(&tEnd);
|
for (int u = 0; u < cfg->UnityStepCount; u++)
|
||||||
|
|
||||||
char stepName[MAX_PATH_LEN];
|
|
||||||
sprintf_s(stepName, sizeof(stepName), "FASTBuild Unity Gen [%s]", cfg->Name);
|
|
||||||
AppendTiming(stepName, (double)(tEnd.QuadPart - tStart.QuadPart) / (double)perfFreq.QuadPart);
|
|
||||||
|
|
||||||
if (res != 0)
|
|
||||||
{
|
{
|
||||||
printf("[BUILD FAILED] FASTBuild failed for %s.\n", cfg->Name);
|
if (GenerateUnityFiles(&cfg->UnitySteps[u]))
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HashCache* oldCache = CreateHashCache();
|
|
||||||
LoadHashCache("Intermediate\\.unity_hashes_cache", oldCache);
|
|
||||||
|
|
||||||
HashCache* newCache = CreateHashCache();
|
|
||||||
bool unityChanged = false;
|
|
||||||
|
|
||||||
FilePathList* unityFiles = CreateFilePathList();
|
|
||||||
CollectUnityFiles("Intermediate", unityFiles);
|
|
||||||
|
|
||||||
if (unityFiles->Count == 0)
|
|
||||||
{
|
|
||||||
unityChanged = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int k = 0; k < unityFiles->Count; k++)
|
|
||||||
{
|
|
||||||
CleanResult cr = CleanAndHashUnityFile(unityFiles->Paths[k]);
|
|
||||||
HashCacheAdd(newCache, unityFiles->Paths[k], cr.HashStr);
|
|
||||||
|
|
||||||
const char* oldHash = HashCacheFind(oldCache, unityFiles->Paths[k]);
|
|
||||||
if (oldHash == NULL || strcmp(oldHash, cr.HashStr) != 0)
|
|
||||||
{
|
{
|
||||||
unityChanged = true;
|
unityChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryPerformanceCounter(&tEnd);
|
||||||
|
char stepName[MAX_PATH_LEN];
|
||||||
|
sprintf_s(stepName, sizeof(stepName), "Unity Gen [%s]", cfg->Name);
|
||||||
|
AppendTiming(stepName, (double)(tEnd.QuadPart - tStart.QuadPart) / (double)perfFreq.QuadPart);
|
||||||
}
|
}
|
||||||
SaveHashCache("Intermediate\\.unity_hashes_cache", newCache);
|
|
||||||
|
|
||||||
if (unityChanged)
|
if (unityChanged)
|
||||||
{
|
{
|
||||||
printf("[FASTBuild] Unity structure or source file list changed.\n");
|
printf("[Unity] Source file list or include mapping changed.\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("[FASTBuild] No Unity file structure changes detected [up-to-date].\n");
|
printf("[Unity] No changes detected [up-to-date].\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n==============================================================================\n");
|
printf("\n==============================================================================\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user