From 59fd8c4328691c53427b2ad2bdb30af009de46fa Mon Sep 17 00:00:00 2001 From: hkc Date: Sat, 25 Nov 2023 22:16:11 +0300 Subject: [PATCH] Now I can build raylib using cbt --- .gitignore | 1 + cbt.c | 17 ++++-- cbt.h | 159 +++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 133 insertions(+), 44 deletions(-) diff --git a/.gitignore b/.gitignore index 3dede65..3c9481a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ cbt cbt_impl.c state add-impl.py +raylib diff --git a/cbt.c b/cbt.c index 42f91fe..143cb50 100644 --- a/cbt.c +++ b/cbt.c @@ -1,20 +1,29 @@ -// x-run: python3 ./add-impl.py && ~/scripts/runc.sh % -Wall -Wextra -X-gdb +// x-run: python3 ./add-impl.py && ~/scripts/runc.sh % -Wall -Wextra #define CBT_IMPLEMENTATION #include "cbt.h" int main(int argc, char **argv) { CBT_INIT(argc, argv); - cbt_shell(CBT_PROC_AUTO, "sh", "-c", "echo 'owo'"); + /*cbt_shell(CBT_PROC_AUTO, "sh", "-c", "echo 'owo'");*/ // example usage, won't actually work struct cbt_lib raylib = cbt_lib("raylib"); - cbt_lib_src(&raylib, "./raylib/*.c"); + raylib.type = CBT_LIB_STATIC; + cbt_lib_src(&raylib, "./raylib/src/*.c"); cbt_lib_ldflags(&raylib, "-lm"); - cbt_lib_cflags(&raylib, "-Wall", "-Wextra"); + cbt_lib_cflags(&raylib, "-D_GNU_SOURCE", "-DPLATFORM_DESKTOP", + "-DGRAPHICS_API_OPENGL_33", "-Wno-missing-braces", + "-Werror=pointer-arith", "-fno-strict-aliasing", "-std=c99", + "-fPIC", "-O1", "-Werror=implicit-function-declaration", + "-I./raylib/src", "-I./raylib/src/external/glfw/include", + "-I./raylib/src/external/glfw/deps/mingw"); cbt_lib_build(raylib, NULL); cbt_lib_free(raylib); + cbt_proc_wait(cbt_proc_new(CBT_PROC_AUTO, cbt_cc, "clock.c", "-o", "clock", + "libraylib.a", "-lm", "-lpthread")); + cbt_cleanup(); return 0; } diff --git a/cbt.h b/cbt.h index c2946bd..cfbf984 100644 --- a/cbt.h +++ b/cbt.h @@ -20,6 +20,8 @@ struct cbt_strarr { size_t size, cap; }; +struct cbt_strarr cbt_strarrdup(struct cbt_strarr src); + extern long cbt_start_time; extern enum cbt_loglevel cbt_verbosity; extern char *cbt_cc, *cbt_cache_dir; @@ -43,7 +45,7 @@ const char *cbt_escape_args(char **args); const char *cbt_escape_argsd(struct cbt_strarr arr); #ifndef CBT_FMT_NBUFS -#define CBT_FMT_NBUFS 64 +#define CBT_FMT_NBUFS 128 #endif #ifndef CBT_FMT_BUFSIZE @@ -118,8 +120,8 @@ void cbt_binary_free(struct cbt_binary bin); #define cbt_da_add(ARR, ITEM) \ { \ if (ARR.size >= ARR.cap) { \ - size_t size = ARR.size == 0 ? CBT_DA_INIT_SIZE : ARR.size * 2; \ - ARR.items = CBT_REALLOC(ARR.items, size * sizeof(ARR.items[0])); \ + ARR.cap = ARR.size == 0 ? CBT_DA_INIT_SIZE : ARR.size * 2; \ + ARR.items = CBT_REALLOC(ARR.items, ARR.cap * sizeof(ARR.items[0])); \ } \ ARR.items[ARR.size] = (ITEM); \ ARR.size++; \ @@ -132,6 +134,8 @@ void cbt_binary_free(struct cbt_binary bin); ARR.size--; \ } +#define cbt_da_pop(ARR) cbt_da_remove(ARR, ARR.size - 1) + #define cbt_da_merge(OUT, IN) \ { \ OUT.cap = OUT.size + IN.size; \ @@ -294,7 +298,7 @@ void cbt_cleanup(void) { const char *cbt_fmt(const char *fmt, ...) { static char cbt_fmt_buffers[CBT_FMT_NBUFS][CBT_FMT_BUFSIZE]; static int cbt_fmt_buffer = 0; - char *buffer = cbt_fmt_buffers[cbt_fmt_buffer++ % CBT_FMT_NBUFS]; + char *buffer = cbt_fmt_buffers[(cbt_fmt_buffer++) % CBT_FMT_NBUFS]; va_list args; va_start(args, fmt); vsnprintf(buffer, CBT_FMT_BUFSIZE - 1, fmt, args); @@ -324,6 +328,15 @@ void cbt_log(enum cbt_loglevel lvl, const char *fmt, ...) { fputc('\n', stdout); } +struct cbt_strarr cbt_strarrdup(struct cbt_strarr src) { + char **items = calloc(src.size, sizeof(char *)); + for (size_t i = 0; i < src.size; i++) { + items[i] = strdup(src.items[i]); + } + return (struct cbt_strarr) { items, src.size, src.size }; +} + + // TODO: find a better option const char *cbt_escape_shell(char *arg) { int n = strlen(arg); @@ -438,7 +451,14 @@ struct cbt_proc cbt_proc_newv(enum cbt_proc_mode mode, va_list args) { } cbt_da_add(args_da, NULL); - return cbt_proc_newd(mode, args_da); + struct cbt_proc proc = cbt_proc_newd(mode, args_da); + cbt_log(CBT_LOG_DEBUG, "freeing up args"); + for (size_t i = 0; i < args_da.size; i++) { + free(args_da.items[i]); + } + free(args_da.items); + + return proc; } struct cbt_proc cbt_proc_newd(enum cbt_proc_mode mode, struct cbt_strarr args) { @@ -455,7 +475,7 @@ struct cbt_proc cbt_proc_newd(enum cbt_proc_mode mode, struct cbt_strarr args) { procinfo.pid = fork(); if (procinfo.pid < 0) { cbt_log(CBT_LOG_ERROR, "fork() failed: %s", strerror(errno)); - goto cbt_proc_new_cleanup; + return procinfo; } if (procinfo.pid == 0) { // child @@ -487,13 +507,6 @@ struct cbt_proc cbt_proc_newd(enum cbt_proc_mode mode, struct cbt_strarr args) { cbt__add_fd(pipe_fds_serr[0], true); } - cbt_proc_new_cleanup: - cbt_log(CBT_LOG_DEBUG, "freeing up args"); - for (size_t i = 0; i < args.size; i++) { - free(args.items[i]); - } - free(args.items); - return procinfo; } } @@ -596,18 +609,22 @@ void _cbt_lib_src(struct cbt_lib *lib, ...) { va_list args; va_start(args, lib); - glob_t globbuf; + glob_t globbuf = { 0 }; for (char *arg = va_arg(args, char *); arg; arg = va_arg(args, char *)) { - CBT_FAIL(glob(arg, GLOB_APPEND | GLOB_BRACE, _cbt_globerr, &globbuf) != 0); + memset(&globbuf, 0, sizeof(glob_t)); + CBT_FAIL(glob(arg, GLOB_BRACE, _cbt_globerr, &globbuf) != 0); + for (size_t i = 0; i < globbuf.gl_pathc; i++) { + char *path = globbuf.gl_pathv[i]; + cbt_log(CBT_LOG_DEBUG, "gl_pathv[%d] = %s", i, path); + if (path) { + cbt_da_add(lib->sources, strdup(path)); + } + } + globfree(&globbuf); } - for (size_t i = 0; i < globbuf.gl_pathc; i++) { - char *path = strdup(globbuf.gl_pathv[i]); - cbt_da_add(lib->sources, path); - } - globfree(&globbuf); va_end(args); } @@ -624,7 +641,7 @@ void _cbt_lib_ldflags(struct cbt_lib *lib, ...) { va_list args; va_start(args, lib); for (char *arg = va_arg(args, char *); arg; arg = va_arg(args, char *)) { - cbt_da_add(lib->ldflags, arg); + cbt_da_add(lib->ldflags, strdup(arg)); } va_end(args); } @@ -641,36 +658,98 @@ bool cbt_lib_build(struct cbt_lib lib, const char *compiler) { return false; } - struct cbt_strarr args = {0}; - cbt_da_add(args, (char *)(compiler ? compiler : cbt_cc)); + { + struct cbt_strarr args = {0}; + cbt_da_add(args, (char *)(compiler ? compiler : cbt_cc)); - cbt_da_merge(args, lib.cflags); + cbt_da_merge(args, lib.cflags); + cbt_da_add(args, "-c"); - cbt_log(CBT_LOG_INFO, "args.size: %d", args.size); - cbt_log(CBT_LOG_INFO, "CMD: %s", cbt_escape_argsd(args)); + cbt_log(CBT_LOG_INFO, "args.size: %d", args.size); + cbt_log(CBT_LOG_INFO, "CMD: %s", cbt_escape_argsd(args)); - cbt_da_add(args, NULL); - cbt_da_add(args, "-o"); - cbt_da_add(args, NULL); + cbt_da_add(args, NULL); // input file + cbt_da_add(args, "-o"); + cbt_da_add(args, NULL); // output file + cbt_da_add(args, NULL); - for (size_t i = 0; i < lib.sources.size; i++) { - args.items[args.size - 3] = lib.sources.items[i]; - args.items[args.size - 1] = ".o"; // TODO + for (size_t i = 0; i < lib.sources.size; i++) { + char *source_name = args.items[args.size - 4] = lib.sources.items[i]; + char *outname = (char *)cbt_fmt("%s", lib.sources.items[i]); + outname[strlen(outname) - 1] = 'o'; + args.items[args.size - 2] = outname; + + cbt_log(CBT_LOG_INFO, "building %s -> %s", lib.sources.items[i], outname); + if (cbt_needs_recompilation(source_name, outname)) { + struct cbt_proc proc = cbt_proc_newd(CBT_PROC_AUTO, args); + if (cbt_proc_wait(proc) != 0) { + cbt_log(CBT_LOG_ERROR, "build failed: %s", cbt_escape_argsd(args)); + return false; + } + } else { + cbt_log(CBT_LOG_INFO, "skipping (already built)"); + } + } + free(args.items); + } + + + if (lib.type == CBT_LIB_SHARED) { + cbt_log(CBT_LOG_INFO, "Linking everything together..."); + + struct cbt_strarr args = {0}; + cbt_da_add(args, (char *)strdup(compiler ? compiler : cbt_cc)); + + for (size_t i = 0; i < lib.sources.size; i++) { + char *outname = (char *)cbt_fmt("%s", lib.sources.items[i]); + outname[strlen(outname) - 1] = 'o'; + cbt_da_add(args, strdup(outname)); + } + + cbt_da_merge(args, lib.ldflags); + + cbt_da_add(args, strdup("-shared")); + cbt_da_add(args, strdup("-o")); + cbt_da_add(args, strdup(cbt_fmt("lib%s.so", lib.libname))); + cbt_da_add(args, NULL); struct cbt_proc proc = cbt_proc_newd(CBT_PROC_AUTO, args); if (cbt_proc_wait(proc) != 0) { cbt_log(CBT_LOG_ERROR, "build failed: %s", cbt_escape_argsd(args)); return false; } + for (size_t i = 0; i < args.size - 1; i++) { + free(args.items[i]); + } + free(args.items); + } else if (lib.type == CBT_LIB_STATIC) { + cbt_log(CBT_LOG_INFO, "Archiving"); + + struct cbt_strarr args = {0}; + cbt_da_add(args, strdup("ar")); + cbt_da_add(args, strdup("rcs")); + cbt_da_add(args, strdup(cbt_fmt("lib%s.a", lib.libname))); + + for (size_t i = 0; i < lib.sources.size; i++) { + char *outname = (char *)cbt_fmt("%s", lib.sources.items[i]); + outname[strlen(outname) - 1] = 'o'; + cbt_da_add(args, strdup(outname)); + } + + cbt_da_add(args, NULL); + struct cbt_proc proc = cbt_proc_newd(CBT_PROC_AUTO, args); + if (cbt_proc_wait(proc) != 0) { + cbt_log(CBT_LOG_ERROR, "build failed: %s", cbt_escape_argsd(args)); + return false; + } + for (size_t i = 0; i < args.size - 1; i++) { + free(args.items[i]); + } + free(args.items); + } else { + CBT_TODO("Unknown library type"); } - char **argp = &args.items[args.size - 1]; - cbt_da_merge(args, lib.ldflags); - - *argp = (char *)cbt_fmt("lib%s.so", lib.libname); - - // todo: link - - return false; + return true; } void cbt_lib_free(struct cbt_lib lib) {