summaryrefslogblamecommitdiffstats
path: root/b.c
blob: 22a2304c0ba5b217861bbebc06e98efffca77b3a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12

                        


                          
 





                            
                                               



                                                   
        
                                                   

                                            
























                                                         


                                                                                                                                                                                         


                        


                                                         

                    
                             

 





                             










                                                                                 






                                     

                                 
                                 
 











                                                                                
                         




                                                                         

                                                             
 
                                                  


                                         
                                           







                                                 
    



                                    

                                                 
 



                                 
 


                                  



                                    



















                                              










                               
 
                                                                          












                                                            
                                   


                                    
                  
   
                                                             
 












                                                      


              


















                                                        















                                                                                        
                                  







                                                      

                               

                    
                      
    
                                
                   


                  

                                                           



                                                                      

                                                                                                                      
                                                                                                                                                                        


           











                                                                                
#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

*/