refactor build to support depfiles

This commit is contained in:
jacob 2024-05-24 20:04:32 -05:00
parent 3e9ac3e99c
commit 9131431144

528
build.c
View File

@ -18,8 +18,7 @@ typedef struct StepListNode StepListNode;
struct StepListNode { struct StepListNode {
String name; String name;
String cmd; String cmd;
String link_file_path; Bool silence_if_success;
Bool silence_output_if_success;
StepListNode *next; StepListNode *next;
StepListNode *prev; StepListNode *prev;
}; };
@ -31,13 +30,12 @@ struct StepList {
Size count; Size count;
}; };
void StepListAppend(Arena *arena, StepList *l, String name, String cmd, String link_file_path, Bool silence_output_if_success) void StepListAppend(Arena *arena, StepList *l, String name, String cmd, Bool silence_if_success)
{ {
StepListNode *n = ArenaPush(arena, StepListNode); StepListNode *n = ArenaPush(arena, StepListNode);
n->name = name; n->name = name;
n->cmd = cmd; n->cmd = cmd;
n->link_file_path = link_file_path; n->silence_if_success = silence_if_success;
n->silence_output_if_success = silence_output_if_success;
DllPushBack(l->first, l->last, n); DllPushBack(l->first, l->last, n);
++l->count; ++l->count;
} }
@ -163,78 +161,67 @@ void OnBuild(StringList cli_args)
SH_PrintF(Lit("Building to \"%F\"\n"), FmtStr(out_bin_dir_path)); SH_PrintF(Lit("Building to \"%F\"\n"), FmtStr(out_bin_dir_path));
SH_Print(Lit("------------------------------\n\n")); SH_Print(Lit("------------------------------\n\n"));
/* ========================== *
* Load hist file
* ========================== */
D_Hist hist = D_HistFromPath(&arena, hist_path);
/* ========================== * /* ========================== *
* Constants * Constants
* ========================== */ * ========================== */
StepList compile_command_list = { 0 }; String dep_file_extension = Lit("d");
String obj_file_extension = Lit("obj"); String obj_file_extension = Lit("obj");
D_Tag executable = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/PowerPlay.exe"), FmtStr(out_bin_dir_path))); Bool should_embed_res_dir = !arg_developer;
D_Tag pdb = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/PowerPlay.pdb"), FmtStr(out_bin_dir_path))); Bool should_embed_in_rc = !!arg_msvc;
/* Pch tags */ D_Tag executable_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/PowerPlay.exe"), FmtStr(out_bin_dir_path)));
D_Tag pch_header = D_FileTagFromPath(&arena, Lit("src/common.h")); D_Tag res_dir = D_DirTagFromPath(&arena, Lit("res"));
D_Tag pch_c_src_gen_output = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.c"), FmtStr(out_obj_dir_path))); D_Tag shaders_dir = D_DirTagFromPath(&arena, Lit("src/shaders"));
D_Tag pch_c_src_gen_obj_output = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.c.obj"), FmtStr(out_obj_dir_path))); D_Tag icon_file = D_FileTagFromPath(&arena, Lit("icon.ico"));
D_Tag pch_c_output = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.c.pch"), FmtStr(out_obj_dir_path)));
D_Tag pch_cpp_output = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.cpp.pch"), FmtStr(out_obj_dir_path))); D_Tag inc_src_file = D_FileTagFromPath(&arena, Lit("src/inc.c"));
D_Tag pch_cpp_src_gen_output = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.cpp"), FmtStr(out_obj_dir_path))); D_Tag rc_res_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/rc.res"), FmtStr(out_obj_dir_path)));
D_Tag pch_cpp_src_gen_obj_output = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.cpp.obj"), FmtStr(out_obj_dir_path)));
/* Dependency order: common.h -> common.c (generated for msvc) -> common.c.obj -> common.c.pch -> PowerPlay.exe */ #if 0
D_AddDependency(pch_c_src_gen_output, pch_header); D_Tag pch_header_file = D_FileTagFromPath(&arena, Lit("src/common.h"));
D_AddDependency(pch_c_src_gen_obj_output, pch_c_src_gen_output); D_Tag pch_c_src_gen_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.c"), FmtStr(out_obj_dir_path)));
D_AddDependency(pch_c_output, pch_c_src_gen_obj_output); D_Tag pch_cpp_src_gen_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.cpp"), FmtStr(out_obj_dir_path)));
D_AddDependency(executable, pch_c_output); D_Tag pch_c_src_gen_obj_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.c.obj"), FmtStr(out_obj_dir_path)));
/* Dependency order: common.h -> common.cpp (generated for msvc) -> common.cpp.obj -> common.cpp.pch -> PowerPlay.exe*/ D_Tag pch_cpp_src_gen_obj_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.cpp.obj"), FmtStr(out_obj_dir_path)));
D_AddDependency(pch_cpp_src_gen_output, pch_header); D_Tag pch_c_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.c.pch"), FmtStr(out_obj_dir_path)));
D_AddDependency(pch_cpp_src_gen_obj_output, pch_cpp_src_gen_output); D_Tag pch_cpp_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/common.cpp.pch"), FmtStr(out_obj_dir_path)));
D_AddDependency(pch_cpp_output, pch_cpp_src_gen_obj_output); #endif
D_AddDependency(executable, pch_cpp_output);
/* ========================== * /* ========================== *
* Determine compiler args * Determine compiler args
* ========================== */ * ========================== */
String final_c_compile_args_fmt = { 0 };
String final_cpp_compile_args_fmt = { 0 };
String final_pch_c_compile_args_fmt = { 0 };
String final_pch_cpp_compile_args_fmt = { 0 };
String final_link_args_fmt = { 0 };
{
StringList compile_warnings = { 0 };
StringList compile_and_link_args = { 0 };
StringList compile_args = { 0 };
StringList c_compile_args = { 0 }; StringList c_compile_args = { 0 };
StringList cpp_compile_args = { 0 }; StringList cpp_compile_args = { 0 };
StringList pch_c_compile_args = { 0 }; StringList pch_c_compile_args = { 0 };
StringList pch_cpp_compile_args = { 0 }; StringList pch_cpp_compile_args = { 0 };
StringList compile_and_link_args = { 0 };
StringList compile_args = { 0 };
StringList compile_warnings = { 0 };
StringList link_warnings = { 0 }; StringList link_warnings = { 0 };
StringList link_args = { 0 }; StringList link_args = { 0 };
StringList rc_compile_args = { 0 };
{
if (arg_msvc) { if (arg_msvc) {
/* Msvc */ /* Msvc */
StringListAppend(&arena, &c_compile_args, Lit("cl.exe /nologo /c \"%F\" /Fo\"%F\"")); 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, &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_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, &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, StringF(&arena, Lit("/Yu\"%F\" /FI\"%F\" /Fp\"%F\""), FmtStr(pch_header.full_path), FmtStr(pch_header.full_path), FmtStr(pch_c_output.full_path))); #if 0
StringListAppend(&arena, &cpp_compile_args, StringF(&arena, Lit("/Yu\"%F\" /FI\"%F\" /Fp\"%F\""), FmtStr(pch_header.full_path), FmtStr(pch_header.full_path), FmtStr(pch_cpp_output.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, &pch_c_compile_args, StringF(&arena, Lit("/FI\"%F\" /Fp\"%F\" /Fo\"%F\""), FmtStr(pch_header.full_path), FmtStr(pch_c_output.full_path), FmtStr(pch_c_src_gen_obj_output.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_cpp_compile_args, StringF(&arena, Lit("/FI\"%F\" /Fp\"%F\" /Fo\"%F\""), FmtStr(pch_header.full_path), FmtStr(pch_cpp_output.full_path), FmtStr(pch_cpp_src_gen_obj_output.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)));
#endif
StringListAppend(&arena, &link_args, Lit("link.exe /nologo %F")); StringListAppend(&arena, &link_args, Lit("link.exe /nologo %F /OUT:\"%F\" /DEBUG:FULL /OPT:REF /OPT:ICF"));
StringListAppend(&arena, &link_args, StringF(&arena, Lit("/OUT:\"%F\" /PDB:\"%F\" /DEBUG:FULL /OPT:REF /OPT:ICF"), FmtStr(executable.full_path), FmtStr(pdb.full_path)));
String warnings = Lit("/WX /Wall " String warnings = Lit("/WX /Wall "
"/options:strict " "/options:strict "
@ -245,16 +232,20 @@ void OnBuild(StringList cli_args)
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 { } else {
/* Clang */ /* Clang */
StringListAppend(&arena, &c_compile_args, Lit("clang -xc -std=c99 -c %F -o %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")); 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")); 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")); 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\""));
#if 0
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)));
#endif
StringListAppend(&arena, &c_compile_args, StringF(&arena, Lit("-include-pch %F"), FmtStr(pch_c_output.full_path)));
StringListAppend(&arena, &cpp_compile_args, StringF(&arena, Lit("-include-pch %F"), FmtStr(pch_cpp_output.full_path)));
StringListAppend(&arena, &link_args, Lit("clang %F")); StringListAppend(&arena, &link_args, Lit("clang %F"));
StringListAppend(&arena, &link_args, StringF(&arena, Lit("-o \"%F\""), FmtStr(executable.full_path))); StringListAppend(&arena, &link_args, StringF(&arena, Lit("-o \"%F\""), FmtStr(executable_file.full_path)));
StringListAppend(&arena, StringListAppend(&arena,
&compile_and_link_args, &compile_and_link_args,
@ -391,168 +382,78 @@ void OnBuild(StringList cli_args)
StringListAppend(&arena, &compile_args, StringF(&arena, Lit("-DINCBIN_DIR_RAW=\"%F\""), FmtStr(incbin_dir))); StringListAppend(&arena, &compile_args, StringF(&arena, Lit("-DINCBIN_DIR_RAW=\"%F\""), FmtStr(incbin_dir)));
} }
#if 0
final_c_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), c_compile_args, compile_warnings, compile_and_link_args, compile_args); final_c_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), c_compile_args, compile_warnings, compile_and_link_args, compile_args);
final_cpp_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), cpp_compile_args, compile_warnings, compile_and_link_args, compile_args); final_cpp_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), cpp_compile_args, compile_warnings, compile_and_link_args, compile_args);
final_pch_c_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), pch_c_compile_args, compile_warnings, compile_and_link_args, compile_args); final_pch_c_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), pch_c_compile_args, compile_warnings, compile_and_link_args, compile_args);
final_pch_cpp_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), pch_cpp_compile_args, compile_warnings, compile_and_link_args, compile_args); final_pch_cpp_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), pch_cpp_compile_args, compile_warnings, compile_and_link_args, compile_args);
final_rc_compile_args_fmt = StringFromStringLists(&arena, Lit(" "), rc_compile_args);
final_link_args_fmt = StringFromStringLists(&arena, Lit(" "), link_args, link_warnings, compile_and_link_args); final_link_args_fmt = StringFromStringLists(&arena, Lit(" "), link_args, link_warnings, compile_and_link_args);
#endif
} }
/* ========================== * /* ========================== *
* Generate embeddable tar files * Read hist file
* ========================== */ * ========================== */
Bool embed_in_rc = !!arg_msvc; D_Hist hist = D_HistFromPath(&arena, hist_path);
D_Tag res_dir = D_DirTagFromPath(&arena, Lit("res"));
D_Tag shaders_dir = D_DirTagFromPath(&arena, Lit("src/shaders"));
D_Tag inc_file = D_FileTagFromPath(&arena, Lit("src/inc.c"));
RcIncludeList rc_includes = { 0 };
/* Generate shaders tar */
D_Tag shaders_tar = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/shaders.tar"), FmtStr(out_inc_dir_path)));
D_AddDependency(shaders_tar, shaders_dir);
if (embed_in_rc) {
RcIncludeListAppend(&arena, &rc_includes, shaders_tar, Lit("RCDATA"));
} else {
D_AddDependency(inc_file, shaders_tar);
}
if (D_IsDirty(shaders_tar, &hist)) {
String tar_cmd = StringF(&arena, Lit("cd %F && tar cvf %F ."), FmtStr(shaders_dir.full_path), FmtStr(shaders_tar.full_path));
String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(shaders_dir)), FmtStr(D_GetName(shaders_tar)));
StepListAppend(&arena, &compile_command_list, step_name, tar_cmd, (String) { 0 }, true);
}
/* Generate res tar */
if (!arg_developer) {
D_Tag res_tar = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/res.tar"), FmtStr(out_inc_dir_path)));
D_AddDependency(res_tar, res_dir);
if (embed_in_rc) {
RcIncludeListAppend(&arena, &rc_includes, res_tar, Lit("RCDATA"));
} else {
D_AddDependency(inc_file, res_tar);
}
if (D_IsDirty(res_tar, &hist)) {
String tar_cmd = StringF(&arena, Lit("cd %F && tar cvf %F ."), FmtStr(res_dir.full_path), FmtStr(res_tar.full_path));
String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(res_dir)), FmtStr(D_GetName(res_tar)));
StepListAppend(&arena, &compile_command_list, step_name, tar_cmd, (String) { 0 }, true);
}
}
/* ========================== * /* ========================== *
* RC file (windows) * Assemble input files
* ========================== */ * ========================== */
D_TagList tar_input_dirs = { 0 };
D_Tag rc_input_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/rc.rc"), FmtStr(out_inc_dir_path)));;
D_Tag pch_header_file = D_FileTagFromPath(&arena, Lit("src/common.h"));
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) { if (PlatformWindows) {
D_Tag rc_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/rc.rc"), FmtStr(out_inc_dir_path)));; D_AddDependency(rc_input_file, icon_file);
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_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_dir)), FmtStr(Lit("RCDATA")), FmtStr(D_GetName(shaders_dir))));
if (should_embed_res_dir) {
D_AppendWrite(rc_input_file, StringF(&arena, Lit("%F %F DISCARDABLE %F\n"), FmtStr(D_GetName(res_dir)), FmtStr(Lit("RCDATA")), FmtStr(D_GetName(res_dir))));
}
}
}
}
/* Add icon file to rc list */ /* Append 'src' dir c & cpp files */
{ {
D_Tag icon_file = D_FileTagFromPath(&arena, Lit("icon.ico"));
RcIncludeListAppend(&arena, &rc_includes, icon_file, Lit("ICON"));
}
/* Add rc dependencies */
for (RcIncludeListNode *rin = rc_includes.first; rin; rin = rin->next) {
D_AddDependency(rc_file, rin->tag);
}
D_Tag rc_res_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/rc.res"), FmtStr(out_obj_dir_path)));
D_AddDependency(rc_res_file, rc_file);
D_AddDependency(executable, rc_res_file);
if (D_IsDirty(rc_res_file, &hist)) {
/* Generate rc file */
D_ClearWrite(rc_file, Lit(""));
for (RcIncludeListNode *rin = rc_includes.first; rin; rin = rin->next) {
String name = D_GetName(rin->tag);
String line = StringF(&arena, Lit("%F %F DISCARDABLE %F\n"), FmtStr(name), FmtStr(rin->rc_type), FmtStr(name));
D_AppendWrite(rc_file, line);
}
/* Append rc -> res compile command */
String rc_compile_cmd = { 0 };
if (arg_msvc) {
rc_compile_cmd = StringF(&arena, Lit("rc /fo\"%F\" \"%F\""), FmtStr(rc_res_file.full_path), FmtStr(rc_file.full_path));
} else {
rc_compile_cmd = StringF(&arena, Lit("llvm-rc /fo\"%F\" \"%F\""), FmtStr(rc_res_file.full_path), FmtStr(rc_file.full_path));
}
String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(rc_file)), FmtStr(D_GetName(rc_res_file)));
StepListAppend(&arena, &compile_command_list, step_name, rc_compile_cmd, rc_res_file.full_path, true);
}
}
/* ========================== *
* PCH compile commands
* ========================== */
if (arg_msvc) {
{
if (D_IsDirty(pch_c_output, &hist)) {
D_ClearWrite(pch_c_src_gen_output, Lit(""));
String comp_cmd = StringF(&arena, final_pch_c_compile_args_fmt, FmtStr(pch_header.full_path), FmtStr(pch_c_src_gen_output.full_path));
String link_file = pch_c_src_gen_obj_output.full_path;
String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header)), FmtStr(D_GetName(pch_c_output)));
StepListAppend(&arena, &compile_command_list, step_name, comp_cmd, link_file, true);
}
}
{
if (D_IsDirty(pch_cpp_src_gen_output, &hist)) {
D_ClearWrite(pch_cpp_src_gen_output, Lit(""));
String comp_cmd = StringF(&arena, final_pch_cpp_compile_args_fmt, FmtStr(pch_header.full_path), FmtStr(pch_cpp_src_gen_output.full_path));
String link_file = pch_cpp_src_gen_obj_output.full_path;
String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header)), FmtStr(D_GetName(pch_cpp_src_gen_output)));
StepListAppend(&arena, &compile_command_list, step_name, comp_cmd, link_file, true);
}
}
} else {
{
if (D_IsDirty(pch_c_output, &hist)) {
String comp_cmd = StringF(&arena, final_pch_c_compile_args_fmt, FmtStr(pch_header.full_path), FmtStr(pch_c_output.full_path));
String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header)), FmtStr(D_GetName(pch_c_output)));
StepListAppend(&arena, &compile_command_list, step_name, comp_cmd, (String) { 0 }, true);
}
}
{
if (D_IsDirty(pch_cpp_output, &hist)) {
String comp_cmd = StringF(&arena, final_pch_cpp_compile_args_fmt, FmtStr(pch_header.full_path), FmtStr(pch_cpp_output.full_path));
String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(D_GetName(pch_header)), FmtStr(D_GetName(pch_cpp_output)));
StepListAppend(&arena, &compile_command_list, step_name, comp_cmd, (String) { 0 }, true);
}
}
}
/* ========================== *
* Add src file compile commands
* ========================== */
D_Tag src_dir = D_DirTagFromPath(&arena, Lit("src")); D_Tag src_dir = D_DirTagFromPath(&arena, Lit("src"));
D_TagList src_files = D_GetDirContents(&arena, src_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;
for (D_TagListNode *n = src_files.first; n; n = n->next) {
D_Tag file = n->tag; D_Tag file = n->tag;
String path = file.full_path;
Bool ignore = !!file.is_dir;
if (ignore) continue;
String name = D_GetName(file); String name = D_GetName(file);
String extension = D_GetExtension(file); String extension = StringPathExtension(name);
Bool is_c = StringEqual(extension, Lit("c")); Bool is_dir = file.is_dir;
Bool is_cpp = !is_c && StringEqual(extension, Lit("cpp")); Bool is_c = !is_dir && StringEqual(extension, Lit("c"));
Bool is_cpp = !is_dir && !is_c && StringEqual(extension, Lit("cpp"));
ignore = !(is_c || is_cpp); if (is_c || is_cpp) {
if (ignore) continue;
/* Determine platform specific source files */
{
if (StringBeginsWith(name, Lit("sys_")) || if (StringBeginsWith(name, Lit("sys_")) ||
StringBeginsWith(name, Lit("renderer_")) || StringBeginsWith(name, Lit("renderer_")) ||
StringBeginsWith(name, Lit("playback_")) || StringBeginsWith(name, Lit("playback_")) ||
StringBeginsWith(name, Lit("mp3_")) || StringBeginsWith(name, Lit("mp3_")) ||
StringBeginsWith(name, Lit("ttf_"))) { StringBeginsWith(name, Lit("ttf_"))) {
ignore = true;
if (PlatformWindows) { if (PlatformWindows) {
ignore = !(StringEqual(name, Lit("sys_win32.c")) || ignore = !(StringEqual(name, Lit("sys_win32.c")) ||
StringEqual(name, Lit("renderer_d3d11.c")) || StringEqual(name, Lit("renderer_d3d11.c")) ||
@ -560,50 +461,200 @@ void OnBuild(StringList cli_args)
StringEqual(name, Lit("mp3_mmf.c")) || StringEqual(name, Lit("mp3_mmf.c")) ||
StringEqual(name, Lit("ttf_dwrite.cpp"))); StringEqual(name, Lit("ttf_dwrite.cpp")));
} }
} else {
ignore = false;
}
} }
} if (!ignore) {
if (ignore) continue; D_TagListAppend(&arena, &src_input_files, file);
D_Tag obj_file; D_Tag dep_file;
{ {
String obj_file_path = { 0 };
String name_no_extension = StringPathNoExtension(name); String name_no_extension = StringPathNoExtension(name);
obj_file_path = StringF(&arena, Lit("%F/%F.%F"), FmtStr(out_obj_dir_path), FmtStr(name_no_extension), FmtStr(obj_file_extension)); String dep_file_path = StringF(&arena, Lit("%F/%F.%F"), FmtStr(out_obj_dir_path), FmtStr(name_no_extension), FmtStr(dep_file_extension));
obj_file = D_FileTagFromPath(&arena, obj_file_path); dep_file = D_FileTagFromPath(&arena, dep_file_path);
} }
D_AddDependency(obj_file, file); D_AddDependency(file, dep_file);
D_AddDependency(executable, obj_file);
String comp_cmd = { 0 }; {
if (D_IsDirty(obj_file, &hist)) { String dep_file_data = D_ReadAll(&arena, dep_file);
String comp_cmd_fmt = is_c ? final_c_compile_args_fmt : final_cpp_compile_args_fmt; StringList patterns = { 0 };
comp_cmd = StringF(&arena, comp_cmd_fmt, FmtStr(file.full_path), FmtStr(obj_file.full_path)); StringListAppend(&arena, &patterns, Lit("\r\n"));
StringListAppend(&arena, &patterns, Lit("\n"));
StringList lines = StringSplit(&arena, dep_file_data, patterns);
for (StringListNode *dn = lines.first; dn; dn = dn->next) {
String line = dn->string;
line = StringReplace(&arena, line, Lit("\\ "), Lit(" "));
if (StringEndsWith(line, Lit(" \\"))) {
line.len -= 2;
}
if (StringBeginsWith(line, Lit(" "))) {
line.len -= 2;
line.text += 2;
}
if (!StringEndsWith(line, Lit(":"))) {
D_Tag tag = D_FileTagFromPath(&arena, line);
if (!D_TagEqual(tag, file)) {
D_AddDependency(file, tag);
}
}
}
}
}
} }
String step_name = StringF(&arena, Lit("%F -> %F"), FmtStr(name), FmtStr(D_GetName(obj_file)));
StepListAppend(&arena, &compile_command_list, step_name, comp_cmd, obj_file.full_path, true);
} }
/* ========================== * /* ========================== *
* Compile / link * Assemble build steps
* ========================== */ * ========================== */
if (D_IsDirty(executable, &hist)) { StepList build_steps = { 0 };
Bool success = true; D_TagList link_files = { 0 };
StringList link_files = { 0 };
/* Compile */ /* Build tar files */
Size comp_i = 0; for (D_TagListNode *n = tar_input_dirs.first; n; n = n->next) {
Size comp_count = compile_command_list.count; D_Tag input_dir = n->tag;
for (StepListNode *n = compile_command_list.first; n; n = n->next) { D_Tag tar_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/%F.tar"), FmtStr(out_inc_dir_path), FmtStr(D_GetName(input_dir))));
++comp_i; D_AddDependency(tar_file, input_dir);
String comp_cmd = n->cmd; if (should_embed_in_rc) {
if (comp_cmd.len > 0 ) { D_AddDependency(rc_res_file, tar_file);
SH_PrintF(Lit("[%F/%F] %F\n"), FmtI64(comp_i), FmtI64(comp_count), FmtStr(n->name)); } else {
//SH_PrintF(Lit("%F\n"), FmtStr(comp_cmd)); D_AddDependency(inc_src_file, tar_file);
SH_CommandResult result = SH_RunCommandCaptureOutput(&arena, comp_cmd, true); }
if (!n->silence_output_if_success || result.error != 0) {
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 rc file */
{
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 */
{
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);
D_Tag pch_c_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/%F.c_pch"), FmtStr(out_obj_dir_path), FmtStr(D_GetName(pch_header_file))));
D_Tag pch_cpp_file = D_FileTagFromPath(&arena, StringF(&arena, Lit("%F/%F.cpp_pch"), FmtStr(out_obj_dir_path), FmtStr(D_GetName(pch_header_file))));
D_AddDependency(pch_c_file, pch_header_file);
D_AddDependency(pch_cpp_file, pch_header_file);
if (arg_msvc) {
#if 0
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)));
#endif
} 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)));
/* C */
{
if (D_IsDirty(pch_c_file, &hist)) {
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)) {
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);
}
}
}
}
/* Build 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_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_FileTagFromPath(&arena, obj_file_path);
}
D_AddDependency(obj_file, 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 */
{
String link_files_str = { 0 };
{
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);
}
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));
StepListAppend(&arena, &build_steps, Lit("Linking"), cmd, true);
}
}
/* ========================== *
* Execute build steps
*
* TODO: Parallelize
* ========================== */
{
Bool success = true;
if (D_IsDirty(executable_file, &hist)) {
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)); SH_PrintF(Lit("%F\n"), FmtStr(result.output));
} }
if (result.error != 0) { if (result.error != 0) {
@ -612,41 +663,14 @@ void OnBuild(StringList cli_args)
break; break;
} }
} }
String link_file_path = n->link_file_path;
if (link_file_path.len > 0) {
StringListAppend(&arena, &link_files, link_file_path);
} }
} } else {
SH_Print(Lit("Nothing to build"));
/* Link */
if (success) {
String link_files_str = { 0 };
{
StringList link_files_quoted_list = { 0 };
for (StringListNode *n = link_files.first; n; n = n->next) {
String path = StringF(&arena, Lit("\"%F\""), FmtStr(n->string));
StringListAppend(&arena, &link_files_quoted_list, path);
}
link_files_str = StringFromStringList(&arena, Lit(" "), link_files_quoted_list);
}
String link_cmd = StringF(&arena, final_link_args_fmt, FmtStr(link_files_str));
//SH_PrintF(Lit("[Link] %F\n"), FmtStr(link_cmd));
SH_Print(Lit("Linking...\n"));
SH_CommandResult result = SH_RunCommandCaptureOutput(&arena, link_cmd, false);
if (result.error != 0) {
Assert(false);
success = false;
}
//D_SetDirty(executable);
} }
if (!success) { if (!success) {
Error(Lit("Build failed")); Error(Lit("Build failed"));
OS_Exit(1); OS_Exit(1);
} }
} else {
/* Nothing to build */
SH_Print(Lit("Nothing to build"));
} }
/* ========================== * /* ========================== *