#define B_IMPLEMENTATION #include "src/b.h" #include #define BUILD_DIR "build/" int debug_level = 1; void debug_or_release(B_Cmd* cmd) { if (debug_level == 0) b_cmd_append(cmd, "-O3", "-s", "-DNDEBUG"); else if (debug_level == 1) b_cmd_append(cmd, "-O2", "-ggdb", "-DVKDEBUG"); else if (debug_level == 2) b_cmd_append(cmd, "-O1", "-ggdb", "-DVKDEBUG"); else { b_cmd_append(cmd, "-O0", "-ggdb", "-DVKDEBUG"); b_cmd_append(cmd, "-fsanitize=address"); } } void inlcude_dirs(B_Cmd* cmd) { b_cmd_append(cmd, "-I./src/"); b_cmd_append(cmd, "-I./lib"); b_cmd_append(cmd, "-I./lib/imgui-1.90.7"); } void cflags(B_Cmd* cmd) { b_cmd_append(cmd, "-Wall", "-Wextra"); debug_or_release(cmd); b_cmd_append(cmd, "-march=native"); b_cmd_append(cmd, "-fno-math-errno", "-funroll-loops"); b_cmd_append(cmd, "-flto", "-pthread"); inlcude_dirs(cmd); } void cxxflags(B_Cmd *cmd) { b_cmd_append(cmd, "-Wall", "-Wextra"); b_cmd_append(cmd, "-Wno-string-plus-int", "-Wno-nullability-completeness", "-Wno-unused-function", "-Wno-missing-field-initializers", "-Wno-unused-parameter", "-Wno-unused-variable"); debug_or_release(cmd); b_cmd_append(cmd, "-march=native"); b_cmd_append(cmd, "-fno-math-errno", "-funroll-loops"); b_cmd_append(cmd, "-flto", "-pthread"); inlcude_dirs(cmd); //b_cmd_append(cmd, "-O3"); } void cxx(B_Cmd *cmd) { b_cmd_append(cmd, "clang"); cxxflags(cmd); } void cc(B_Cmd *cmd) { b_cmd_append(cmd, "clang"); cflags(cmd); } void libs(B_Cmd *cmd) { b_cmd_append(cmd, "-lSDL2", "-lm", "-lvulkan", "-lshaderc_shared", "-lstdc++"); } bool build_c(bool force, B_Cmd* cmd, const char** input_paths, size_t input_paths_len, const char** dep_paths, size_t dep_paths_len, const char** objects, size_t objects_len, const char* output_path) { size_t size = input_paths_len + objects_len; const char **new_array = (const char **)malloc((size) * sizeof(const char *)); // Copy existing elements to the new array int i = 0; for (; i < input_paths_len; ++i) { new_array[i] = input_paths[i]; } for (; i < size; ++i) { new_array[i] = objects[i - input_paths_len]; } int rebuild_is_needed = b_needs_rebuild(output_path, new_array, size); int dep_rebuild = 0; if (rebuild_is_needed == 0) dep_rebuild = b_needs_rebuild(output_path, dep_paths, dep_paths_len); if (rebuild_is_needed < 0 || dep_rebuild < 0) return false; if (force || rebuild_is_needed || dep_rebuild) { cmd->count = 0; cc(cmd); b_cmd_append(cmd, "-o", output_path); b_da_append_many(cmd, new_array, size); libs(cmd); return b_cmd_run_sync(*cmd); } b_log(B_INFO, "%s is up-to-date", output_path); return true; } bool build_objects(const char* lang, const char* object, const char* deps[], size_t deps_size, const char* out[], // deps_size + 1 size_t * it) { char *tmpc, *tmpc2; char tmp[deps_size + 1][1000]; char* tmp_obj = strdup(object); char path[1000] = ""; strcpy(path, BUILD_DIR); //strcat(path, "/"); strcat(path, basename(tmp_obj)); if (!strcmp(lang, "C++")) path[ strlen(path) - 4 ] = '\0'; else path[ strlen(path) - 2 ] = '\0'; strcat(path, "/"); b_mkdir_if_not_exists(path); int rebuild = 0; for (size_t i = 0; i < deps_size + 1; i++) { strcpy(tmp[i], path); if (i == deps_size) { tmpc = basename(tmp_obj); strcat(tmp[i], tmpc); free(tmp_obj); } else { tmpc2 = strdup(deps[i]); tmpc = basename(tmpc2); strcat(tmp[i], tmpc); free(tmpc2); } size_t s = strlen(tmp[i]); if (!strcmp(lang, "C++")) { tmp[i][s - 4] = '.'; tmp[i][s - 3] = 'o'; tmp[i][s - 2] = '\0'; } else { tmp[i][s - 2] = '.'; tmp[i][s - 1] = 'o'; tmp[i][s ] = '\0'; } out[*it] = strdup(tmp[i]); int c = b_needs_rebuild1(out[*it], i == deps_size ? object : deps[i]); if (c < 0) return false; rebuild += c; if (c != 0) { B_Cmd cmd = { 0 }; if (!strcmp(lang, "C++")) cxx(&cmd); else cc(&cmd); b_cmd_append(&cmd, "-c"); b_cmd_append(&cmd, i == deps_size ? object : deps[i]); b_cmd_append(&cmd, "-o"); b_cmd_append(&cmd, out[*it]); bool rc = b_cmd_run_sync(cmd); if (!rc) return false; } *it = *it + 1; } if (rebuild == 0) b_log(B_INFO, "%s* is up-to-date", path); /* if (rebuild != 0) { */ /* if (!strcmp(lang, "C++")) */ /* cxx(&cmd); */ /* else */ /* cc(&cmd); */ /* b_cmd_append(&cmd, "-c"); */ /* b_cmd_append(&cmd, object); */ /* b_da_append_many(&cmd, deps, deps_size); */ /* return b_cmd_run_sync(cmd); */ /* } */ //b_log(B_INFO, "%s is up-to-date", out[deps_size]); return true; } int main(int argc, char *argv[]) { B_GO_REBUILD_URSELF(argc, argv); const char *program_name = b_shift_args(&argc, &argv); bool force = false; while (argc > 0) { const char *flag = b_shift_args(&argc, &argv); if (strcmp(flag, "-f") == 0) { force = true; } else { b_log(B_ERROR, "Unknown flag `%s`", flag); return 1; } } /* const char* const new_deps[][100] = { */ /* { "src/state.h" }, */ /* { "src/vksetup.h" }, */ /* { "src/cplusplus", */ /* "lib/imgui-1.90.7/imgui.cpp", */ /* "lib/imgui-1.90.7/imgui_demo.cpp", */ /* "lib/imgui-1.90.7/imgui_draw.cpp", */ /* "lib/imgui-1.90.7/imgui_tables.cpp", */ /* "lib/imgui-1.90.7/imgui_widgets.cpp", */ /* "lib/imgui-1.90.7/backends/imgui_impl_sdl2.cpp", */ /* "lib/imgui-1.90.7/backends/imgui_impl_vulkan.cpp" }, */ /* {"src/testlib", "src/hash" } */ /* }; */ /* if (!build("render", "src/render.c", new_deps, B_ARRAY_LEN(new_deps))) return 1; */ const char* cplusplus_deps[] = { "lib/imgui-1.90.7/imgui.cpp", "lib/imgui-1.90.7/imgui_demo.cpp", "lib/imgui-1.90.7/imgui_draw.cpp", "lib/imgui-1.90.7/imgui_tables.cpp", "lib/imgui-1.90.7/imgui_widgets.cpp", "lib/imgui-1.90.7/backends/imgui_impl_sdl2.cpp", "lib/imgui-1.90.7/backends/imgui_impl_vulkan.cpp", }; const char *render_deps[] = { "src/state.h", "src/vksetup.h", "src/cplusplus.h", }; const char* render_paths[] = { "src/render.c", }; B_Cmd cmd = {0}; size_t it = 0; const char* objects[B_ARRAY_LEN(cplusplus_deps) + 1 + 1]; b_mkdir_if_not_exists(BUILD_DIR); // TODO: make build_object func to build one by one, and add headers if (!build_objects("C", "src/test.c", NULL, 0, objects, &it)) return 1; if (!build_objects("C++", "src/cplusplus.cpp", cplusplus_deps, B_ARRAY_LEN(cplusplus_deps), objects, &it)) return 1; if (!build_c(force, &cmd, render_paths, B_ARRAY_LEN(render_paths), render_deps, B_ARRAY_LEN(render_deps), objects, B_ARRAY_LEN(objects), BUILD_DIR"render")) return 1; return 0; } /* 1. Build list of .cpp (with s) -> into build/cxx//.o 2. Build list of .c (with s) -> into build/c//.o 3. Build .c linking with the objects from 1 & 2 -> into Check for rebuilds: 1. and s 2. and s 3. and all links {cxx,c}/ * / *.o */