Init new repository
This commit is contained in:
127
src/build_tool/cache.cpp
Normal file
127
src/build_tool/cache.cpp
Normal 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;
|
||||
}
|
||||
116
src/build_tool/easy_strings.cpp
Normal file
116
src/build_tool/easy_strings.cpp
Normal 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;
|
||||
}
|
||||
55
src/build_tool/library.cpp
Normal file
55
src/build_tool/library.cpp
Normal 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
90
src/build_tool/main.cpp
Normal 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
153
src/build_tool/process.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user