From d13c0e6f86135b08eacda1df8366048ccd254276 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Wed, 3 Jan 2024 22:01:32 +0100 Subject: [PATCH] Bring back bld with new design --- bld_lib.cpp | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++ bld_main.cpp | 64 +++++++++++++ build.bat | 4 + build.cpp | 28 ++++++ 4 files changed, 361 insertions(+) create mode 100644 bld_lib.cpp create mode 100644 bld_main.cpp create mode 100644 build.cpp diff --git a/bld_lib.cpp b/bld_lib.cpp new file mode 100644 index 0000000..eebb235 --- /dev/null +++ b/bld_lib.cpp @@ -0,0 +1,265 @@ +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "core.c" + +#define CL_Arena MA_Arena +#define CL_PushSize MA_PushSizeNonZeroed +#define CL_ASSERT IO_Assert +#define CL_VSNPRINTF stbsp_vsnprintf +#define CL_SNPRINTF stbsp_snprintf +#define AND_CL_STRING_TERMINATE_ON_NEW_LINE +#include "clexer.c" + +#define SRC_CACHE_ENTRY_COUNT 1024 +struct SRC_CacheEntry { + uint64_t filepath_hash; + uint64_t file_hash; + uint64_t includes_hash; + uint64_t total_hash; +}; + +struct SRC_Cache { + int entry_cap; + int entry_len; + SRC_CacheEntry entries[SRC_CACHE_ENTRY_COUNT]; +}; + +double SRC_Time; +SRC_Cache *SRC_InMemoryCache; +SRC_Cache *SRC_FromFileCache; +CL_ArenaTuple SRC_ArenaTuple; +S8_String SRC_CacheFilename; +MA_Arena PernamentArena; +MA_Arena *Perm = &PernamentArena; +CL_SearchPaths SRC_SearchPaths = {}; // @todo; + +void SRC_InitCache(MA_Arena *arena, S8_String cachefilename) { + SRC_CacheFilename = cachefilename; + CL_InitDefaultTuple(&SRC_ArenaTuple); + + SRC_InMemoryCache = MA_PushStruct(arena, SRC_Cache); + SRC_InMemoryCache->entry_cap = SRC_CACHE_ENTRY_COUNT; + + SRC_FromFileCache = MA_PushStruct(arena, SRC_Cache); + SRC_FromFileCache->entry_cap = SRC_CACHE_ENTRY_COUNT; + + S8_String cache = OS_ReadFile(arena, SRC_CacheFilename); + if (cache.len) MA_MemoryCopy(SRC_FromFileCache, cache.str, cache.len); +} + +void SRC_SaveCache() { + S8_String dump = S8_Make((char *)SRC_InMemoryCache, sizeof(SRC_Cache)); + OS_WriteFile(SRC_CacheFilename, dump); +} + +SRC_CacheEntry *SRC_AddHash(uint64_t filepath, uint64_t file, uint64_t includes) { + IO_Assert(SRC_InMemoryCache->entry_len + 1 < SRC_InMemoryCache->entry_cap); + SRC_CacheEntry *result = SRC_InMemoryCache->entries + SRC_InMemoryCache->entry_len++; + result->filepath_hash = filepath; + result->file_hash = file; + result->includes_hash = includes; + result->total_hash = HashBytes(result, sizeof(uint64_t) * 3); + return result; +} + +SRC_CacheEntry *SRC_FindCache(SRC_Cache *cache, uint64_t filepath_hash) { + for (int cache_i = 0; cache_i < cache->entry_len; cache_i += 1) { + SRC_CacheEntry *it = cache->entries + cache_i; + if (it->filepath_hash == filepath_hash) { + return it; + } + } + return 0; +} + +SRC_CacheEntry *SRC_HashFile(S8_String file, char *parent_file) { + char *resolved_file = CL_ResolveFilepath(Perm, &SRC_SearchPaths, file.str, parent_file, false); + if (!resolved_file) { + IO_Printf("Failed to resolve file: %s\n", file.str); + return 0; + } + + uint64_t filepath_hash = HashBytes(resolved_file, S8_Length(resolved_file)); + SRC_CacheEntry *entry = SRC_FindCache(SRC_InMemoryCache, filepath_hash); + if (entry) return entry; + + CL_LexResult *first_lex = CL_LexFile(&SRC_ArenaTuple, resolved_file); + IO_Assert(first_lex); + uint64_t file_hash = HashBytes(first_lex->stream_begin, first_lex->stream - first_lex->stream_begin); + uint64_t includes_hash = 13; + + CL_LexList list = CL_MakeLexList(first_lex); + for (CL_IncludeIter iter = CL_IterateIncludes(&list); iter.filename; CL_GetNextInclude(&iter)) { + if (iter.is_system_include) continue; + + S8_String file_it = S8_MakeFromChar(iter.filename); + SRC_CacheEntry *cache = SRC_HashFile(file_it, resolved_file); + if (!cache) { + IO_Printf("Missing cache for: %s\n", file_it.str); + continue; + } + + includes_hash = HashMix(includes_hash, cache->total_hash); + } + + SRC_CacheEntry *result = SRC_AddHash(filepath_hash, file_hash, includes_hash); + return result; +} + +bool SRC_WasModified(S8_String file) { + double time_start = OS_GetTime(); + + if (OS_FileExists(file) == false) { + IO_Printf("FAILED File doesnt exist: %.*s\n", S8_Expand(file)); + exit(0); + } + if (OS_IsAbsolute(file) == false) { + file = OS_GetAbsolutePath(Perm, file); + } + + S8_String without_ext = S8_ChopLastPeriod(file); + S8_String name_only = S8_SkipToLastSlash(without_ext); + S8_String obj = S8_Format(Perm, "%.*s.obj", S8_Expand(name_only)); + bool modified = OS_FileExists(obj) == false; + + SRC_CacheEntry *in_memory = SRC_HashFile(file, 0); + IO_Assert(in_memory); + + if (modified == false) { + SRC_CacheEntry *from_file = SRC_FindCache(SRC_FromFileCache, in_memory->filepath_hash); + if (from_file == 0 || (in_memory->total_hash != from_file->total_hash)) { + modified = true; + } + } + + SRC_Time = SRC_Time + (OS_GetTime() - time_start); + + return modified; +} + +// +// +// + +using Str = S8_String; +struct Strs : Array { + Strs() = default; + Strs(char *str) { + *this = {}; + this->add(S8_MakeFromChar(str)); + } + Strs(Array a) { MA_MemoryCopy(this, &a, sizeof(a)); } +}; + +Strs operator+(Strs a, Strs b) { + Strs c = {a.copy(*Perm)}; + c.add_array(b); + return c; +} + +Strs operator+(Strs a, Str b) { + Strs c = {a.copy(*Perm)}; + c.add(b); + return c; +} + +Strs operator+(Str a, Strs b) { + Strs c = {b.copy(*Perm)}; + c.add(a); + return c; +} + +Strs &operator+=(Strs &a, Strs b) { + a.add_array(b); + return a; +} + +Strs &operator+=(Strs &a, char *str) { + a.add(S8_MakeFromChar(str)); + return a; +} + +Strs &operator+=(Strs &a, Str s) { + a.add(s); + return a; +} + +Strs operator+(Strs a, char *b) { + Strs c = {a.copy(*Perm)}; + c.add(S8_MakeFromChar(b)); + return c; +} + +Strs operator+(char *a, Strs b) { + Strs c = {b.copy(*Perm)}; + c.add(S8_MakeFromChar(a)); + return c; +} + +Strs operator+(Str a, Str b) { + Strs c = {}; + c.add(a); + c.add(b); + return c; +} + +Strs Split(char *str) { + Str s = S8_MakeFromChar(str); + S8_List list = S8_Split(Perm, s, S8_Lit(" "), 0); + + Strs result = {}; + S8_For(it, list) result.add(it->string); + return result; +} + +Str Merge(Strs list, Str separator = " "_s) { + int64_t char_count = 0; + For(list) char_count += it.len; + if (char_count == 0) return {}; + int64_t node_count = list.len; + + int64_t base_size = (char_count + 1); + int64_t sep_size = (node_count - 1) * separator.len; + int64_t size = base_size + sep_size; + char *buff = (char *)MA_PushSize(Perm, sizeof(char) * size); + Str string = S8_Make(buff, 0); + For(list) { + IO_Assert(string.len + it.len <= size); + MA_MemoryCopy(string.str + string.len, it.str, it.len); + string.len += it.len; + if (!list.is_last(it)) { + MA_MemoryCopy(string.str + string.len, separator.str, separator.len); + string.len += separator.len; + } + } + IO_Assert(string.len == size - 1); + string.str[size] = 0; + return string; +} + +bool CodeWasModified(char *str) { return SRC_WasModified(S8_MakeFromChar(str)); } +Strs IfCodeWasModified(char *cfile, char *objfile) { + Strs result = {}; + S8_String s = S8_MakeFromChar(cfile); + if (SRC_WasModified(s)) { + return cfile; + } + return objfile; +} +void MakeDir(char *str) { OS_MakeDir(S8_MakeFromChar(str)); } +void ChangeDir(char *str) { OS_SetWorkingDir(S8_MakeFromChar(str)); } +int Run(Strs s) { + Str cmd = Merge(s); + return OS_SystemF("%Q", cmd); +} + +#ifndef BLD_MAIN +int main() { + int Main(); + SRC_InitCache(Perm, S8_Lit("project.cache")); + int result = Main(); + if (result == 0) SRC_SaveCache(); +} +#endif \ No newline at end of file diff --git a/bld_main.cpp b/bld_main.cpp new file mode 100644 index 0000000..20cd29b --- /dev/null +++ b/bld_main.cpp @@ -0,0 +1,64 @@ +#define BLD_MAIN +#include "bld_lib.cpp" + +int main(int argument_count, char **arguments) { + OS_MakeDir(S8_Lit("build")); + OS_SetWorkingDir(S8_Lit("build")); + IO_Printf("WORKING DIR: %Q\n", OS_GetWorkingDir(Perm)); + + for (int i = 1; i < argument_count; i += 1) { + S8_String arg = S8_MakeFromChar(arguments[i]); + if (arg == "clear_cache"_s) OS_DeleteFile("bld.cache"_s); + } + + SRC_InitCache(Perm, S8_Lit("bld.cache")); + + // Search for build file in the project directory + S8_String build_file = {0}; + { + S8_List files_current_dir = OS_ListDir(Perm, S8_Lit(".."), 0); + for (S8_Node *it = files_current_dir.first; it; it = it->next) { + if (S8_Find(it->string, S8_Lit("build.c"), S8_IGNORE_CASE, 0)) { + build_file = it->string; + } + } + + if (build_file.str == 0) { + IO_Printf("IDLE Nothing to do, couldnt find build file in current dir: %Q, exiting ... \n", OS_GetWorkingDir(Perm)); + return 0; + } + } + + S8_String a = S8_ChopLastPeriod(build_file); + S8_String b = S8_SkipToLastSlash(a); + S8_String exe_name = S8_Format(Perm, "%Q.exe", b); + + // @todo: add search path? + // Compile the build file only if code changed + if (SRC_WasModified(build_file)) { + double time = OS_GetTime(); + S8_String f = S8_Lit("-WX -W3 -wd4200 -diagnostics:column -nologo -Zi"); + int result = OS_SystemF("cl %Q %Q -Fe:%Q ", build_file, f, exe_name); + if (result != 0) { + IO_Printf("FAILED compilation of the build file!\n"); + return result; + } + time = OS_GetTime() - time; + IO_Printf("TIME Build file compilation: %f\n", time); + } + + // Run the build file + double time = OS_GetTime(); + if (build_file.str) { + int result = OS_SystemF("%.*s", S8_Expand(exe_name)); + if (result != 0) { + printf("FAILED execution of the build file!\n"); + return result; + } + } + time = OS_GetTime() - time; + IO_Printf("TIME total build file execution: %f\n", time); + + SRC_SaveCache(); + // OS_SetWorkingDir(S8_Lit("..")); +} diff --git a/build.bat b/build.bat index 8382e12..c435587 100644 --- a/build.bat +++ b/build.bat @@ -14,6 +14,10 @@ set RELEASE_LINE=%RELEASE% %WRN% %COMMON% -link -incremental:no %LINK_RELEASE% mkdir build cd build +cl.exe -Fe:bld.exe ../bld_main.cpp %DEBUG_LINE% +if %errorlevel% neq 0 exit /b %errorlevel% +rem bld.exe +if %errorlevel% neq 0 exit /b %errorlevel% cl.exe -Fe:test_arena.exe ../test/test_arena.cpp %DEBUG_LINE% if %errorlevel% neq 0 exit /b %errorlevel% diff --git a/build.cpp b/build.cpp new file mode 100644 index 0000000..a78ce2a --- /dev/null +++ b/build.cpp @@ -0,0 +1,28 @@ +#include "bld_lib.cpp" + +int Main() { + bool debug = true; + bool release = !debug; + bool use_std = false; + + Strs cc = "cl.exe"; + Strs flags = Split("-WX -W3 -wd4200 -diagnostics:column -nologo -Z7 -FC -GF -Gm- -Oi -Zo -D_CRT_SECURE_NO_WARNINGS"); + Strs link = Split("-link -incremental:no"); + Strs files = Split("../test/main_core_as_header.cpp"); + files += IfCodeWasModified("../core.c", "../core.obj"); + if (use_std) { + flags += Split("-GR- -EHa-"); + } + if (!use_std) { + flags += Split("-EHsc"); + } + if (release) { + flags += Split("-O2 -MT -DNDEBUG -GL"); + link += Split("-opt:ref -opt:icf -ltcg"); + } + if (debug) { + flags += Split("-Od -D_DEBUG -MTd -fsanitize=address -MTd -RTC1"); + link += Split("-NODEFAULTLIB:LIBCMT"); + } + return Run(cc + files + flags + link); +} \ No newline at end of file