re-build all if dirty

This commit is contained in:
jacob 2024-05-28 19:21:33 -05:00
parent d6d89b9625
commit fea045ac54

343
build.c
View File

@ -1,6 +1,13 @@
#define Rtc 1
#include "buildit.h"
/* ========================== *
* Globals
* ========================== */
D_Hist hist = { 0 };
Bool force_rebuild = false;
/* ========================== *
* Util
* ========================== */
@ -10,6 +17,11 @@ void Error(String msg)
SH_PrintF(Lit("ERROR: %F\n"), FmtStr(msg));
}
Bool IsDirty(D_Tag tag)
{
return force_rebuild ? true : D_IsDirty(tag, &hist);
}
/* ========================== *
* Step
* ========================== */
@ -128,6 +140,7 @@ 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)));
@ -273,7 +286,7 @@ void OnBuild(StringList cli_args)
} else {
/* Enable UBSan */
StringListAppend(&arena, &compile_and_link_args, Lit("-fsanitize=undefined -fsanitize-trap=all"));
//StringListAppend(&compile_and_link_args, "-fsanitize=undefined");
//StringListAppend(&arena, &compile_and_link_args, Lit("-fsanitize=undefined"));
}
}
@ -363,128 +376,125 @@ void OnBuild(StringList cli_args)
}
/* ========================== *
* Read hist file
* Generate root dependencies
* ========================== */
D_Hist hist = D_HistFromPath(&arena, hist_path);
/* ========================== *
* Assemble input files
* ========================== */
D_TagList tar_input_dirs = { 0 };
D_Tag rc_input_file = D_TagFromPath(&arena, StringF(&arena, Lit("%F/rc.rc"), FmtStr(out_inc_dir_path)), D_TagKind_File);
D_Tag pch_header_file = D_TagFromPath(&arena, Lit("src/common.h"), D_TagKind_File);
D_TagList src_input_files = { 0 };
/* Append tar input dirs */
D_TagListAppend(&arena, &tar_input_dirs, shaders_dir);
if (should_embed_res_dir) {
D_TagListAppend(&arena, &tar_input_dirs, res_dir);
}
/* Generate & append rc input file */
if (PlatformWindows) {
D_AddDependency(rc_input_file, icon_file);
/* TODO: Depend on tar files rather than dir (more correct) */
if (should_embed_in_rc) {
D_AddDependency(rc_input_file, shaders_dir);
if (should_embed_res_dir) {
D_AddDependency(rc_input_file, res_dir);
}
}
if (D_IsDirty(rc_input_file, &hist)) {
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_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))));
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))));
if (should_embed_res_dir) {
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_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))));
}
}
}
}
/* Append 'src' dir c & cpp files */
{
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;
D_Tag build_hash_file = D_TagFromPath(&arena, build_hash_path, D_TagKind_File);
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("renderer_")) ||
StringBeginsWith(name, Lit("playback_")) ||
StringBeginsWith(name, Lit("mp3_")) ||
StringBeginsWith(name, Lit("ttf_"))) {
if (PlatformWindows) {
ignore = !(StringEqual(name, Lit("sys_win32.c")) ||
StringEqual(name, Lit("renderer_d3d11.c")) ||
StringEqual(name, Lit("playback_wasapi.c")) ||
StringEqual(name, Lit("mp3_mmf.c")) ||
StringEqual(name, Lit("ttf_dwrite.cpp")));
}
} else {
ignore = false;
}
}
U64 build_hash = D_HashString64Basis;
{
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);
}
if (!ignore) {
D_TagListAppend(&arena, &src_input_files, file);
U64 old_build_hash = 0;
{
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);
}
}
if (build_hash != old_build_hash) {
SH_Print(Lit("Builder exe or build args have changed, rebuilding all.\n"));
force_rebuild = true;
String data = StringFromStruct(&build_hash);
D_ClearWrite(build_hash_file, data);
}
}
/* ========================== *
* Assemble build steps
* Build
* ========================== */
hist = D_HistFromPath(&arena, hist_path);
StepList build_steps = { 0 };
D_TagList link_files = { 0 };
/* Build tar files */
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);
if (should_embed_in_rc) {
D_AddDependency(rc_res_file, tar_file);
} else {
D_AddDependency(inc_src_file, tar_file);
}
if (D_IsDirty(tar_file, &hist)) {
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(&arena, &build_steps, step_name, cmd, true);
}
}
/* ========================== *
* Build step: Tar archives
* ========================== */
/* Build rc file */
if (PlatformWindows) {
String rc_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), rc_compile_args);
D_AddDependency(rc_res_file, rc_input_file);
if (D_IsDirty(rc_res_file, &hist)) {
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(&arena, &build_steps, step_name, cmd, true);
}
D_TagListAppend(&arena, &link_files, rc_res_file);
}
/* Build pch */
{
D_TagList tar_input_dirs = { 0 };
{
D_TagListAppend(&arena, &tar_input_dirs, shaders_dir);
if (should_embed_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);
if (should_embed_in_rc) {
D_AddDependency(rc_res_file, tar_file);
} else {
D_AddDependency(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(&arena, &build_steps, step_name, cmd, true);
}
}
}
/* ========================== *
* Build step: Compile RC files
* ========================== */
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 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);
if (should_embed_in_rc) {
D_AddDependency(rc_input_file, shaders_tar_file);
if (should_embed_res_dir) {
D_AddDependency(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))));
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))));
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))));
}
}
}
}
{
String rc_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), rc_compile_args);
D_AddDependency(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(&arena, &build_steps, step_name, cmd, true);
}
D_TagListAppend(&arena, &link_files, rc_res_file);
}
}
/* ========================== *
* Build step: Compile pch files
* ========================== */
{
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);
@ -520,7 +530,7 @@ void OnBuild(StringList cli_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);
if (D_IsDirty(pch_c_file, &hist)) {
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)));
@ -530,7 +540,7 @@ void OnBuild(StringList cli_args)
/* 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);
if (D_IsDirty(pch_cpp_file, &hist)) {
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)));
@ -544,14 +554,14 @@ void OnBuild(StringList cli_args)
String pch_cpp_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), pch_cpp_compile_args, compile_warnings, compile_and_link_args, compile_args);
/* C */
if (D_IsDirty(pch_c_file, &hist)) {
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(&arena, &build_steps, step_name, comp_cmd, true);
}
/* Cpp */
if (D_IsDirty(pch_cpp_file, &hist)) {
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(&arena, &build_steps, step_name, comp_cmd, true);
@ -559,46 +569,93 @@ void OnBuild(StringList cli_args)
}
}
/* Build src files */
/* ========================== *
* Build step: Compile src files
* ========================== */
{
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;
String name = D_GetName(file);
String extension = StringPathExtension(name);
Bool is_c = StringEqual(extension, Lit("c"));
Bool is_cpp = !is_c && StringEqual(extension, Lit("cpp"));
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);
for (D_TagListNode *n = src_dir_files.first; n; n = n->next) {
Bool ignore = true;
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);
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("renderer_")) ||
StringBeginsWith(name, Lit("playback_")) ||
StringBeginsWith(name, Lit("mp3_")) ||
StringBeginsWith(name, Lit("ttf_"))) {
if (PlatformWindows) {
ignore = !(StringEqual(name, Lit("sys_win32.c")) ||
StringEqual(name, Lit("renderer_d3d11.c")) ||
StringEqual(name, Lit("playback_wasapi.c")) ||
StringEqual(name, Lit("mp3_mmf.c")) ||
StringEqual(name, Lit("ttf_dwrite.cpp")));
}
} else {
ignore = false;
}
}
if (!ignore) {
D_TagListAppend(&arena, &src_input_files, file);
}
}
}
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 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;
String name = D_GetName(file);
String extension = StringPathExtension(name);
Bool is_c = StringEqual(extension, Lit("c"));
Bool is_cpp = !is_c && StringEqual(extension, Lit("cpp"));
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);
}
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);
}
D_AddDependency(obj_file, file);
D_AddDependency(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(&arena, &build_steps, step_name, comp_cmd, true);
}
D_TagListAppend(&arena, &link_files, obj_file);
}
D_AddDependency(obj_file, file);
D_AddDependency(obj_file, dep_file);
if (D_IsDirty(obj_file, &hist)) {
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(&arena, &build_steps, step_name, comp_cmd, true);
}
D_TagListAppend(&arena, &link_files, obj_file);
}
}
/* Link */
/* ========================== *
* Build step: Link
* ========================== */
{
String link_files_str = { 0 };
{
@ -626,7 +683,7 @@ void OnBuild(StringList cli_args)
{
Bool success = true;
if (D_IsDirty(executable_file, &hist)) {
if (IsDirty(executable_file)) {
Size step_i = 0;
Size step_count = build_steps.count;
for (StepListNode *n = build_steps.first; n; n = n->next) {