diff --git a/build.c b/build.c index 0fdc6c66..fddca9cb 100644 --- a/build.c +++ b/build.c @@ -1,15 +1,5 @@ -#define Rtc 1 #include "buildit.h" -/* ========================== * - * Globals - * ========================== */ - -Arena *arena = 0; -D_Hist *hist = 0; - -Bool force_rebuild = false; - /* ========================== * * Util * ========================== */ @@ -21,53 +11,294 @@ void Error(String msg) Bool IsDirty(D_Tag tag) { - return force_rebuild ? true : D_IsDirty(tag, hist); + extern Bool force_rebuild; + extern D_Store store; + extern D_Hist hist; + Bool res = force_rebuild ? true : D_IsDirty(&store, &hist, tag); + if (!res) { + if (tag.kind == D_TagKind_File || tag.kind == D_TagKind_Dir) { + res = !D_Exists(tag); + } + } + + return res; } /* ========================== * * Step * ========================== */ -typedef struct StepListNode StepListNode; -struct StepListNode { + +typedef struct Step Step; +typedef struct StepList StepList; + +typedef void StepFunc(Step *step); + +typedef enum StepStatus { + StepStatus_None, + StepStatus_Success, + StepStatus_Failure +} StepStatus; + +typedef struct Step Step; +struct Step { String name; - String cmd; - Bool silence_if_success; - StepListNode *next; - StepListNode *prev; + StepFunc *func; + void *arg; + StepList *sl; + + OS_Mutex res_mutex; + OS_ConditionVariable res_cv; + StepStatus res_status; + String res_output; + + Step *next; + Step *prev; + + Step *next_unqueued; + Step *prev_unqueued; }; typedef struct StepList StepList; struct StepList { - StepListNode *first; - StepListNode *last; + OS_Mutex mutex; + Arena arena; + + Step *first; + Step *last; Size count; + + Step *first_unqueued; + Step *last_unqueued; + + StepList *next; }; -void StepListAppend(StepList *l, String name, String cmd, Bool silence_if_success) +StepList StepListAlloc(void) { - StepListNode *n = ArenaPush(arena, StepListNode); - n->name = name; - n->cmd = cmd; - n->silence_if_success = silence_if_success; - DllPushBack(l->first, l->last, n); - ++l->count; + StepList sl = { 0 }; + sl.mutex = OS_MutexAlloc(); + sl.arena = ArenaAlloc(Gigabyte(64)); + return sl; } +Step *DequeueNextStep(StepList *sl) +{ + Step *res = 0; + OS_MutexLockW(&sl->mutex); + { + res = sl->first_unqueued; + if (res) { + DllRemoveNP(sl->first_unqueued, sl->last_unqueued, res, next_unqueued, prev_unqueued); + } + } + OS_MutexUnlockW(&sl->mutex); + return res; +} + +void AddStep(StepList *sl, String name, StepFunc *func, void *arg) +{ + OS_MutexLockW(&sl->mutex); + { + Step *s = ArenaPush(&sl->arena, Step); + s->name = StringCopy(&sl->arena, name); + s->func = func; + s->arg = arg; + s->sl = sl; + s->res_mutex = OS_MutexAlloc(); + s->res_cv = OS_ConditionVariableAlloc(); + DllPushBack(sl->first, sl->last, s); + DllPushBackNP(sl->first_unqueued, sl->last_unqueued, s, next_unqueued, prev_unqueued); + ++sl->count; + } + OS_MutexUnlockW(&sl->mutex); +} + +/* ========================== * + * Worker + * ========================== */ + +typedef struct Worker Worker; + +typedef struct WorkerSharedState WorkerSharedState; +struct WorkerSharedState { + OS_Mutex mutex; + OS_ConditionVariable cv; + Arena arena; + + StepList *first_step_list; + StepList *last_step_list; + + Bool shutdown; + Worker *first_worker; + I64 worker_count; +}; +extern WorkerSharedState worker_shared; + +typedef struct Worker Worker; +struct Worker { + OS_Thread thread; + Worker *next; +}; + +OS_ThreadEntryPointFuncDef(WorkerEntryPoint, arg) +{ +#if 0 + I64 id = (I64)arg; + { + TempArena scratch = ScratchBeginNoConflict(); + String name = StringF(scratch.arena, Lit("Builder worker %F"), FmtI64(id)); + OS_SetThreadName(name); + ScratchEnd(scratch); + } +#else + OS_SetThreadName(Lit("Builder worker")); +#endif + + while (!worker_shared.shutdown) { + OS_MutexLockW(&worker_shared.mutex); + { + if (!worker_shared.shutdown && !worker_shared.first_step_list) { + OS_ConditionVariableWaitW(&worker_shared.cv, &worker_shared.mutex); + } + + if (!worker_shared.shutdown && worker_shared.first_step_list) { + StepList *sl = worker_shared.first_step_list; + Step *s = DequeueNextStep(sl); + if (s) { + OS_MutexUnlockW(&worker_shared.mutex); + { + s->func(s); + } + OS_MutexLockW(&worker_shared.mutex); + } else { + /* Wait for all steps in old step list to finish, then pop the list */ + for (Step *check_step = sl->first; check_step; check_step = check_step->next) { + OS_MutexLockW(&check_step->res_mutex); + { + while (check_step->res_status == StepStatus_None) { + OS_ConditionVariableWaitW(&check_step->res_cv, &check_step->res_mutex); + } + } + OS_MutexUnlockW(&check_step->res_mutex); + } + SllQueuePop(worker_shared.first_step_list, worker_shared.last_step_list); + } + } + } + OS_MutexUnlockW(&worker_shared.mutex); + } +} + +void StartWorkers(I64 count) +{ + OS_MutexLockW(&worker_shared.mutex); + { + for (I64 i = 0; i < count; ++i) { + Worker *w = ArenaPush(&worker_shared.arena, Worker); + w->thread = OS_ThreadAlloc(&WorkerEntryPoint, (void *)worker_shared.worker_count); + SllStackPush(worker_shared.first_worker, w); + ++worker_shared.worker_count; + } + } + OS_MutexUnlockW(&worker_shared.mutex); +} + +void ShutdownWorkers(void) +{ + OS_MutexLockW(&worker_shared.mutex); + { + worker_shared.shutdown = true; + OS_ConditionVariableBroadcast(&worker_shared.cv); + } + OS_MutexUnlockW(&worker_shared.mutex); + + for (Worker *w = worker_shared.first_worker; w; w = w->next) { + OS_ThreadWaitRelease(&w->thread); + } +} + +void AddStepListToWorkQueue(StepList *sl) +{ + OS_MutexLockW(&worker_shared.mutex); + { + SllQueuePush(worker_shared.first_step_list, worker_shared.last_step_list, sl); + OS_ConditionVariableBroadcast(&worker_shared.cv); + } + OS_MutexUnlockW(&worker_shared.mutex); +} + +/* ========================== * + * Build steps + * ========================== */ + +typedef struct BuildStepSimpleCommandArg BuildStepSimpleCommandArg; +struct BuildStepSimpleCommandArg { + String cmd; +}; + +void BuildStepSimpleCommand(Step *s) +{ + TempArena scratch = ScratchBeginNoConflict(); + + BuildStepSimpleCommandArg *arg = s->arg; + SH_CommandResult result = SH_RunCommandCaptureOutput(scratch.arena, arg->cmd, true); + + OS_MutexLockW(&s->res_mutex); + { + if (result.output.len > 0) { + OS_MutexLockW(&s->sl->mutex); + { + s->res_output.text = ArenaPushArrayNoZero(&s->sl->arena, Byte, result.output.len); + } + OS_MutexUnlockW(&s->sl->mutex); + s->res_output.len = result.output.len; + MemoryCopy(s->res_output.text, result.output.text, result.output.len); + } + s->res_status = result.error ? StepStatus_Failure : StepStatus_Success; + OS_ConditionVariableBroadcast(&s->res_cv); + } + OS_MutexUnlockW(&s->res_mutex); + + ScratchEnd(scratch); +} + +void BuildStepCompileRc(Step *s) +{ +} + +/* ========================== * + * Globals + * ========================== */ + +Arena arena = { 0 }; +D_Store store = { 0 }; +D_Hist hist = { 0 }; +WorkerSharedState worker_shared = { 0 }; + +Bool force_rebuild = false; + /* ========================== * * Build * ========================== */ void OnBuild(StringList cli_args) { - { - Arena a = ArenaAlloc(Gigabyte(64)); - arena = ArenaPush(&a, Arena); - *arena = a; - } - OS_TimeStamp start = OS_GetTimeStamp(); + arena = ArenaAlloc(Gigabyte(64)); + store = D_StoreAlloc(); + + /* ========================== * + * Setup workers + * ========================== */ + + worker_shared.mutex = OS_MutexAlloc(); + worker_shared.arena = ArenaAlloc(Gigabyte(64)); + + I64 worker_count = OS_GetProcessorCount(); + StartWorkers(worker_count); + /* ========================== * * Read args * ========================== */ @@ -117,12 +348,12 @@ void OnBuild(StringList cli_args) } } - String hist_path = OS_GetAbsPath(arena, StringF(arena, Lit("%F/.dephist"), FmtStr(arg_outdir))); - String build_hash_path = OS_GetAbsPath(arena, StringF(arena, Lit("%F/.pp_build_hash"), FmtStr(arg_outdir))); - String out_dep_dir_path = OS_GetAbsPath(arena, StringF(arena, Lit("%F/dep/"), FmtStr(arg_outdir))); - String out_obj_dir_path = OS_GetAbsPath(arena, StringF(arena, Lit("%F/obj/"), FmtStr(arg_outdir))); - String out_inc_dir_path = OS_GetAbsPath(arena, StringF(arena, Lit("%F/inc/"), FmtStr(arg_outdir))); - String out_bin_dir_path = OS_GetAbsPath(arena, StringF(arena, Lit("%F/bin/"), FmtStr(arg_outdir))); + String hist_path = OS_GetAbsPath(&arena, StringF(&arena, Lit("%F/.dephist"), FmtStr(arg_outdir))); + String build_hash_path = OS_GetAbsPath(&arena, StringF(&arena, Lit("%F/.pp_build_hash"), FmtStr(arg_outdir))); + String out_dep_dir_path = OS_GetAbsPath(&arena, StringF(&arena, Lit("%F/dep/"), FmtStr(arg_outdir))); + String out_obj_dir_path = OS_GetAbsPath(&arena, StringF(&arena, Lit("%F/obj/"), FmtStr(arg_outdir))); + String out_inc_dir_path = OS_GetAbsPath(&arena, StringF(&arena, Lit("%F/inc/"), FmtStr(arg_outdir))); + String out_bin_dir_path = OS_GetAbsPath(&arena, StringF(&arena, Lit("%F/bin/"), FmtStr(arg_outdir))); if (!OS_DirExists(out_obj_dir_path)) { OS_CreateDirAtAbsPath(out_obj_dir_path); @@ -135,18 +366,19 @@ void OnBuild(StringList cli_args) } SH_Print(Lit("------------------------------\n")); + SH_Print(Lit("Power Play build\n")); { String compiler = { 0 }; String compiler_loc = { 0 }; SH_CommandResult where_res = { 0 }; if (arg_msvc) { compiler = Lit("Msvc"); - where_res = SH_RunCommandCaptureOutput(arena, Lit("where cl.exe"), true); + where_res = SH_RunCommandCaptureOutput(&arena, Lit("where cl.exe"), true); } else { compiler = Lit("Clang"); - where_res = SH_RunCommandCaptureOutput(arena, Lit("where clang.exe"), true); + where_res = SH_RunCommandCaptureOutput(&arena, Lit("where clang.exe"), true); } - compiler_loc = where_res.error ? Lit("Not found") : StringReplace(arena, where_res.output, Lit("\n"), Lit("")); + compiler_loc = where_res.error ? Lit("Not found") : StringReplace(&arena, where_res.output, Lit("\n"), Lit("")); SH_PrintF(Lit("Compiler: %F (%F)\n"), FmtStr(compiler), FmtStr(compiler_loc)); } if (arg_asan) SH_Print(Lit("Asan Enabled\n")); @@ -164,13 +396,13 @@ void OnBuild(StringList cli_args) Bool should_embed_res_dir = !arg_developer; Bool should_embed_in_rc = !!arg_msvc; - D_Tag executable_file = D_TagFromPath(arena, StringF(arena, Lit("%F/PowerPlay.exe"), FmtStr(out_bin_dir_path)), D_TagKind_File); - D_Tag res_dir = D_TagFromPath(arena, Lit("res"), D_TagKind_Dir); - D_Tag shaders_dir = D_TagFromPath(arena, Lit("src/shaders"), D_TagKind_Dir); - D_Tag icon_file = D_TagFromPath(arena, Lit("icon.ico"), D_TagKind_File); + D_Tag executable_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/PowerPlay.exe"), FmtStr(out_bin_dir_path)), D_TagKind_File); + D_Tag res_dir = D_TagFromPath(&arena, Lit("res"), D_TagKind_Dir); + D_Tag shaders_dir = D_TagFromPath(&arena, Lit("src/shaders"), D_TagKind_Dir); + D_Tag icon_file = D_TagFromPath(&arena, Lit("icon.ico"), D_TagKind_File); - D_Tag inc_src_file = D_TagFromPath(arena, Lit("src/inc.c"), D_TagKind_File); - D_Tag rc_res_file = D_TagFromPath(arena, StringF(arena, Lit("%F/rc.res"), FmtStr(out_obj_dir_path)), D_TagKind_File); + D_Tag inc_src_file = D_TagFromPath(&arena, Lit("src/inc.c"), D_TagKind_File); + D_Tag rc_res_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/rc.res"), FmtStr(out_obj_dir_path)), D_TagKind_File); /* ========================== * * Determine compiler args @@ -192,32 +424,32 @@ void OnBuild(StringList cli_args) { if (arg_msvc) { /* Msvc */ - StringListAppend(arena, &c_compile_args, Lit("cl.exe /nologo /c \"%F\" /Fo\"%F\"")); - StringListAppend(arena, &cpp_compile_args, Lit("cl.exe /nologo /c \"%F\" /Fo\"%F\"")); - StringListAppend(arena, &pch_c_compile_args, Lit("cl.exe /nologo /c /Yc\"%F\" \"%F\"")); - StringListAppend(arena, &pch_cpp_compile_args, Lit("cl.exe /nologo /c /Yc\"%F\" \"%F\"")); - StringListAppend(arena, &rc_compile_args, Lit("rc /fo\"%F\" \"%F\"")); + StringListAppend(&arena, &c_compile_args, Lit("cl.exe /nologo /c \"%F\" /Fo\"%F\" /FS")); + StringListAppend(&arena, &cpp_compile_args, Lit("cl.exe /nologo /c \"%F\" /Fo\"%F\" /FS")); + StringListAppend(&arena, &pch_c_compile_args, Lit("cl.exe /nologo /c /Yc\"%F\" \"%F\" /FS")); + StringListAppend(&arena, &pch_cpp_compile_args, Lit("cl.exe /nologo /c /Yc\"%F\" \"%F\" /FS")); + StringListAppend(&arena, &rc_compile_args, Lit("rc /fo\"%F\" \"%F\"")); - StringListAppend(arena, &link_args, Lit("link.exe /nologo %F /OUT:\"%F\" /DEBUG:FULL /OPT:REF /OPT:ICF")); + StringListAppend(&arena, &link_args, Lit("link.exe /nologo %F /OUT:\"%F\" /DEBUG:FULL /OPT:REF /OPT:ICF")); String warnings = Lit("/WX /Wall " "/options:strict " "/wd4820 /wd4201 /wd5220 /wd4514 /wd4244 /wd5045 /wd4242 /wd4061 /wd4189 /wd4723 /wd5246"); - StringListAppend(arena, &compile_warnings, warnings); - StringListAppend(arena, &link_warnings, Lit("/WX")); + StringListAppend(&arena, &compile_warnings, warnings); + StringListAppend(&arena, &link_warnings, Lit("/WX")); - StringListAppend(arena, &compile_args, StringF(arena, Lit("/Fd\"%F\\\""), FmtStr(out_bin_dir_path))); + StringListAppend(&arena, &compile_args, StringF(&arena, Lit("/Fd\"%F\\\""), FmtStr(out_bin_dir_path))); } else { /* Clang */ - StringListAppend(arena, &c_compile_args, Lit("clang -xc -std=c99 -c \"%F\" -o \"%F\" -MD")); - StringListAppend(arena, &cpp_compile_args, Lit("clang -xc++ -std=c++20 -c \"%F\" -o \"%F\" -MD")); - StringListAppend(arena, &pch_c_compile_args, Lit("clang -xc-header -std=c99 -c \"%F\" -o \"%F\" -MD")); - StringListAppend(arena, &pch_cpp_compile_args, Lit("clang -xc++-header -std=c++20 -c \"%F\" -o \"%F\" -MD")); - StringListAppend(arena, &rc_compile_args, Lit("llvm-rc /fo\"%F\" \"%F\"")); + StringListAppend(&arena, &c_compile_args, Lit("clang -xc -std=c99 -c \"%F\" -o \"%F\" -MD")); + StringListAppend(&arena, &cpp_compile_args, Lit("clang -xc++ -std=c++20 -c \"%F\" -o \"%F\" -MD")); + StringListAppend(&arena, &pch_c_compile_args, Lit("clang -xc-header -std=c99 -c \"%F\" -o \"%F\" -MD")); + StringListAppend(&arena, &pch_cpp_compile_args, Lit("clang -xc++-header -std=c++20 -c \"%F\" -o \"%F\" -MD")); + StringListAppend(&arena, &rc_compile_args, Lit("llvm-rc /fo\"%F\" \"%F\"")); - StringListAppend(arena, &link_args, Lit("clang %F -o \"%F\"")); + StringListAppend(&arena, &link_args, Lit("clang %F -o \"%F\"")); - StringListAppend(arena, + StringListAppend(&arena, &compile_and_link_args, Lit("-fuse-ld=lld-link " "-fno-strict-aliasing " @@ -245,8 +477,8 @@ void OnBuild(StringList cli_args) "-Wno-double-promotion"); /* -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter */ - StringListAppend(arena, &compile_warnings, warnings); - StringListAppend(arena, &link_warnings, warnings); + StringListAppend(&arena, &compile_warnings, warnings); + StringListAppend(&arena, &link_warnings, warnings); } /* RTC */ @@ -255,56 +487,56 @@ void OnBuild(StringList cli_args) Error(Lit("CRTLIB (C runtime library) Must be enabled when compiling with RTC (runtime checks)")); OS_Exit(1); } - StringListAppend(arena, &compile_args, Lit("-DRTC=1")); + StringListAppend(&arena, &compile_args, Lit("-DRTC=1")); if (arg_msvc) { if (!arg_asan) { /* Enable /RTC option (not compatible with ASAN) */ - StringListAppend(arena, &compile_and_link_args, Lit("/RTCcsu")); + StringListAppend(&arena, &compile_and_link_args, Lit("/RTCcsu")); } } else { /* Enable UBSan */ - StringListAppend(arena, &compile_and_link_args, Lit("-fsanitize=undefined -fsanitize-trap=all")); - //StringListAppend(arena, &compile_and_link_args, Lit("-fsanitize=undefined")); + StringListAppend(&arena, &compile_and_link_args, Lit("-fsanitize=undefined -fsanitize-trap=all")); + //StringListAppend(&arena, &compile_and_link_args, Lit("-fsanitize=undefined")); } } /* CRTLIB */ if (arg_crtlib) { - StringListAppend(arena, &compile_args, Lit("-DCRTLIB=1")); + StringListAppend(&arena, &compile_args, Lit("-DCRTLIB=1")); } else { if (arg_msvc) { /* TODO */ Error(Lit("TODO\n")); OS_Exit(1); } else { - StringListAppend(arena, &compile_and_link_args, Lit("-mno-stack-arg-probe -fno-builtin -nostdlib")); + StringListAppend(&arena, &compile_and_link_args, Lit("-mno-stack-arg-probe -fno-builtin -nostdlib")); } } /* Optimization */ if (arg_unoptimized) { - StringListAppend(arena, &compile_args, Lit("-DUNOPTIMIZED=1")); + StringListAppend(&arena, &compile_args, Lit("-DUNOPTIMIZED=1")); if (arg_msvc) { - StringListAppend(arena, &compile_args, Lit("/Od")); + StringListAppend(&arena, &compile_args, Lit("/Od")); } else { - StringListAppend(arena, &compile_and_link_args, Lit("-O0")); + StringListAppend(&arena, &compile_and_link_args, Lit("-O0")); } } else { if (arg_msvc) { - StringListAppend(arena, &compile_args, Lit("/O2")); - StringListAppend(arena, &link_args, Lit("/LTCG")); + StringListAppend(&arena, &compile_args, Lit("/O2")); + StringListAppend(&arena, &link_args, Lit("/LTCG")); } else { - StringListAppend(arena, &compile_and_link_args, Lit("-O3 -flto")); + StringListAppend(&arena, &compile_and_link_args, Lit("-O3 -flto")); } } /* Debug info */ if (arg_debinfo) { - StringListAppend(arena, &compile_args, Lit("-DDEBINFO=1")); + StringListAppend(&arena, &compile_args, Lit("-DDEBINFO=1")); if (arg_msvc) { - StringListAppend(arena, &compile_args, Lit("/JMC /Zi")); + StringListAppend(&arena, &compile_args, Lit("/JMC /Zi")); } else { - StringListAppend(arena, &compile_and_link_args, Lit("-g")); + StringListAppend(&arena, &compile_and_link_args, Lit("-g")); } } @@ -314,17 +546,17 @@ void OnBuild(StringList cli_args) Error(Lit("CRTLIB (C runtime library) Must be enabled when compiling with asan enabled")); OS_Exit(1); } - StringListAppend(arena, &compile_args, Lit("-DASAN=1")); + StringListAppend(&arena, &compile_args, Lit("-DASAN=1")); if (arg_msvc) { - StringListAppend(arena, &compile_args, Lit("/fsanitize=address")); + StringListAppend(&arena, &compile_args, Lit("/fsanitize=address")); } else { - StringListAppend(arena, &compile_and_link_args, Lit("-fsanitize=address -shared-libasan")); + StringListAppend(&arena, &compile_and_link_args, Lit("-fsanitize=address -shared-libasan")); } } /* Developer mode */ if (arg_developer) { - StringListAppend(arena, &compile_args, Lit("-DDEVELOPER=1")); + StringListAppend(&arena, &compile_args, Lit("-DDEVELOPER=1")); } /* Profiling */ @@ -337,19 +569,19 @@ void OnBuild(StringList cli_args) Error(Lit("MSVC not supported with profiling enabled (Profiling relies on Clang attributes)")); OS_Exit(1); } - StringListAppend(arena, &compile_args, Lit("-DPROFILING=1")); + StringListAppend(&arena, &compile_args, Lit("-DPROFILING=1")); /* Tracy flags */ - StringListAppend(arena, &compile_args, Lit("-DTRACY_ENABLE=1")); - StringListAppend(arena, &compile_args, Lit("-DTRACY_CALLSTACK=5")); - StringListAppend(arena, &compile_args, Lit("-DTRACY_NO_SAMPLING -DTRACY_NO_SYSTEM_TRACING -DTRACY_NO_CALLSTACK")); + StringListAppend(&arena, &compile_args, Lit("-DTRACY_ENABLE=1")); + StringListAppend(&arena, &compile_args, Lit("-DTRACY_CALLSTACK=5")); + StringListAppend(&arena, &compile_args, Lit("-DTRACY_NO_SAMPLING -DTRACY_NO_SYSTEM_TRACING -DTRACY_NO_CALLSTACK")); /* Disable compile_warnings when compiling tracy client */ compile_warnings = (StringList) { 0 }; link_warnings = (StringList) { 0 }; } if (!arg_msvc) { - String incbin_dir = StringReplace(arena, out_inc_dir_path, Lit("\\"), Lit("/")); - StringListAppend(arena, &compile_args, StringF(arena, Lit("-DINCBIN_DIR_RAW=\"%F\""), FmtStr(incbin_dir))); + String incbin_dir = StringReplace(&arena, out_inc_dir_path, Lit("\\"), Lit("/")); + StringListAppend(&arena, &compile_args, StringF(&arena, Lit("-DINCBIN_DIR_RAW=\"%F\""), FmtStr(incbin_dir))); } } @@ -358,11 +590,11 @@ void OnBuild(StringList cli_args) * ========================== */ { - D_Tag build_hash_file = D_TagFromPath(arena, build_hash_path, D_TagKind_File); + D_Tag build_hash_file = D_TagFromPath(&arena, build_hash_path, D_TagKind_File); U64 build_hash = D_HashString64Basis; { - String args_str = StringFromStringList(arena, Lit(" "), cli_args); + String args_str = StringFromStringList(&arena, Lit(" "), cli_args); String compile_time_str = Lit(__DATE__ __TIME__); build_hash = D_HashString64(build_hash, args_str); build_hash = D_HashString64(build_hash, compile_time_str); @@ -370,7 +602,7 @@ void OnBuild(StringList cli_args) U64 old_build_hash = 0; { - String build_hash_file_data = D_ReadAll(arena, build_hash_file); + String build_hash_file_data = D_ReadAll(&arena, build_hash_file); if (build_hash_file_data.len >= 8) { MemoryCopy((Byte *)&old_build_hash, build_hash_file_data.text, 8); } @@ -389,10 +621,13 @@ void OnBuild(StringList cli_args) * Build * ========================== */ - hist = ArenaPush(arena, D_Hist); - *hist = D_HistFromPath(arena, hist_path); + hist = D_HistFromPath(&arena, hist_path); + + StepList tar_build_steps = StepListAlloc(); + StepList rc_and_pch_build_steps = StepListAlloc(); + StepList comp_build_steps = StepListAlloc(); + StepList link_build_steps = StepListAlloc(); - StepList build_steps = { 0 }; D_TagList link_files = { 0 }; /* ========================== * @@ -402,25 +637,26 @@ void OnBuild(StringList cli_args) { D_TagList tar_input_dirs = { 0 }; { - D_TagListAppend(arena, &tar_input_dirs, shaders_dir); + D_TagListAppend(&arena, &tar_input_dirs, shaders_dir); if (should_embed_res_dir) { - D_TagListAppend(arena, &tar_input_dirs, res_dir); + D_TagListAppend(&arena, &tar_input_dirs, res_dir); } } for (D_TagListNode *n = tar_input_dirs.first; n; n = n->next) { D_Tag input_dir = n->tag; - D_Tag tar_file = D_TagFromPath(arena, StringF(arena, Lit("%F/%F.tar"), FmtStr(out_inc_dir_path), FmtStr(D_GetName(input_dir))), D_TagKind_File); - D_AddDependency(tar_file, input_dir); + D_Tag tar_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/%F.tar"), FmtStr(out_inc_dir_path), FmtStr(D_GetName(input_dir))), D_TagKind_File); + D_AddDependency(&store, tar_file, input_dir); if (should_embed_in_rc) { - D_AddDependency(rc_res_file, tar_file); + D_AddDependency(&store, rc_res_file, tar_file); } else { - D_AddDependency(inc_src_file, tar_file); + D_AddDependency(&store, inc_src_file, tar_file); } if (IsDirty(tar_file)) { - String cmd = StringF(arena, Lit("cd %F && tar cvf %F ."), FmtStr(input_dir.full_path), FmtStr(tar_file.full_path)); - String step_name = StringF(arena, Lit("%F -> %F"), FmtStr(D_GetName(input_dir)), FmtStr(D_GetName(tar_file))); - StepListAppend(&build_steps, step_name, cmd, true); + BuildStepSimpleCommandArg *bs_arg = ArenaPush(&arena, BuildStepSimpleCommandArg); + bs_arg->cmd = StringF(&arena, Lit("cd %F && tar cvf %F ."), FmtStr(input_dir.full_path), FmtStr(tar_file.full_path)); + String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(input_dir)), FmtStr(D_GetName(tar_file))); + AddStep(&tar_build_steps, step_name, &BuildStepSimpleCommand, bs_arg); } } } @@ -430,40 +666,41 @@ void OnBuild(StringList cli_args) * ========================== */ if (PlatformWindows) { - D_Tag rc_input_file = D_TagFromPath(arena, StringF(arena, Lit("%F/rc.rc"), FmtStr(out_inc_dir_path)), D_TagKind_File); + D_Tag rc_input_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/rc.rc"), FmtStr(out_inc_dir_path)), D_TagKind_File); { - D_Tag shaders_tar_file = D_TagFromPath(arena, StringF(arena, Lit("%F/%F.tar"), FmtStr(out_inc_dir_path), FmtStr(D_GetName(shaders_dir))), D_TagKind_File); - D_Tag res_tar_file = D_TagFromPath(arena, StringF(arena, Lit("%F/%F.tar"), FmtStr(out_inc_dir_path), FmtStr(D_GetName(res_dir))), D_TagKind_File); - D_AddDependency(rc_input_file, icon_file); + D_Tag shaders_tar_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/%F.tar"), FmtStr(out_inc_dir_path), FmtStr(D_GetName(shaders_dir))), D_TagKind_File); + D_Tag res_tar_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/%F.tar"), FmtStr(out_inc_dir_path), FmtStr(D_GetName(res_dir))), D_TagKind_File); + D_AddDependency(&store, rc_input_file, icon_file); if (should_embed_in_rc) { - D_AddDependency(rc_input_file, shaders_tar_file); + D_AddDependency(&store, rc_input_file, shaders_tar_file); if (should_embed_res_dir) { - D_AddDependency(rc_input_file, res_tar_file); + D_AddDependency(&store, rc_input_file, res_tar_file); } } if (IsDirty(rc_input_file)) { D_ClearWrite(rc_input_file, Lit("")); - D_AppendWrite(rc_input_file, StringF(arena, Lit("%F %F DISCARDABLE %F\n"), FmtStr(D_GetName(icon_file)), FmtStr(Lit("ICON")), FmtStr(D_GetName(icon_file)))); + D_AppendWrite(rc_input_file, StringF(&arena, Lit("%F %F DISCARDABLE %F\n"), FmtStr(D_GetName(icon_file)), FmtStr(Lit("ICON")), FmtStr(D_GetName(icon_file)))); if (should_embed_in_rc) { - D_AppendWrite(rc_input_file, StringF(arena, Lit("%F %F DISCARDABLE %F\n"), FmtStr(D_GetName(shaders_tar_file)), FmtStr(Lit("RCDATA")), FmtStr(D_GetName(shaders_tar_file)))); + D_AppendWrite(rc_input_file, StringF(&arena, Lit("%F %F DISCARDABLE %F\n"), FmtStr(D_GetName(shaders_tar_file)), FmtStr(Lit("RCDATA")), FmtStr(D_GetName(shaders_tar_file)))); if (should_embed_res_dir) { - D_AppendWrite(rc_input_file, StringF(arena, Lit("%F %F DISCARDABLE %F\n"), FmtStr(D_GetName(res_tar_file)), FmtStr(Lit("RCDATA")), FmtStr(D_GetName(res_tar_file)))); + D_AppendWrite(rc_input_file, StringF(&arena, Lit("%F %F DISCARDABLE %F\n"), FmtStr(D_GetName(res_tar_file)), FmtStr(Lit("RCDATA")), FmtStr(D_GetName(res_tar_file)))); } } } } { - String rc_compile_args_fmt = StringFromStringLists(arena, Lit(" "), rc_compile_args); - D_AddDependency(rc_res_file, rc_input_file); + String rc_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), rc_compile_args); + D_AddDependency(&store, rc_res_file, rc_input_file); if (IsDirty(rc_res_file)) { - String cmd = StringF(arena, rc_compile_args_fmt, FmtStr(rc_res_file.full_path), FmtStr(rc_input_file.full_path)); - String step_name = StringF(arena, Lit("%F -> %F"), FmtStr(D_GetName(rc_input_file)), FmtStr(D_GetName(rc_res_file))); - StepListAppend(&build_steps, step_name, cmd, true); + BuildStepSimpleCommandArg *bs_arg = ArenaPush(&arena, BuildStepSimpleCommandArg); + bs_arg->cmd = StringF(&arena, rc_compile_args_fmt, FmtStr(rc_res_file.full_path), FmtStr(rc_input_file.full_path)); + String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(rc_input_file)), FmtStr(D_GetName(rc_res_file))); + AddStep(&rc_and_pch_build_steps, step_name, &BuildStepSimpleCommand, bs_arg); } - D_TagListAppend(arena, &link_files, rc_res_file); + D_TagListAppend(&arena, &link_files, rc_res_file); } } @@ -472,78 +709,82 @@ void OnBuild(StringList cli_args) * ========================== */ { - D_Tag pch_header_file = D_TagFromPath(arena, Lit("src/common.h"), D_TagKind_File); + D_Tag pch_header_file = D_TagFromPath(&arena, Lit("src/common.h"), D_TagKind_File); D_Tag dep_file; { String name = D_GetName(pch_header_file); - String dep_file_path = StringF(arena, Lit("%F/%F.%F"), FmtStr(out_obj_dir_path), FmtStr(name), FmtStr(dep_file_extension)); - dep_file = D_TagFromPath(arena, dep_file_path, D_TagKind_DepFile); + String dep_file_path = StringF(&arena, Lit("%F/%F.%F"), FmtStr(out_obj_dir_path), FmtStr(name), FmtStr(dep_file_extension)); + dep_file = D_TagFromPath(&arena, dep_file_path, D_TagKind_DepFile); } - D_Tag pch_c_file = D_TagFromPath(arena, StringF(arena, Lit("%F/%F.c_pch"), FmtStr(out_obj_dir_path), FmtStr(D_GetName(pch_header_file))), D_TagKind_File); - D_AddDependency(pch_c_file, pch_header_file); - D_AddDependency(pch_c_file, dep_file); + D_Tag pch_c_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/%F.c_pch"), FmtStr(out_obj_dir_path), FmtStr(D_GetName(pch_header_file))), D_TagKind_File); + D_AddDependency(&store, pch_c_file, pch_header_file); + D_AddDependency(&store, pch_c_file, dep_file); - D_Tag pch_cpp_file = D_TagFromPath(arena, StringF(arena, Lit("%F/%F.cpp_pch"), FmtStr(out_obj_dir_path), FmtStr(D_GetName(pch_header_file))), D_TagKind_File); - D_AddDependency(pch_cpp_file, pch_header_file); - D_AddDependency(pch_cpp_file, dep_file); + D_Tag pch_cpp_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/%F.cpp_pch"), FmtStr(out_obj_dir_path), FmtStr(D_GetName(pch_header_file))), D_TagKind_File); + D_AddDependency(&store, pch_cpp_file, pch_header_file); + D_AddDependency(&store, pch_cpp_file, dep_file); if (arg_msvc) { - D_Tag pch_c_src_gen_file = D_TagFromPath(arena, StringF(arena, Lit("%F/common.c"), FmtStr(out_obj_dir_path)), D_TagKind_File); - D_Tag pch_c_src_gen_obj_file = D_TagFromPath(arena, StringF(arena, Lit("%F/common.c.obj"), FmtStr(out_obj_dir_path)), D_TagKind_File); - D_Tag pch_cpp_src_gen_file = D_TagFromPath(arena, StringF(arena, Lit("%F/common.cpp"), FmtStr(out_obj_dir_path)), D_TagKind_File); - D_Tag pch_cpp_src_gen_obj_file = D_TagFromPath(arena, StringF(arena, Lit("%F/common.cpp.obj"), FmtStr(out_obj_dir_path)), D_TagKind_File); + D_Tag pch_c_src_gen_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/common.c"), FmtStr(out_obj_dir_path)), D_TagKind_File); + D_Tag pch_c_src_gen_obj_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/common.c.obj"), FmtStr(out_obj_dir_path)), D_TagKind_File); + D_Tag pch_cpp_src_gen_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/common.cpp"), FmtStr(out_obj_dir_path)), D_TagKind_File); + D_Tag pch_cpp_src_gen_obj_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/common.cpp.obj"), FmtStr(out_obj_dir_path)), D_TagKind_File); - StringListAppend(arena, &c_compile_args, StringF(arena, Lit("/Yu\"%F\" /FI\"%F\" /Fp\"%F\""), FmtStr(pch_header_file.full_path), FmtStr(pch_header_file.full_path), FmtStr(pch_c_file.full_path))); - StringListAppend(arena, &cpp_compile_args, StringF(arena, Lit("/Yu\"%F\" /FI\"%F\" /Fp\"%F\""), FmtStr(pch_header_file.full_path), FmtStr(pch_header_file.full_path), FmtStr(pch_cpp_file.full_path))); - StringListAppend(arena, &pch_c_compile_args, StringF(arena, Lit("/FI\"%F\" /Fp\"%F\" /Fo\"%F\""), FmtStr(pch_header_file.full_path), FmtStr(pch_c_file.full_path), FmtStr(pch_c_src_gen_obj_file.full_path))); - StringListAppend(arena, &pch_cpp_compile_args, StringF(arena, Lit("/FI\"%F\" /Fp\"%F\" /Fo\"%F\""), FmtStr(pch_header_file.full_path), FmtStr(pch_cpp_file.full_path), FmtStr(pch_cpp_src_gen_obj_file.full_path))); + StringListAppend(&arena, &c_compile_args, StringF(&arena, Lit("/Yu\"%F\" /FI\"%F\" /Fp\"%F\""), FmtStr(pch_header_file.full_path), FmtStr(pch_header_file.full_path), FmtStr(pch_c_file.full_path))); + StringListAppend(&arena, &cpp_compile_args, StringF(&arena, Lit("/Yu\"%F\" /FI\"%F\" /Fp\"%F\""), FmtStr(pch_header_file.full_path), FmtStr(pch_header_file.full_path), FmtStr(pch_cpp_file.full_path))); + StringListAppend(&arena, &pch_c_compile_args, StringF(&arena, Lit("/FI\"%F\" /Fp\"%F\" /Fo\"%F\""), FmtStr(pch_header_file.full_path), FmtStr(pch_c_file.full_path), FmtStr(pch_c_src_gen_obj_file.full_path))); + StringListAppend(&arena, &pch_cpp_compile_args, StringF(&arena, Lit("/FI\"%F\" /Fp\"%F\" /Fo\"%F\""), FmtStr(pch_header_file.full_path), FmtStr(pch_cpp_file.full_path), FmtStr(pch_cpp_src_gen_obj_file.full_path))); - D_TagListAppend(arena, &link_files, pch_c_src_gen_obj_file); - D_TagListAppend(arena, &link_files, pch_cpp_src_gen_obj_file); + D_TagListAppend(&arena, &link_files, pch_c_src_gen_obj_file); + D_TagListAppend(&arena, &link_files, pch_cpp_src_gen_obj_file); - String pch_c_compile_args_fmt = StringFromStringLists(arena, Lit(" "), pch_c_compile_args, compile_warnings, compile_and_link_args, compile_args); - String pch_cpp_compile_args_fmt = StringFromStringLists(arena, Lit(" "), pch_cpp_compile_args, compile_warnings, compile_and_link_args, compile_args); + String pch_c_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), pch_c_compile_args, compile_warnings, compile_and_link_args, compile_args); + String pch_cpp_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), pch_cpp_compile_args, compile_warnings, compile_and_link_args, compile_args); /* C */ - D_AddDependency(pch_c_src_gen_obj_file, pch_c_src_gen_file); - D_AddDependency(pch_c_file, pch_c_src_gen_obj_file); + D_AddDependency(&store, pch_c_src_gen_obj_file, pch_c_src_gen_file); + D_AddDependency(&store, pch_c_file, pch_c_src_gen_obj_file); if (IsDirty(pch_c_file)) { D_ClearWrite(pch_c_src_gen_file, Lit("")); - String cmd = StringF(arena, pch_c_compile_args_fmt, FmtStr(pch_header_file.full_path), FmtStr(pch_c_src_gen_file.full_path)); - String step_name = StringF(arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header_file)), FmtStr(D_GetName(pch_c_file))); - StepListAppend(&build_steps, step_name, cmd, true); + BuildStepSimpleCommandArg *bs_arg = ArenaPush(&arena, BuildStepSimpleCommandArg); + bs_arg->cmd = StringF(&arena, pch_c_compile_args_fmt, FmtStr(pch_header_file.full_path), FmtStr(pch_c_src_gen_file.full_path)); + String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header_file)), FmtStr(D_GetName(pch_c_file))); + AddStep(&rc_and_pch_build_steps, step_name, &BuildStepSimpleCommand, bs_arg); } /* Cpp */ - D_AddDependency(pch_cpp_src_gen_obj_file, pch_cpp_src_gen_file); - D_AddDependency(pch_cpp_file, pch_cpp_src_gen_obj_file); + D_AddDependency(&store, pch_cpp_src_gen_obj_file, pch_cpp_src_gen_file); + D_AddDependency(&store, pch_cpp_file, pch_cpp_src_gen_obj_file); if (IsDirty(pch_cpp_file)) { D_ClearWrite(pch_cpp_src_gen_file, Lit("")); - String cmd = StringF(arena, pch_cpp_compile_args_fmt, FmtStr(pch_header_file.full_path), FmtStr(pch_cpp_src_gen_file.full_path)); - String step_name = StringF(arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header_file)), FmtStr(D_GetName(pch_cpp_file))); - StepListAppend(&build_steps, step_name, cmd, true); + BuildStepSimpleCommandArg *bs_arg = ArenaPush(&arena, BuildStepSimpleCommandArg); + bs_arg->cmd = StringF(&arena, pch_cpp_compile_args_fmt, FmtStr(pch_header_file.full_path), FmtStr(pch_cpp_src_gen_file.full_path)); + String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header_file)), FmtStr(D_GetName(pch_cpp_file))); + AddStep(&rc_and_pch_build_steps, step_name, &BuildStepSimpleCommand, bs_arg); } } else { - StringListAppend(arena, &c_compile_args, StringF(arena, Lit("-include-pch %F"), FmtStr(pch_c_file.full_path))); - StringListAppend(arena, &cpp_compile_args, StringF(arena, Lit("-include-pch %F"), FmtStr(pch_cpp_file.full_path))); + StringListAppend(&arena, &c_compile_args, StringF(&arena, Lit("-include-pch %F"), FmtStr(pch_c_file.full_path))); + StringListAppend(&arena, &cpp_compile_args, StringF(&arena, Lit("-include-pch %F"), FmtStr(pch_cpp_file.full_path))); - String pch_c_compile_args_fmt = StringFromStringLists(arena, Lit(" "), pch_c_compile_args, compile_warnings, compile_and_link_args, compile_args); - String pch_cpp_compile_args_fmt = StringFromStringLists(arena, Lit(" "), pch_cpp_compile_args, compile_warnings, compile_and_link_args, compile_args); + String pch_c_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), pch_c_compile_args, compile_warnings, compile_and_link_args, compile_args); + String pch_cpp_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), pch_cpp_compile_args, compile_warnings, compile_and_link_args, compile_args); /* C */ if (IsDirty(pch_c_file)) { - String comp_cmd = StringF(arena, pch_c_compile_args_fmt, FmtStr(pch_header_file.full_path), FmtStr(pch_c_file.full_path)); - String step_name = StringF(arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header_file)), FmtStr(D_GetName(pch_c_file))); - StepListAppend(&build_steps, step_name, comp_cmd, true); + BuildStepSimpleCommandArg *bs_arg = ArenaPush(&arena, BuildStepSimpleCommandArg); + bs_arg->cmd = StringF(&arena, pch_c_compile_args_fmt, FmtStr(pch_header_file.full_path), FmtStr(pch_c_file.full_path)); + String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header_file)), FmtStr(D_GetName(pch_c_file))); + AddStep(&rc_and_pch_build_steps, step_name, &BuildStepSimpleCommand, bs_arg); } /* Cpp */ if (IsDirty(pch_cpp_file)) { - String comp_cmd = StringF(arena, pch_cpp_compile_args_fmt, FmtStr(pch_header_file.full_path), FmtStr(pch_cpp_file.full_path)); - String step_name = StringF(arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header_file)), FmtStr(D_GetName(pch_cpp_file))); - StepListAppend(&build_steps, step_name, comp_cmd, true); + BuildStepSimpleCommandArg *bs_arg = ArenaPush(&arena, BuildStepSimpleCommandArg); + bs_arg->cmd = StringF(&arena, pch_cpp_compile_args_fmt, FmtStr(pch_header_file.full_path), FmtStr(pch_cpp_file.full_path)); + String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header_file)), FmtStr(D_GetName(pch_cpp_file))); + AddStep(&rc_and_pch_build_steps, step_name, &BuildStepSimpleCommand, bs_arg); } } } @@ -555,8 +796,8 @@ void OnBuild(StringList cli_args) { D_TagList src_input_files = { 0 }; { - D_Tag src_dir = D_TagFromPath(arena, Lit("src"), D_TagKind_Dir); - D_TagList src_dir_files = D_GetDirContents(arena, src_dir); + D_Tag src_dir = D_TagFromPath(&arena, Lit("src"), D_TagKind_Dir); + D_TagList src_dir_files = D_GetDirContents(&arena, src_dir); for (D_TagListNode *n = src_dir_files.first; n; n = n->next) { Bool ignore = true; @@ -586,14 +827,14 @@ void OnBuild(StringList cli_args) } if (!ignore) { - D_TagListAppend(arena, &src_input_files, file); + D_TagListAppend(&arena, &src_input_files, file); } } } { - String c_compile_args_fmt = StringFromStringLists(arena, Lit(" "), c_compile_args, compile_warnings, compile_and_link_args, compile_args); - String cpp_compile_args_fmt = StringFromStringLists(arena, Lit(" "), cpp_compile_args, compile_warnings, compile_and_link_args, compile_args); + String c_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), c_compile_args, compile_warnings, compile_and_link_args, compile_args); + String cpp_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), cpp_compile_args, compile_warnings, compile_and_link_args, compile_args); for (D_TagListNode *n = src_input_files.first; n; n = n->next) { D_Tag file = n->tag; String path = file.full_path; @@ -605,27 +846,28 @@ void OnBuild(StringList cli_args) D_Tag dep_file; { String name_no_extension = StringPathNoExtension(name); - String dep_file_path = StringF(arena, Lit("%F/%F.%F"), FmtStr(out_obj_dir_path), FmtStr(name_no_extension), FmtStr(dep_file_extension)); - dep_file = D_TagFromPath(arena, dep_file_path, D_TagKind_DepFile); + String dep_file_path = StringF(&arena, Lit("%F/%F.%F"), FmtStr(out_obj_dir_path), FmtStr(name_no_extension), FmtStr(dep_file_extension)); + dep_file = D_TagFromPath(&arena, dep_file_path, D_TagKind_DepFile); } D_Tag obj_file; { String name_no_extension = StringPathNoExtension(name); - String obj_file_path = StringF(arena, Lit("%F/%F.%F"), FmtStr(out_obj_dir_path), FmtStr(name_no_extension), FmtStr(obj_file_extension)); - obj_file = D_TagFromPath(arena, obj_file_path, D_TagKind_File); + String obj_file_path = StringF(&arena, Lit("%F/%F.%F"), FmtStr(out_obj_dir_path), FmtStr(name_no_extension), FmtStr(obj_file_extension)); + obj_file = D_TagFromPath(&arena, obj_file_path, D_TagKind_File); } - D_AddDependency(obj_file, file); - D_AddDependency(obj_file, dep_file); + D_AddDependency(&store, obj_file, file); + D_AddDependency(&store, obj_file, dep_file); if (IsDirty(obj_file)) { String comp_cmd_fmt = is_c ? c_compile_args_fmt : cpp_compile_args_fmt; - String comp_cmd = StringF(arena, comp_cmd_fmt, FmtStr(file.full_path), FmtStr(obj_file.full_path)); - String step_name = StringF(arena, Lit("%F -> %F"), FmtStr(name), FmtStr(D_GetName(obj_file))); - StepListAppend(&build_steps, step_name, comp_cmd, true); + BuildStepSimpleCommandArg *bs_arg = ArenaPush(&arena, BuildStepSimpleCommandArg); + bs_arg->cmd = StringF(&arena, comp_cmd_fmt, FmtStr(file.full_path), FmtStr(obj_file.full_path)); + String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(name), FmtStr(D_GetName(obj_file))); + AddStep(&comp_build_steps, step_name, &BuildStepSimpleCommand, bs_arg); } - D_TagListAppend(arena, &link_files, obj_file); + D_TagListAppend(&arena, &link_files, obj_file); } } } @@ -641,66 +883,114 @@ void OnBuild(StringList cli_args) StringList link_files_quoted_list = { 0 }; for (D_TagListNode *n = link_files.first; n; n = n->next) { D_Tag file = n->tag; - String path = StringF(arena, Lit("\"%F\""), FmtStr(file.full_path)); - StringListAppend(arena, &link_files_quoted_list, path); - D_AddDependency(executable_file, file); + String path = StringF(&arena, Lit("\"%F\""), FmtStr(file.full_path)); + StringListAppend(&arena, &link_files_quoted_list, path); + D_AddDependency(&store, executable_file, file); } - link_files_str = StringFromStringList(arena, Lit(" "), link_files_quoted_list); + link_files_str = StringFromStringList(&arena, Lit(" "), link_files_quoted_list); } if (link_files_str.len > 0) { - String link_args_fmt = StringFromStringLists(arena, Lit(" "), link_args, link_warnings, compile_and_link_args); - String cmd = StringF(arena, link_args_fmt, FmtStr(link_files_str), FmtStr(executable_file.full_path)); - StepListAppend(&build_steps, Lit("Linking"), cmd, true); + String link_args_fmt = StringFromStringLists(&arena, Lit(" "), link_args, link_warnings, compile_and_link_args); + BuildStepSimpleCommandArg *bs_arg = ArenaPush(&arena, BuildStepSimpleCommandArg); + bs_arg->cmd = StringF(&arena, link_args_fmt, FmtStr(link_files_str), FmtStr(executable_file.full_path)); + String step_name = Lit("Linking"); + AddStep(&link_build_steps, step_name, &BuildStepSimpleCommand, bs_arg); } } - /* ========================== * - * Execute build steps - * - * TODO: Parallelize - * ========================== */ + /* ========================== * + * Execute build steps + * ========================== */ - { - Bool success = true; - if (IsDirty(executable_file)) { - Size step_i = 0; - Size step_count = build_steps.count; - for (StepListNode *n = build_steps.first; n; n = n->next) { - ++step_i; - String cmd = n->cmd; - if (cmd.len > 0) { - SH_PrintF(Lit("[%F/%F] %F\n"), FmtI64(step_i), FmtI64(step_count), FmtStr(n->name)); - //SH_PrintF(Lit("%F\n"), FmtStr(cmd)); - SH_CommandResult result = SH_RunCommandCaptureOutput(arena, cmd, true); - if (!n->silence_if_success || result.error != 0) { - SH_PrintF(Lit("%F\n"), FmtStr(result.output)); - } - if (result.error != 0) { - Assert(false); - success = false; - break; + /* TODO: Cleanup (testing parallel stuff) */ + + Bool success = true; + if (IsDirty(executable_file)) { + AddStepListToWorkQueue(&tar_build_steps); + AddStepListToWorkQueue(&rc_and_pch_build_steps); + AddStepListToWorkQueue(&comp_build_steps); + AddStepListToWorkQueue(&link_build_steps); + + I64 step_count = 0; + step_count += tar_build_steps.count; + step_count += rc_and_pch_build_steps.count; + step_count += comp_build_steps.count; + step_count += link_build_steps.count; + + Step *s = tar_build_steps.first; + { + if (!s) { + s = rc_and_pch_build_steps.first; + if (!s) { + s = comp_build_steps.first; + if (!s) { + s = link_build_steps.first; } } + } - } else { - SH_Print(Lit("No work to do\n")); } - if (!success) { - Error(Lit("Build failed\n")); - OS_Exit(1); + I64 step_i = 0; + while (s) { + ++step_i; + + SH_PrintF(Lit("[%F/%F] %F\n"), FmtI64(step_i), FmtI64(step_count), FmtStr(s->name)); + + OS_MutexLockR(&s->res_mutex); + { + while (s->res_status == StepStatus_None) { + OS_ConditionVariableWaitR(&s->res_cv, &s->res_mutex); + } + } + OS_MutexUnlockR(&s->res_mutex); + + String output = s->res_output; + if (s->res_status != StepStatus_Success) { + Assert(false); + success = false; + SH_PrintF(Lit("%F\n"), FmtStr(output)); + break; + } + + { + if (s == tar_build_steps.last) { + s = rc_and_pch_build_steps.first; + if (s) goto skip_cont; + } + if (s == rc_and_pch_build_steps.last) { + s = comp_build_steps.first; + if (s) goto skip_cont; + } + if (s == comp_build_steps.last) { + s = link_build_steps.first; + if (s) goto skip_cont; + } + } + s = s->next; + skip_cont: + continue; } + } else { + SH_Print(Lit("No work to do\n")); + } + + if (!success) { + Error(Lit("Build failed\n")); + OS_Exit(1); } /* ========================== * * Write hist file * ========================== */ - D_WriteStateToHistFile(hist_path); + D_WriteStoreToHistFile(&store, hist_path); OS_TimeStamp end = OS_GetTimeStamp(); F64 seconds = OS_SecondsFromTimeStamp(end - start); SH_PrintF(Lit("Finished in %F seconds\n"), FmtF64P(seconds, 5)); + ShutdownWorkers(); + #if 0 #if Rtc getchar();