diff --git a/build.c b/build.c index c0f197bf..05051801 100644 --- a/build.c +++ b/build.c @@ -2,9 +2,8 @@ #include "buildit.h" typedef struct StepList StepList; -/* ========================== * - * Globals - * ========================== */ +//////////////////////////////// +//~ Globals Bool force_rebuild = 0; @@ -24,9 +23,8 @@ Bool arg_developer = 0; Bool arg_profiling = 0; Bool arg_unoptimized = 0; -/* ========================== * - * Util - * ========================== */ +//////////////////////////////// +//~ Utilities void Error(String msg) { @@ -36,8 +34,10 @@ void Error(String msg) Bool IsDirty(D_Tag tag) { Bool res = force_rebuild ? 1 : D_IsDirty(&store, &hist, tag); - if (!res) { - if (tag.kind == D_TagKind_File || tag.kind == D_TagKind_Dir) { + if (!res) + { + if (tag.kind == D_TagKind_File || tag.kind == D_TagKind_Dir) + { res = !D_Exists(tag); } } @@ -56,21 +56,22 @@ void KillRunningProcesses(void) SH_RunCommand(Lit("taskkill /im PowerPlay.exe /f /fi \"STATUS eq RUNNING\""), 1); } -/* ========================== * - * Step - * ========================== */ +//////////////////////////////// +//~ Steplist operations typedef struct StepList StepList; -typedef enum StepStatus { +typedef I32 StepStatus; enum +{ StepStatus_None, StepStatus_Success, StepStatus_Failure, StepStatus_Skipped -} StepStatus; +}; typedef struct Step Step; -struct Step { +struct Step +{ String name; void *arg; @@ -83,7 +84,8 @@ struct Step { }; typedef struct StepList StepList; -struct StepList { +struct StepList +{ OS_Mutex mutex; Arena arena; @@ -120,24 +122,28 @@ void ExecuteSteps(void) T_Execute(&sl->tq); } -/* ========================== * - * Clean result output - * ========================== */ +//////////////////////////////// +//~ Output cleaning operations /* TODO: Move to buildit */ Size StringFind(String s, String pattern) { Size pos = -1; - for (Size i = 0; i < s.len; ++i) { - if ((s.len - i) >= pattern.len) { + for (Size i = 0; i < s.len; ++i) + { + if ((s.len - i) >= pattern.len) + { String cmp = { 0 }; cmp.text = s.text + i; cmp.len = pattern.len; - if (StringEqual(cmp, pattern)) { + if (StringEqual(cmp, pattern)) + { pos = i; break; } - } else { + } + else + { break; } } @@ -154,12 +160,14 @@ String CleanResultOutput(Arena *arena, String output) StringListAppend(scratch.arena, &patterns, Lit("\r\n")); StringListAppend(scratch.arena, &patterns, Lit("\n")); StringList lines = StringSplit(scratch.arena, output, patterns); - for (StringListNode *n = lines.first; n; n = n->next) { + for (StringListNode *n = lines.first; n; n = n->next) + { String line = n->string; String line_cleaned = line; /* Ignore MSVC header include messages */ - if (StringContains(line, Lit("Note: including file"))) { + if (StringContains(line, Lit("Note: including file"))) + { line_cleaned.len = 0; } @@ -167,15 +175,18 @@ String CleanResultOutput(Arena *arena, String output) * This is a hack to get around visual studio's "GoToNextLocation" * picking up noise from clang & msvc notes since src location * info is present, rather than going to the next error. */ - if (StringContains(line_cleaned, Lit(": note: "))) { + if (StringContains(line_cleaned, Lit(": note: "))) + { String trunc = Lit("power_play\\src\\"); Size pos = StringFind(line_cleaned, trunc); - if (pos < 0) { + if (pos < 0) + { trunc = Lit("power_play\\src/"); pos = StringFind(line_cleaned, trunc); } String line_trunced = line_cleaned; - if (pos >= 0) { + if (pos >= 0) + { line_trunced.text += pos + trunc.len; line_trunced.len -= pos + trunc.len; line_cleaned = StringCopy(scratch.arena, Lit("[note]: ")); @@ -183,7 +194,8 @@ String CleanResultOutput(Arena *arena, String output) } } - if (line_cleaned.len > 0) { + if (line_cleaned.len > 0) + { StringListAppend(scratch.arena, &res_lines, line_cleaned); } } @@ -194,12 +206,12 @@ String CleanResultOutput(Arena *arena, String output) return res; } -/* ========================== * - * Build steps - * ========================== */ +//////////////////////////////// +//~ Build step operations typedef struct BuildStepSimpleCommandArg BuildStepSimpleCommandArg; -struct BuildStepSimpleCommandArg { +struct BuildStepSimpleCommandArg +{ String cmd; Atomic32 *skip_flag; Atomic32 *failure_flag; @@ -209,7 +221,8 @@ struct BuildStepSimpleCommandArg { }; typedef struct BuildStepMsvcCompileCommandArg BuildStepMsvcCompileCommandArg; -struct BuildStepMsvcCompileCommandArg { +struct BuildStepMsvcCompileCommandArg +{ String cmd; Atomic32 *skip_flag; Atomic32 *failure_flag; @@ -227,12 +240,14 @@ void BuildStepSimpleCommand(void *arg_raw) Atomic32 *skip_flag = arg->skip_flag; Atomic32 *failure_flag = arg->failure_flag; - if (!skip_flag || !Atomic32Fetch(skip_flag)) { + if (!skip_flag || !Atomic32Fetch(skip_flag)) + { SH_CommandResult result = RunCommand(scratch.arena, arg->cmd); String result_output_cleaned = CleanResultOutput(scratch.arena, result.output); { OS_Lock res_lock = OS_MutexLockE(&s->res_mutex); - if (result_output_cleaned.len > 0) { + if (result_output_cleaned.len > 0) + { OS_Lock sl_lock = OS_MutexLockE(&sl->mutex); { s->res_output.text = ArenaPushArrayNoZero(&sl->arena, Byte, result_output_cleaned.len); @@ -242,25 +257,32 @@ void BuildStepSimpleCommand(void *arg_raw) MemoryCopy(s->res_output.text, result_output_cleaned.text, result_output_cleaned.len); } s->res_status = result.error ? StepStatus_Failure : StepStatus_Success; - if (!D_IsNil(arg->dxc_depfile)) { + if (!D_IsNil(arg->dxc_depfile)) + { String depfile_data = D_DepfileTextFromDxcOutput(scratch.arena, arg->dxc_depfile_dependent, result.output); D_ClearWrite(arg->dxc_depfile, depfile_data); } - if (result.error) { - if (failure_flag) { + if (result.error) + { + if (failure_flag) + { Atomic32FetchSet(failure_flag, 1); } - if (!D_IsNil(arg->delete_file_on_failure)) { + if (!D_IsNil(arg->delete_file_on_failure)) + { D_Delete(arg->delete_file_on_failure); } } OS_ConditionVariableBroadcast(&s->res_cv); OS_MutexUnlock(&res_lock); } - } else { + } + else + { OS_Lock res_lock = OS_MutexLockE(&s->res_mutex); s->res_status = StepStatus_Skipped; - if (failure_flag) { + if (failure_flag) + { Atomic32FetchSet(failure_flag, 1); } OS_ConditionVariableBroadcast(&s->res_cv); @@ -279,16 +301,19 @@ void BuildStepMsvcCompileCommand(void *arg_raw) Atomic32 *skip_flag = arg->skip_flag; Atomic32 *failure_flag = arg->failure_flag; - if (!skip_flag || !Atomic32Fetch(skip_flag)) { + if (!skip_flag || !Atomic32Fetch(skip_flag)) + { SH_CommandResult result = RunCommand(scratch.arena, arg->cmd); - if (!result.error && !D_IsNil(arg->depfile_dependent) && !D_IsNil(arg->output_depfile)) { + if (!result.error && !D_IsNil(arg->depfile_dependent) && !D_IsNil(arg->output_depfile)) + { String depfile_data = D_DepfileTextFromMsvcOutput(scratch.arena, arg->depfile_dependent, arg->depfile_force_includes, result.output); D_ClearWrite(arg->output_depfile, depfile_data); } String result_output_cleaned = CleanResultOutput(scratch.arena, result.output); { OS_Lock res_lock = OS_MutexLockE(&s->res_mutex); - if (result_output_cleaned.len > 0) { + if (result_output_cleaned.len > 0) + { OS_Lock sl_lock = OS_MutexLockE(&sl->mutex); { s->res_output.text = ArenaPushArrayNoZero(&sl->arena, Byte, result_output_cleaned.len); @@ -298,21 +323,27 @@ void BuildStepMsvcCompileCommand(void *arg_raw) MemoryCopy(s->res_output.text, result_output_cleaned.text, result_output_cleaned.len); } s->res_status = result.error ? StepStatus_Failure : StepStatus_Success; - if (result.error) { - if (failure_flag) { + if (result.error) + { + if (failure_flag) + { Atomic32FetchSet(failure_flag, 1); } - if (!D_IsNil(arg->delete_file_on_failure)) { + if (!D_IsNil(arg->delete_file_on_failure)) + { D_Delete(arg->delete_file_on_failure); } } OS_ConditionVariableBroadcast(&s->res_cv); OS_MutexUnlock(&res_lock); } - } else { + } + else + { OS_Lock res_lock = OS_MutexLockE(&s->res_mutex); s->res_status = StepStatus_Skipped; - if (failure_flag) { + if (failure_flag) + { Atomic32FetchSet(failure_flag, 1); } OS_ConditionVariableBroadcast(&s->res_cv); @@ -322,9 +353,8 @@ void BuildStepMsvcCompileCommand(void *arg_raw) ScratchEnd(scratch); } -/* ========================== * - * Build - * ========================== */ +//////////////////////////////// +//~ Build void OnBuild(StringList cli_args) { @@ -340,25 +370,29 @@ void OnBuild(StringList cli_args) sl->mutex = OS_MutexAlloc(); sl->tq = T_QueueAlloc(); - /* ========================== * - * Read args - * ========================== */ + + //////////////////////////////// + //~ Read args String tracy_env_var_name = Lit("TRACY_SRC_PATH"); String tracy_src_dir_path = OS_GetEnvVar(&perm, tracy_env_var_name); String tracy_client_header_path = OS_GetAbsPath(&perm, StringF(&perm, Lit("%F%F"), FmtStr(tracy_src_dir_path), FmtStr(Lit("/public/tracy/TracyC.h")))); String tracy_client_src_path = OS_GetAbsPath(&perm, StringF(&perm, Lit("%F%F"), FmtStr(tracy_src_dir_path), FmtStr(Lit("/public/TracyClient.cpp")))); { - typedef enum ArgState { + typedef I32 ArgState; enum + { ArgState_None, ArgState_OutputDir - } ArgState; + }; ArgState arg_state = ArgState_None; - for (StringListNode *n = cli_args.first; n; n = n->next) { + for (StringListNode *n = cli_args.first; n; n = n->next) + { String arg = n->string; - if (n != cli_args.first) { - switch (arg_state) { + if (n != cli_args.first) + { + switch (arg_state) + { case ArgState_OutputDir: { arg_outdir = arg; @@ -391,16 +425,20 @@ void OnBuild(StringList cli_args) String out_inc_dir_path = OS_GetAbsPath(&perm, StringF(&perm, Lit("%F/inc/"), FmtStr(arg_outdir))); String out_bin_dir_path = OS_GetAbsPath(&perm, StringF(&perm, Lit("%F/bin/"), FmtStr(arg_outdir))); - if (!OS_DirExists(out_obj_dir_path)) { + if (!OS_DirExists(out_obj_dir_path)) + { OS_CreateDirAtAbsPath(out_obj_dir_path); } - if (!OS_DirExists(out_dxc_dir_path)) { + if (!OS_DirExists(out_dxc_dir_path)) + { OS_CreateDirAtAbsPath(out_dxc_dir_path); } - if (!OS_DirExists(out_inc_dir_path)) { + if (!OS_DirExists(out_inc_dir_path)) + { OS_CreateDirAtAbsPath(out_inc_dir_path); } - if (!OS_DirExists(out_bin_dir_path)) { + if (!OS_DirExists(out_bin_dir_path)) + { OS_CreateDirAtAbsPath(out_bin_dir_path); } @@ -410,10 +448,13 @@ void OnBuild(StringList cli_args) String compiler_loc = { 0 }; { SH_CommandResult where_res = { 0 }; - if (arg_msvc) { + if (arg_msvc) + { compiler = Lit("Msvc"); where_res = RunCommand(&perm, Lit("where cl.exe")); - } else { + } + else + { compiler = Lit("Clang"); where_res = RunCommand(&perm, Lit("where clang.exe")); } @@ -428,16 +469,14 @@ void OnBuild(StringList cli_args) SH_Print(Lit("------------------------------\n\n")); } - /* ========================== * - * Constants - * ========================== */ - + //- Constants String dep_file_extension = Lit("d"); String obj_file_extension = Lit("obj"); Bool should_embed_res_dir = !arg_developer; Bool should_embed_in_rc = !!arg_msvc; D_Tag executable_file = D_TagFromPath(&perm, StringF(&perm, Lit("%F/PowerPlay.exe"), FmtStr(out_bin_dir_path)), D_TagKind_File); + D_Tag editor_include_file = D_TagFromPath(&perm, StringF(&perm, Lit("build/editor_include.h")), D_TagKind_File); D_Tag dxc_dir = D_TagFromPath(&perm, out_dxc_dir_path, D_TagKind_Dir); D_Tag res_dir = D_TagFromPath(&perm, Lit("res"), D_TagKind_Dir); D_Tag icon_file = D_TagFromPath(&perm, Lit("icon.ico"), D_TagKind_File); @@ -445,9 +484,8 @@ void OnBuild(StringList cli_args) D_Tag inc_src_file = D_TagFromPath(&perm, Lit("src/inc/inc_core.c"), D_TagKind_File); D_Tag rc_res_file = D_TagFromPath(&perm, StringF(&perm, Lit("%F/rc.res"), FmtStr(out_obj_dir_path)), D_TagKind_File); - /* ========================== * - * Determine compiler args - * ========================== */ + //////////////////////////////// + //~ Determine compiler args String dxc_args_format = { 0 }; @@ -461,13 +499,14 @@ void OnBuild(StringList cli_args) StringList rc_compile_args = { 0 }; StringList dxc_compile_args = { 0 }; { - if (arg_msvc) { - /* Msvc */ + if (arg_msvc) + { + //- Msvc StringListAppend(&perm, &c_compile_args, Lit("cl.exe /nologo /c \"%F\" /Fo\"%F\" /FS /showIncludes")); StringListAppend(&perm, &cpp_compile_args, Lit("cl.exe /nologo /std:c++20 /c \"%F\" /Fo\"%F\" /FS /showIncludes")); StringListAppend(&perm, &rc_compile_args, Lit("rc /fo\"%F\" \"%F\"")); - StringListAppend(&perm, &link_args, Lit("link.exe /nologo %F /OUT:\"%F\" /DEBUG:FULL /OPT:REF /OPT:ICF")); + StringListAppend(&perm, &link_args, Lit("link.exe /nologo %F /OUT:\"%F\" /OPT:REF /OPT:ICF")); String warnings = Lit("/WX /Wall " "/options:strict " @@ -476,8 +515,10 @@ void OnBuild(StringList cli_args) StringListAppend(&perm, &link_warnings, Lit("/WX")); StringListAppend(&perm, &compile_args, StringF(&perm, Lit("/Fd\"%F\\\""), FmtStr(out_bin_dir_path))); - } else { - /* Clang */ + } + else + { + //- Clang StringListAppend(&perm, &c_compile_args, Lit("clang -xc -std=c99 -c \"%F\" -o \"%F\" -MD")); StringListAppend(&perm, &cpp_compile_args, Lit("clang -xc++ -std=c++20 -c \"%F\" -o \"%F\" -MD")); StringListAppend(&perm, &rc_compile_args, Lit("llvm-rc /fo\"%F\" \"%F\"")); @@ -515,108 +556,144 @@ void OnBuild(StringList cli_args) StringListAppend(&perm, &link_warnings, warnings); } - /* DXC */ + //- Dxc { StringListAppend(&perm, &dxc_compile_args, Lit("-I src/ -H -WX -Ges")); String dxc_args_define = StringFromStringList(&perm, Lit(" "), dxc_compile_args); StringListAppend(&perm, &compile_args, StringF(&perm, Lit("-DDXC_ARGS=\"%F\""), FmtStr(dxc_args_define))); } - /* RTC */ - if (arg_rtc) { - if (!arg_crtlib) { + //- Rtc + if (arg_rtc) + { + if (!arg_crtlib) + { Error(Lit("CRTLIB (C runtime library) Must be enabled when compiling with RTC (runtime checks)")); OS_Exit(1); } StringListAppend(&perm, &compile_args, Lit("-DRTC=1")); - if (arg_msvc) { - if (!arg_asan) { + if (arg_msvc) + { + if (!arg_asan) + { /* Enable /RTC option (not compatible with ASAN) */ StringListAppend(&perm, &compile_args, Lit("/RTCcsu")); } - } else { + } + else + { /* Enable UBSan */ StringListAppend(&perm, &compile_and_link_args, Lit("-fsanitize=undefined -fsanitize-trap=all")); //StringListAppend(&perm, &compile_and_link_args, Lit("-fsanitize=undefined")); } } - /* CRTLIB */ - if (arg_crtlib) { + //- Crtlib + if (arg_crtlib) + { StringListAppend(&perm, &compile_args, Lit("-DCRTLIB=1")); - } else { - if (arg_msvc) { + } + else + { + if (arg_msvc) + { /* TODO */ Error(Lit("TODO\n")); OS_Exit(1); - } else { + } + else + { StringListAppend(&perm, &compile_and_link_args, Lit("-mno-stack-arg-probe -fno-builtin -nostdlib")); } } - /* Optimization */ - if (arg_unoptimized) { + //- Optimization + if (arg_unoptimized) + { StringListAppend(&perm, &compile_args, Lit("-DUNOPTIMIZED=1")); - if (arg_msvc) { + if (arg_msvc) + { StringListAppend(&perm, &compile_args, Lit("/Od")); - } else { + } + else + { StringListAppend(&perm, &compile_and_link_args, Lit("-O0")); } StringListAppend(&perm, &dxc_compile_args, Lit("-Od")); - } else { - if (arg_msvc) { + } + else + { + if (arg_msvc) + { StringListAppend(&perm, &compile_args, Lit("/O2")); StringListAppend(&perm, &link_args, Lit("/LTCG")); - } else { + } + else + { StringListAppend(&perm, &compile_and_link_args, Lit("-O3 -flto")); } StringListAppend(&perm, &dxc_compile_args, Lit("-O3")); } - /* Debug info */ - if (arg_debinfo) { + //- Debug info + if (arg_debinfo) + { StringListAppend(&perm, &compile_args, Lit("-DDEBINFO=1")); - if (arg_msvc) { + if (arg_msvc) + { StringListAppend(&perm, &compile_args, Lit("/JMC /Zi")); - } else { + StringListAppend(&perm, &link_args, Lit("/DEBUG:FULL")); + } + else + { StringListAppend(&perm, &compile_and_link_args, Lit("-g")); } StringListAppend(&perm, &dxc_compile_args, Lit("-Zi -Qembed_debug")); } - /* Address sanitizer */ - if (arg_asan) { - if (!arg_crtlib) { + //- Address sanitizer + if (arg_asan) + { + if (!arg_crtlib) + { Error(Lit("CRTLIB (C runtime library) Must be enabled when compiling with asan enabled")); OS_Exit(1); } StringListAppend(&perm, &compile_args, Lit("-DASAN=1")); - if (arg_msvc) { + if (arg_msvc) + { StringListAppend(&perm, &compile_args, Lit("/fsanitize=address")); - } else { + } + else + { StringListAppend(&perm, &compile_and_link_args, Lit("-fsanitize=address")); } } - /* Developer mode */ - if (arg_developer) { + //- Developer mode + if (arg_developer) + { StringListAppend(&perm, &compile_args, Lit("-DDEVELOPER=1")); } - /* Profiling */ - if (arg_profiling) { - if (!arg_crtlib) { + //- Profiling + if (arg_profiling) + { + if (!arg_crtlib) + { Error(Lit("CRTLIB (C runtime library) must be enabled when compiling with profiling enabled")); OS_Exit(1); } - if (arg_msvc) { + if (arg_msvc) + { Error(Lit("MSVC not supported with profiling enabled (Profiling relies on Clang attributes)")); OS_Exit(1); } StringListAppend(&perm, &compile_args, Lit("-DPROFILING=1")); /* Tracy include path */ - if (tracy_src_dir_path.len == 0 || !OS_DirExists(tracy_src_dir_path)) { + if (tracy_src_dir_path.len == 0 || !OS_DirExists(tracy_src_dir_path)) + { Error(StringF(&perm, Lit("Profiling is enabled but tracy directory \"%F\" does not exist (set by environment variable \"%F\")"), FmtStr(tracy_src_dir_path), FmtStr(tracy_env_var_name))); OS_Exit(1); } @@ -624,15 +701,16 @@ void OnBuild(StringList cli_args) StringListAppend(&perm, &compile_args, StringF(&perm, Lit("-DTRACY_CLIENT_SRC_PATH=\\\"%F\\\""), FmtStr(tracy_client_src_path))); } - if (!arg_msvc) { + //- Incbin + if (!arg_msvc) + { String incbin_dir = StringReplace(&perm, out_inc_dir_path, Lit("\\"), Lit("/")); StringListAppend(&perm, &compile_args, StringF(&perm, Lit("-DINCBIN_DIR_RAW=\"%F\""), FmtStr(incbin_dir))); } } - /* ========================== * - * Examine build hash - * ========================== */ + //////////////////////////////// + //~ Examine build hash { D_Tag build_hash_file = D_TagFromPath(&perm, build_hash_path, D_TagKind_File); @@ -648,12 +726,14 @@ void OnBuild(StringList cli_args) U64 old_build_hash = 0; { String build_hash_file_data = D_ReadAll(&perm, build_hash_file); - if (build_hash_file_data.len >= 8) { + if (build_hash_file_data.len >= 8) + { MemoryCopy((Byte *)&old_build_hash, build_hash_file_data.text, 8); } } - if (build_hash != old_build_hash) { + if (build_hash != old_build_hash) + { SH_Print(Lit("Builder exe or build args have changed, forcing complete rebuild.\n")); force_rebuild = 1; String data = StringFromStruct(&build_hash); @@ -661,17 +741,13 @@ void OnBuild(StringList cli_args) } } - /* ========================== * - * Begin build - * ========================== */ + //////////////////////////////// + //~ Build steps hist = D_HistFromPath(&perm, hist_path); D_TagList link_files = { 0 }; - /* ========================== * - * Build step: Compile shaders - * ========================== */ - + //- Build step: Compile shaders Atomic32 shader_success_flag = { 0 }; { D_TagList src_input_files = { 0 }; @@ -680,7 +756,8 @@ void OnBuild(StringList cli_args) D_TagList src_files = { 0 }; D_GetDirContents(&perm, &src_files, src_dir, 1); - for (D_TagListNode *n = src_files.first; n; n = n->next) { + for (D_TagListNode *n = src_files.first; n; n = n->next) + { D_Tag file = n->tag; String path = file.full_path; String name = D_GetName(file); @@ -688,7 +765,8 @@ void OnBuild(StringList cli_args) Bool is_dir = file.kind == D_TagKind_Dir; Bool is_rst = !is_dir && StringEqual(extension, Lit("rst")); Bool is_knl = !is_dir && StringEqual(extension, Lit("knl")); - if (is_rst || is_knl) { + if (is_rst || is_knl) + { D_TagListAppend(&perm, &src_input_files, file); } } @@ -699,7 +777,8 @@ void OnBuild(StringList cli_args) String dxc_args_bare = StringFromStringLists(&perm, Lit(" "), dxc_compile_args); String dxc_compile_args_fmt = StringF(&perm, Lit("dxc %%F -E %%F -T %%F -Fo %%F %F"), FmtStr(dxc_args_bare)); - for (D_TagListNode *n = src_input_files.first; n; n = n->next) { + for (D_TagListNode *n = src_input_files.first; n; n = n->next) + { D_Tag file = n->tag; String path = file.full_path; String name = D_GetName(file); @@ -707,27 +786,34 @@ void OnBuild(StringList cli_args) String extension = StringPathExtension(name); Bool is_rst = StringEqual(extension, Lit("rst")); Bool is_knl = !is_rst && StringEqual(extension, Lit("knl")); - for (I32 kind = 0; kind < 3; ++kind) { + for (I32 kind = 0; kind < 3; ++kind) + { String out_file_extension = { 0 }; String entry = { 0 }; String profile = { 0 }; - if (kind == 0 && is_rst) { + if (kind == 0 && is_rst) + { /* Vertex shader */ out_file_extension = Lit("vs"); entry = Lit("vs"); profile = Lit("vs_6_6"); - } else if (kind == 1 && is_rst) { + } + else if (kind == 1 && is_rst) + { /* Pixel shader */ out_file_extension = Lit("ps"); entry = Lit("ps"); profile = Lit("ps_6_6"); - } else if (kind == 2 && is_knl) { + } + else if (kind == 2 && is_knl) + { /* Compute shader */ out_file_extension = Lit("cs"); entry = Lit("cs"); profile = Lit("cs_6_6"); } - if (entry.len > 0) { + if (entry.len > 0) + { D_Tag dep_file; { String dep_file_path = StringF(&perm, Lit("%F/%F.%F"), FmtStr(out_obj_dir_path), FmtStr(name_no_extension), FmtStr(dep_file_extension)); @@ -742,7 +828,8 @@ void OnBuild(StringList cli_args) D_AddDependency(&store, dxc_file, file); D_AddDependency(&store, dxc_file, dep_file); - if (IsDirty(dxc_file)) { + if (IsDirty(dxc_file)) + { String step_name = StringF(&perm, Lit("%F -> %F"), FmtStr(name), FmtStr(D_GetName(dxc_file))); { BuildStepSimpleCommandArg *bs_arg = ArenaPush(&perm, BuildStepSimpleCommandArg); @@ -760,30 +847,33 @@ void OnBuild(StringList cli_args) } } - /* ========================== * - * Build step: Tar archives - * ========================== */ - + //- Build step: Tar archives Atomic32 tar_success_flag = { 0 }; { AddSyncPoint(); D_TagList tar_input_dirs = { 0 }; D_TagListAppend(&perm, &tar_input_dirs, dxc_dir); - if (should_embed_res_dir) { + if (should_embed_res_dir) + { D_TagListAppend(&perm, &tar_input_dirs, res_dir); } - for (D_TagListNode *n = tar_input_dirs.first; n; n = n->next) { + for (D_TagListNode *n = tar_input_dirs.first; n; n = n->next) + { D_Tag input_dir = n->tag; D_Tag tar_file = D_TagFromPath(&perm, StringF(&perm, 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) { + if (should_embed_in_rc) + { D_AddDependency(&store, rc_res_file, tar_file); - } else { + } + else + { D_AddDependency(&store, inc_src_file, tar_file); } - if (IsDirty(tar_file)) { + if (IsDirty(tar_file)) + { BuildStepSimpleCommandArg *bs_arg = ArenaPush(&perm, BuildStepSimpleCommandArg); bs_arg->cmd = StringF(&perm, Lit("cd %F && tar cvf %F ."), FmtStr(input_dir.full_path), FmtStr(tar_file.full_path)); bs_arg->failure_flag = &tar_success_flag; @@ -794,12 +884,10 @@ void OnBuild(StringList cli_args) } } - /* ========================== * - * Build step: Compile RC files - * ========================== */ - + //- Build step: Compile RC files Atomic32 rc_success_flag = { 0 }; - if (PlatformWindows) { + if (PlatformWindows) + { AddSyncPoint(); D_Tag rc_input_file = D_TagFromPath(&perm, StringF(&perm, Lit("%F/rc.rc"), FmtStr(out_inc_dir_path)), D_TagKind_File); @@ -808,14 +896,17 @@ void OnBuild(StringList cli_args) D_Tag dxc_tar_file = D_TagFromPath(&perm, StringF(&perm, Lit("%F/%F.tar"), FmtStr(out_inc_dir_path), FmtStr(D_GetName(dxc_dir))), D_TagKind_File); D_AddDependency(&store, rc_input_file, icon_file); D_AddDependency(&store, rc_input_file, dxc_tar_file); - if (should_embed_in_rc && should_embed_res_dir) { + if (should_embed_in_rc && should_embed_res_dir) + { D_AddDependency(&store, rc_input_file, res_tar_file); } - if (IsDirty(rc_input_file)) { + if (IsDirty(rc_input_file)) + { D_ClearWrite(rc_input_file, Lit("")); D_AppendWrite(rc_input_file, StringF(&perm, 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(&perm, Lit("%F %F DISCARDABLE %F\n"), FmtStr(D_GetName(dxc_tar_file)), FmtStr(Lit("RCDATA")), FmtStr(D_GetName(dxc_tar_file)))); - if (should_embed_in_rc && should_embed_res_dir) { + if (should_embed_in_rc && should_embed_res_dir) + { D_AppendWrite(rc_input_file, StringF(&perm, Lit("%F %F DISCARDABLE %F\n"), FmtStr(D_GetName(res_tar_file)), FmtStr(Lit("RCDATA")), FmtStr(D_GetName(res_tar_file)))); } } @@ -825,7 +916,8 @@ void OnBuild(StringList cli_args) String rc_compile_args_fmt = StringFromStringLists(&perm, Lit(" "), rc_compile_args); D_AddDependency(&store, rc_res_file, rc_input_file); - if (IsDirty(rc_res_file)) { + if (IsDirty(rc_res_file)) + { BuildStepSimpleCommandArg *bs_arg = ArenaPush(&perm, BuildStepSimpleCommandArg); bs_arg->cmd = StringF(&perm, rc_compile_args_fmt, FmtStr(rc_res_file.full_path), FmtStr(rc_input_file.full_path)); bs_arg->skip_flag = &tar_success_flag; @@ -838,87 +930,58 @@ void OnBuild(StringList cli_args) } } - /* ========================== * - * Build step: Compile src files - * ========================== */ - + //- Build step: Compile src files Atomic32 src_success_flag = { 0 }; { + /* src_input_files will contain .c & .cpp files with names that match their parent directory */ D_TagList src_input_files = { 0 }; + /* header_files will contain .h files with names that match their parent directory */ + D_TagList header_files = { 0 }; { - D_Tag src_dir = D_TagFromPath(&perm, Lit("src"), D_TagKind_Dir); - D_TagList src_files = { 0 }; - - D_GetDirContents(&perm, &src_files, src_dir, 0); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/base/base.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/prof/prof.cpp"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/platform/platform.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/gp/gp.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/resource/resource.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/watch/watch.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/tar/tar.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/ase/ase.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/mp3/mp3.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/json/json.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/ttf/ttf.cpp"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/dxc/dxc.cpp"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/sprite/sprite.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/font/font.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/sound/sound.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/draw/draw.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/inc/inc.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/net/net.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/asset_cache/asset_cache.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/mixer/mixer.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/settings/settings.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/collider/collider.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/app/app.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/playback/playback.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/sim/sim.c"), D_TagKind_File)); - D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/user/user.c"), D_TagKind_File)); - - for (D_TagListNode *n = src_files.first; n; n = n->next) { - Bool ignore = 1; - - D_Tag file = n->tag; - String path = file.full_path; - String name = D_GetName(file); - String extension = StringPathExtension(name); - Bool is_dir = file.kind == D_TagKind_Dir; - Bool is_c = !is_dir && StringEqual(extension, Lit("c")); - Bool is_cpp = !is_dir && !is_c && StringEqual(extension, Lit("cpp")); - if (is_c || is_cpp) { - if (StringBeginsWith(name, Lit("sys_")) || - StringBeginsWith(name, Lit("gp_")) || - StringBeginsWith(name, Lit("playback_")) || - StringBeginsWith(name, Lit("mp3_")) || - StringBeginsWith(name, Lit("ttf_")) || - StringBeginsWith(name, Lit("dxc"))) { - if (PlatformWindows) { - ignore = !(StringEqual(name, Lit("sys_win32.c")) || - StringEqual(name, Lit("gp_dx12.c")) || - StringEqual(name, Lit("playback_win32.c")) || - StringEqual(name, Lit("mp3_mmf.c")) || - StringEqual(name, Lit("ttf_dwrite.cpp")) || - StringEqual(name, Lit("dxc.cpp"))); + D_Tag top_level_dir = D_TagFromPath(&perm, Lit("src"), D_TagKind_Dir); + D_TagList top_level_files = { 0 }; + D_GetDirContents(&perm, &top_level_files, top_level_dir, 0); + for (D_TagListNode *top_level_node = top_level_files.first; top_level_node; top_level_node = top_level_node->next) + { + D_Tag top_level_item = top_level_node->tag; + String top_level_item_name = D_GetName(top_level_item); + if (top_level_item.kind == D_TagKind_Dir) + { + D_TagList sub_files = { 0 }; + D_GetDirContents(&perm, &sub_files, top_level_item, 0); + for (D_TagListNode *n = sub_files.first; n; n = n->next) + { + D_Tag file = n->tag; + String name = D_GetName(file); + String extension = StringPathExtension(name); + String name_no_extension = StringPathNoExtension(name); + if (StringEqual(name_no_extension, top_level_item_name)) + { + Bool is_c = StringEqual(extension, Lit("c")); + Bool is_cpp = !is_c && StringEqual(extension, Lit("cpp")); + Bool is_h = !is_c && !is_cpp && StringEqual(extension, Lit("h")); + if (is_c || is_cpp) + { + D_TagListAppend(&perm, &src_input_files, file); + } + else if (is_h) + { + D_TagListAppend(&perm, &header_files, file); + } } - } else { - ignore = 0; } } - - if (!ignore) { - D_TagListAppend(&perm, &src_input_files, file); - } } } + /* Build src files */ { AddSyncPoint(); String c_compile_args_fmt = StringFromStringLists(&perm, Lit(" "), c_compile_args, compile_warnings, compile_and_link_args, compile_args); String cpp_compile_args_fmt = StringFromStringLists(&perm, Lit(" "), cpp_compile_args, compile_warnings, compile_and_link_args, compile_args); - for (D_TagListNode *n = src_input_files.first; n; n = n->next) { + for (D_TagListNode *n = src_input_files.first; n; n = n->next) + { D_Tag file = n->tag; String path = file.full_path; String name = D_GetName(file); @@ -942,11 +1005,13 @@ void OnBuild(StringList cli_args) D_AddDependency(&store, obj_file, file); D_AddDependency(&store, obj_file, dep_file); - if (IsDirty(obj_file)) { + if (IsDirty(obj_file)) + { String comp_cmd_fmt = is_c ? c_compile_args_fmt : cpp_compile_args_fmt; String step_name = StringF(&perm, Lit("%F -> %F"), FmtStr(name), FmtStr(D_GetName(obj_file))); D_TagList depfile_force_includes = { 0 }; - if (arg_msvc) { + if (arg_msvc) + { BuildStepMsvcCompileCommandArg *bs_arg = ArenaPush(&perm, BuildStepMsvcCompileCommandArg); bs_arg->cmd = StringF(&perm, comp_cmd_fmt, FmtStr(file.full_path), FmtStr(obj_file.full_path)); bs_arg->depfile_dependent = obj_file; @@ -956,7 +1021,9 @@ void OnBuild(StringList cli_args) bs_arg->failure_flag = &src_success_flag; bs_arg->delete_file_on_failure = obj_file; AddStep(step_name, &BuildStepMsvcCompileCommand, bs_arg); - } else { + } + else + { BuildStepSimpleCommandArg *bs_arg = ArenaPush(&perm, BuildStepSimpleCommandArg); bs_arg->cmd = StringF(&perm, comp_cmd_fmt, FmtStr(file.full_path), FmtStr(obj_file.full_path)); bs_arg->skip_flag = &rc_success_flag; @@ -968,19 +1035,32 @@ void OnBuild(StringList cli_args) D_TagListAppend(&perm, &link_files, obj_file); } } + + /* Generate include file to assist editor parsing */ + { + StringList file_contents = { 0 }; + StringListAppend(&perm, &file_contents, Lit("// This is an auto generated file containing all includes necessary to assist in editor parsing\n")); + for (D_TagListNode *n = header_files.first; n; n = n->next) + { + D_Tag tag = n->tag; + String include_path = tag.full_path; + String line = StringF(&perm, Lit("#include \"%F\""), FmtStr(include_path)); + StringListAppend(&perm, &file_contents, line); + } + String file_contents_str = StringFromStringList(&perm, Lit("\n"), file_contents); + D_ClearWrite(editor_include_file, file_contents_str); + } } - /* ========================== * - * Build step: Link - * ========================== */ - + //- Build step: Link { AddSyncPoint(); String link_files_str = { 0 }; { StringList link_files_quoted_list = { 0 }; - for (D_TagListNode *n = link_files.first; n; n = n->next) { + for (D_TagListNode *n = link_files.first; n; n = n->next) + { D_Tag file = n->tag; String path = StringF(&perm, Lit("\"%F\""), FmtStr(file.full_path)); StringListAppend(&perm, &link_files_quoted_list, path); @@ -988,7 +1068,8 @@ void OnBuild(StringList cli_args) } link_files_str = StringFromStringList(&perm, Lit(" "), link_files_quoted_list); } - if (link_files_str.len > 0 && IsDirty(executable_file)) { + if (link_files_str.len > 0 && IsDirty(executable_file)) + { String link_args_fmt = StringFromStringLists(&perm, Lit(" "), link_args, link_warnings, compile_and_link_args); BuildStepSimpleCommandArg *bs_arg = ArenaPush(&perm, BuildStepSimpleCommandArg); bs_arg->cmd = StringF(&perm, link_args_fmt, FmtStr(link_files_str), FmtStr(executable_file.full_path)); @@ -998,53 +1079,62 @@ void OnBuild(StringList cli_args) } } - /* ========================== * - * Execute build steps - * ========================== */ + //////////////////////////////// + //~ Execute build steps Bool success = 1; I64 step_count = sl->count; - if (step_count > 0) { + if (step_count > 0) + { KillRunningProcesses(); ExecuteSteps(); Step *s = sl->first; I64 step_i = 0; - while (s) { + while (s) + { ++step_i; { OS_Lock lock = OS_MutexLockS(&s->res_mutex); - while (s->res_status == StepStatus_None) { + while (s->res_status == StepStatus_None) + { OS_ConditionVariableWait(&s->res_cv, &lock); } OS_MutexUnlock(&lock); } String output = s->res_output; - if (s->res_status == StepStatus_Success) { + if (s->res_status == StepStatus_Success) + { SH_PrintF(Lit("[%F/%F] %F\n"), FmtI64(step_i), FmtI64(step_count), FmtStr(s->name)); - } else if (s->res_status == StepStatus_Failure) { + } + else if (s->res_status == StepStatus_Failure) + { success = 0; SH_PrintF(Lit("[%F/%F] %F\n\n%F\n\n"), FmtI64(step_i), FmtI64(step_count), FmtStr(s->name), FmtStr(output)); } s = s->next; - skip_cont: + skip_cont: continue; } - } else { + } + else + { SH_Print(Lit("No work to do\n")); } - if (!D_Exists(executable_file)) { + if (!D_Exists(executable_file)) + { /* Create blank executible if build fails (since Visual Studio can get * confused if no build target exists) */ D_ClearWrite(executable_file, Lit("")); } #if 0 - if (!success) { + if (!success) + { Error(Lit("Build failed\n")); } #endif