#define B_IMPLEMENTATION
#include "src/b.h"
#include <libgen.h>
#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 <object>.cpp (with <dep>s) -> into build/cxx/<object>/<dep>.o
2. Build list of <object>.c (with <dep>s) -> into build/c/<object>/<dep>.o
3. Build <target>.c linking with the objects from 1 & 2 -> into <target>
Check for rebuilds:
1. <object.cpp> and <dep>s
2. <object.c> and <dep>s
3. <target.c> and all links {cxx,c}/ * / *.o
*/