Init new repository

This commit is contained in:
Krzosa Karol
2024-04-13 15:29:53 +02:00
commit 5a2e3dcec4
335 changed files with 61571 additions and 0 deletions

127
src/build_tool/cache.cpp Normal file
View File

@@ -0,0 +1,127 @@
#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;
S8_String SRC_CacheFilename;
CL_SearchPaths SRC_SearchPaths = {}; // @todo;
void SRC_InitCache(MA_Arena *arena, S8_String cachefilename) {
SRC_CacheFilename = cachefilename;
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", S8_Expand(file));
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;
S8_String filecontent = OS_ReadFile(Perm, S8_MakeFromChar(resolved_file));
IO_Assert(filecontent.str);
uint64_t file_hash = HashBytes(filecontent.str, filecontent.len);
uint64_t includes_hash = 13;
CL_Lexer lexer = CL_Begin(Perm, filecontent.str, resolved_file);
lexer.select_includes = true;
for (CL_Token token = CL_Next(&lexer); token.kind != CL_EOF; token = CL_Next(&lexer)) {
if (token.is_system_include) continue;
S8_String file_it = S8_MakeFromChar(token.string_literal);
SRC_CacheEntry *cache = SRC_HashFile(file_it, resolved_file);
if (!cache) {
// error was reported already IO_Printf("Missing cache for: %.*s\n", S8_Expand(file_it));
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, S8_String artifact_path) {
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);
if (artifact_path.len == 0) artifact_path = S8_Format(Perm, "%.*s.%s", S8_Expand(name_only), IF_WINDOWS_ELSE("obj", "o"));
bool modified = OS_FileExists(artifact_path) == 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;
}

View File

@@ -0,0 +1,116 @@
S8_String Fmt(const char *str, ...) S8__PrintfFormat(1, 2);
Array<S8_String> operator+(Array<S8_String> a, Array<S8_String> b) {
Array<S8_String> c = a.copy(MA_GetAllocator(Perm));
c.add_array(b);
return c;
}
Array<S8_String> operator+(Array<S8_String> a, S8_String b) {
Array<S8_String> c = a.copy(MA_GetAllocator(Perm));
c.add(b);
return c;
}
Array<S8_String> operator+(S8_String a, Array<S8_String> b) {
Array<S8_String> c = b.copy(MA_GetAllocator(Perm));
c.insert(a, 0);
return c;
}
Array<S8_String> operator+(S8_String a, S8_String b) {
Array<S8_String> c = {MA_GetAllocator(Perm)};
c.add(a);
c.add(b);
return c;
}
Array<S8_String> &operator+=(Array<S8_String> &a, Array<S8_String> b) {
a.add_array(b);
return a;
}
Array<S8_String> &operator+=(Array<S8_String> &a, S8_String s) {
a.add(s);
return a;
}
//@todo: split on any whitespace instead!
Array<S8_String> Split(S8_String s, S8_String sep = " ") {
S8_List list = S8_Split(Perm, s, sep, 0);
Array<S8_String> result = {MA_GetAllocator(Perm)};
S8_For(it, list) result.add(it->string);
return result;
}
S8_String Merge(MA_Arena *arena, Array<S8_String> list, S8_String 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(arena, sizeof(char) * (size + 1));
S8_String 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;
}
S8_String Merge(Array<S8_String> list, S8_String separator = " ") {
return Merge(Perm, list, separator);
}
S8_String Fmt(const char *str, ...) {
S8_FORMAT(Perm, str, str_fmt);
return str_fmt;
}
Array<S8_String> ListDir(char *dir) {
Array<S8_String> result = {MA_GetAllocator(Perm)};
for (OS_FileIter it = OS_IterateFiles(Perm, S8_MakeFromChar(dir)); OS_IsValid(it); OS_Advance(&it)) {
result.add(S8_Copy(Perm, it.absolute_path));
}
return result;
}
Array<S8_String> CMD_Make(char **argv, int argc) {
Array<S8_String> result = {MA_GetAllocator(Perm)};
for (int i = 1; i < argc; i += 1) {
S8_String it = S8_MakeFromChar(argv[i]);
result.add(it);
}
return result;
}
S8_String CMD_Get(Array<S8_String> &cmd, S8_String name, S8_String default_value = "") {
For(cmd) {
int64_t idx = 0;
if (S8_Seek(it, "="_s, 0, &idx)) {
S8_String key = S8_GetPrefix(it, idx);
S8_String value = S8_Skip(it, idx + 1);
if (key == name) {
return value;
}
}
}
return default_value;
}
bool CMD_Match(Array<S8_String> &cmd, S8_String name) {
For(cmd) {
if (it == name) return true;
}
return false;
}

View File

@@ -0,0 +1,55 @@
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "../core/core.c"
#define CL_Allocator MA_Arena *
#define CL_Allocate(a, s) MA_PushSizeNonZeroed(a, s)
#define CL_ASSERT IO_Assert
#define CL_VSNPRINTF stbsp_vsnprintf
#define CL_SNPRINTF stbsp_snprintf
#define AND_CL_STRING_TERMINATE_ON_NEW_LINE
#include "../standalone_libraries/clexer.c"
thread_local MA_Arena PernamentArena;
thread_local MA_Arena *Perm = &PernamentArena;
#include "cache.cpp"
#include "easy_strings.cpp"
#include "process.cpp"
S8_String CL_Flags = "/MP /Zi /FC /WX /W3 /wd4200 /diagnostics:column /nologo -D_CRT_SECURE_NO_WARNINGS /GF /Gm- /Oi";
S8_String CL_Link = "/link /incremental:no";
S8_String CL_StdOff = "/GR- /EHa-";
S8_String CL_StdOn = "/EHsc";
S8_String CL_Debug = "-Od -D_DEBUG -fsanitize=address -RTC1";
S8_String CL_Release = "-O2 -MT -DNDEBUG -GL";
S8_String CL_ReleaseLink = "-opt:ref -opt:icf";
/*
/FC = Print full paths in diagnostics
/Gm- = Old feature, 'minimal compilation', in case it's not off by default
/GF = Pools strings as read-only. If you try to modify strings under /GF, an application error occurs.
/Oi = Replaces some function calls with intrinsic
/MP = Multithreaded compilation
/GR- = Disable runtime type information
/EHa- = Disable exceptions
/EHsc = Enable exceptions
/MT = Link static libc. The 'd' means debug version
/MD = Link dynamic libc. The 'd' means debug version
/GL = Whole program optimization
/RTC1 = runtime error checks
/opt:ref = eliminates functions and data that are never referenced
/opt:icf = eliminates redundant 'COMDAT's
*/
S8_String Clang_Flags = "-fdiagnostics-absolute-paths -Wno-writable-strings";
S8_String Clang_NoStd = "-fno-exceptions";
S8_String Clang_Debug = "-fsanitize=address -g";
/*
-std=c++11
*/
S8_String GCC_Flags = "-Wno-write-strings";
S8_String GCC_NoStd = "-fno-exceptions";
S8_String GCC_Debug = "-fsanitize=address -g";

90
src/build_tool/main.cpp Normal file
View File

@@ -0,0 +1,90 @@
#include "library.cpp"
int main(int argument_count, char **arguments) {
MA_InitScratch();
OS_MakeDir(S8_Lit("build"));
OS_SetWorkingDir(S8_Lit("build"));
S8_String working_dir = OS_GetWorkingDir(Perm);
IO_Printf("WORKING DIR: %.*s\n", S8_Expand(working_dir));
Array<S8_String> cmd = CMD_Make(arguments, argument_count);
S8_String cc = CMD_Get(cmd, "cc", IF_WINDOWS("cl") IF_MAC("clang") IF_LINUX("gcc"));
// Search for build file in the project directory
S8_String build_file = {};
{
for (OS_FileIter it = OS_IterateFiles(Perm, S8_Lit("..")); OS_IsValid(it); OS_Advance(&it)) {
if (S8_Seek(it.filename, S8_Lit("build_file.c"), S8_IgnoreCase)) {
build_file = it.absolute_path;
}
}
if (build_file.str == 0) {
IO_Printf("Couldnt find build file in current dir: %.*s, exiting ... \n", S8_Expand(working_dir));
IO_Printf("- Proper build file contains 'build_file.c' in it's name\n");
IO_Printf("- Alternative compiler can be chosen like this: bld cc=clang\n");
return 0;
}
}
SRC_InitCache(Perm, "build_tool.cache");
S8_String name_no_ext = S8_GetNameNoExt(build_file);
S8_String exe_name = S8_Format(Perm, "%.*s.exe", S8_Expand(name_no_ext));
// Compile the build file only if code changed
if (SRC_WasModified(build_file, exe_name)) {
double time = OS_GetTime();
int result = 0;
if (cc == "cl") {
Array<S8_String> flags = {MA_GetAllocator(Perm)};
flags += "-nologo -Zi";
flags += "-WX -W3 -wd4200 -diagnostics:column";
flags += Fmt("/Fe:%.*s /Fd:%.*s.pdb", S8_Expand(exe_name), S8_Expand(exe_name));
result = Run(cc + build_file + flags);
} else if (cc == "clang") {
Array<S8_String> flags = {MA_GetAllocator(Perm)};
cc = "clang++";
flags += "-std=c++11 -g";
flags += "-fdiagnostics-absolute-paths";
flags += "-Wno-writable-strings";
flags += "-lm";
flags += Fmt("-o %.*s", S8_Expand(exe_name));
result = Run(cc + build_file + flags);
} else {
IO_Assert(cc == "gcc");
cc = "g++";
Array<S8_String> flags = {MA_GetAllocator(Perm)};
flags += "-std=c++11 -g";
flags += "-Wno-write-strings";
flags += "-lm";
flags += Fmt("-o %.*s", S8_Expand(exe_name));
result = Run(cc + build_file + flags);
}
if (result != 0) {
IO_Printf("FAILED compilation of the build file!\n");
OS_DeleteFile("build_tool.cache");
return 1;
}
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) {
exe_name = OS_GetAbsolutePath(Perm, exe_name);
int result = Run(exe_name + cmd);
if (result != 0) {
IO_Printf("FAILED execution of the build file!\n");
OS_DeleteFile("build_tool.cache");
return 1;
}
}
SRC_SaveCache();
time = OS_GetTime() - time;
IO_Printf("TIME total build file execution: %f\n", time);
}

153
src/build_tool/process.cpp Normal file
View File

@@ -0,0 +1,153 @@
struct Process {
bool is_valid;
char platform[32];
};
#if OS_WINDOWS
Process RunEx(S8_String in_cmd) {
MA_Scratch scratch;
wchar_t *application_name = NULL;
wchar_t *cmd = S8_ToWidechar(scratch, in_cmd);
BOOL inherit_handles = FALSE;
DWORD creation_flags = 0;
void *enviroment = NULL;
wchar_t *working_dir = NULL;
STARTUPINFOW startup_info = {};
startup_info.cb = sizeof(STARTUPINFOW);
Process result = {};
IO_Assert(sizeof(result.platform) >= sizeof(PROCESS_INFORMATION));
PROCESS_INFORMATION *process_info = (PROCESS_INFORMATION *)result.platform;
BOOL success = CreateProcessW(application_name, cmd, NULL, NULL, inherit_handles, creation_flags, enviroment, working_dir, &startup_info, process_info);
result.is_valid = true;
if (!success) {
result.is_valid = false;
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
LocalFree(lpMsgBuf);
IO_FatalErrorf("Failed to create process \ncmd: %.*s\nwindows_message: %s", S8_Expand(in_cmd), lpMsgBuf);
}
return result;
}
int Wait(Process *process) {
IO_Assert(process->is_valid);
PROCESS_INFORMATION *pi = (PROCESS_INFORMATION *)process->platform;
WaitForSingleObject(pi->hProcess, INFINITE);
DWORD exit_code;
BOOL err = GetExitCodeProcess(pi->hProcess, &exit_code);
IO_Assert(err != 0);
CloseHandle(pi->hProcess);
CloseHandle(pi->hThread);
process[0] = {};
return (int)exit_code;
}
#else
#include <spawn.h>
#include <sys/wait.h>
struct TH_UnixProcess {
pid_t pid;
};
extern char **environ;
Process RunEx(S8_String cmd) {
MA_Scratch scratch;
Process result = {};
IO_Assert(sizeof(result.platform) >= sizeof(TH_UnixProcess));
TH_UnixProcess *u = (TH_UnixProcess *)result.platform;
S8_String exec_file = cmd;
S8_String argv = "";
int64_t pos;
if (S8_Seek(cmd, S8_Lit(" "), 0, &pos)) {
exec_file = S8_GetPrefix(cmd, pos);
argv = S8_Skip(cmd, pos + 1);
}
exec_file = S8_Copy(scratch, exec_file);
// Split string on whitespace and conform with argv format
Array<char *> args = {MA_GetAllocator(scratch)};
{
args.add(exec_file.str);
for (int64_t i = 0; i < argv.len;) {
while (i < argv.len && CHAR_IsWhitespace(argv.str[i])) {
i += 1;
}
S8_String word = {argv.str + i, 0};
while (i < argv.len && !CHAR_IsWhitespace(argv.str[i])) {
word.len += 1;
i += 1;
}
word = S8_Copy(scratch, word);
args.add(word.str);
}
args.add(NULL);
}
int err = posix_spawnp(&u->pid, exec_file.str, NULL, NULL, args.data, environ);
if (err == 0) {
result.is_valid = true;
} else {
perror("posix_spawnp error");
IO_FatalErrorf("Failed to create process, cmd: %.*s", S8_Expand(cmd));
}
return result;
}
int Wait(Process *process) {
if (!process->is_valid) return 1;
TH_UnixProcess *u = (TH_UnixProcess *)process->platform;
int status = 0;
int pid = waitpid(u->pid, &status, 0);
IO_Assert(pid != -1);
int result = 0;
if (WIFEXITED(status)) {
result = WEXITSTATUS(status);
} else {
result = 1;
}
process[0] = {};
return result;
}
#endif
Process RunEx(Array<S8_String> s) {
S8_String cmd = Merge(s);
Process proc = RunEx(cmd);
return proc;
}
Process RunEx(Array<S8_String> s, S8_String process_start_dir) {
OS_MakeDir(process_start_dir);
S8_String working_dir = OS_GetWorkingDir(Perm);
OS_SetWorkingDir(process_start_dir);
S8_String cmd = Merge(s);
Process proc = RunEx(cmd);
OS_SetWorkingDir(working_dir);
return proc;
}
int Run(S8_String cmd) {
Process process = RunEx(cmd);
int result = Wait(&process);
return result;
}
int Run(Array<S8_String> cmd) {
S8_String cmds = Merge(cmd);
int result = Run(cmds);
return result;
}