tbd: library definitions

This commit is contained in:
Casey 2023-11-19 13:50:44 +03:00
parent fed1c0a3ca
commit cdacf0868b
Signed by: hkc
GPG Key ID: F0F6CFE11CDB0960
2 changed files with 203 additions and 25 deletions

13
cbt.c
View File

@ -1,13 +1,18 @@
// x-run: ~/scripts/runc.sh % -Wall -Wextra // x-run: python3 ./add-impl.py && ~/scripts/runc.sh % -Wall -Wextra
#define CBT_IMPLEMENTATION #define CBT_IMPLEMENTATION
#include "cbt.h" #include "cbt.h"
int main(int argc, char **argv) { int main(int argc, char **argv) {
CBT_INIT(argc, argv); CBT_INIT(argc, argv);
struct cbt_proc proc = cbt_shell(CBT_PROC_AUTO, "sh", "-c", "echo 'owo'");
cbt_proc_new(CBT_PROC_NORMAL, "sh", "-c", "echo 'owo'");
cbt_proc_wait(proc); struct cbt_lib raylib = cbt_lib("raylib", "./raylib");
cbt_lib_src(&raylib, "rcore.c");
cbt_lib_ldflags(&raylib, "-lm");
cbt_lib_cflags(&raylib, "-Wall", "-Wextra");
cbt_lib_build(raylib, NULL);
cbt_lib_free(raylib);
cbt_cleanup(); cbt_cleanup();
return 0; return 0;

211
cbt.h
View File

@ -15,9 +15,14 @@ enum cbt_loglevel {
CBT_LOG_ALL CBT_LOG_ALL
}; };
struct cbt_chararray {
char **items;
size_t size, cap;
};
extern long cbt_start_time; extern long cbt_start_time;
extern enum cbt_loglevel cbt_verbosity; extern enum cbt_loglevel cbt_verbosity;
extern char *cbt_cc; extern char *cbt_cc, *cbt_cache_dir;
void cbt__init(int argc, char **argv, const char *source_file); void cbt__init(int argc, char **argv, const char *source_file);
void cbt_cleanup(void); void cbt_cleanup(void);
@ -27,11 +32,15 @@ extern const char *cbt_log__colors[CBT_LOG_ALL + 1];
extern const char *cbt_log__typecolors[8]; extern const char *cbt_log__typecolors[8];
void cbt_log(enum cbt_loglevel lvl, const char *fmt, ...); void cbt_log(enum cbt_loglevel lvl, const char *fmt, ...);
long cbt_get_time(void); long cbt_get_time(void);
unsigned long cbt_get_modtime(const char *filename); unsigned long cbt_get_modtime(const char *filename);
bool cbt_needs_recompilation(const char *input, const char *output); bool cbt_needs_recompilation(const char *input, const char *output);
const char *cbt_escape_shell(char *arg); const char *cbt_escape_shell(char *arg);
const char *cbt_escape_args(char **args); const char *cbt_escape_args(char **args);
const char *cbt_escape_argsd(struct cbt_chararray arr);
#ifndef CBT_FMT_NBUFS #ifndef CBT_FMT_NBUFS
#define CBT_FMT_NBUFS 64 #define CBT_FMT_NBUFS 64
@ -43,11 +52,6 @@ const char *cbt_escape_args(char **args);
const char *cbt_fmt(const char *fmt, ...); const char *cbt_fmt(const char *fmt, ...);
struct cbt_proc_args {
char **items;
size_t size, cap;
};
struct cbt_proc { struct cbt_proc {
FILE *fp_stdin, *fp_stdout, *fp_stderr; FILE *fp_stdin, *fp_stdout, *fp_stderr;
int pid; int pid;
@ -56,20 +60,53 @@ struct cbt_proc {
struct cbt_procgroup { struct cbt_procgroup {
struct cbt_proc *items; struct cbt_proc *items;
size_t size, cap; size_t size, cap;
bool fixed_size;
}; };
enum cbt_proc_mode { enum cbt_proc_mode {
CBT_PROC_NORMAL = 0, CBT_PROC_AUTO = 0,
CBT_PROC_R = 1, CBT_PROC_R = 1,
CBT_PROC_W = 2, CBT_PROC_W = 2,
CBT_PROC_RW = 3, CBT_PROC_RW = 3,
}; };
#define cbt_proc_new(...) _cbt_proc_new(__VA_ARGS__, NULL) #define cbt_proc_new(...) _cbt_proc_new(__VA_ARGS__, NULL)
#define cbt_shell(...) cbt_proc_wait(_cbt_proc_new(__VA_ARGS__, NULL))
struct cbt_proc _cbt_proc_new(enum cbt_proc_mode mode, ...); struct cbt_proc _cbt_proc_new(enum cbt_proc_mode mode, ...);
struct cbt_proc cbt_proc_newv(enum cbt_proc_mode mode, va_list args); struct cbt_proc cbt_proc_newv(enum cbt_proc_mode mode, va_list args);
int cbt_proc_wait(struct cbt_proc proc); int cbt_proc_wait(struct cbt_proc proc);
enum cbt_libtype { CBT_LIB_STATIC, CBT_LIB_SHARED };
struct cbt_lib {
enum cbt_libtype type;
const char *basepath;
const char *libname;
struct cbt_chararray sources, cflags, ldflags;
};
#define cbt_lib_src(LIB, ...) _cbt_lib_src(LIB, __VA_ARGS__, NULL)
#define cbt_lib_cflags(LIB, ...) _cbt_lib_cflags(LIB, __VA_ARGS__, NULL)
#define cbt_lib_ldflags(LIB, ...) _cbt_lib_ldflags(LIB, __VA_ARGS__, NULL)
struct cbt_lib cbt_lib(const char *libname, const char *basepath);
void _cbt_lib_src(struct cbt_lib *lib, ...);
void _cbt_lib_cflags(struct cbt_lib *lib, ...);
void _cbt_lib_ldflags(struct cbt_lib *lib, ...);
bool cbt_lib_build(struct cbt_lib lib, const char *cc);
void cbt_lib_free(struct cbt_lib lib);
struct cbt_binary {
const char *out_path;
struct cbt_chararray sources, cflags, ldflags;
};
#define cbt_binary_add_src(B, ...) _cbt_binary_add_src(B, __VA_ARGS__, NULL)
#define cbt_binary_build(B, CC, ...) _cbt_binary_build(B, CC, __VA_ARGS__, NULL)
struct cbt_binary cbt_binary(const char *out_path);
void _cbt_binary_add_src(struct cbt_binary bin, ...);
bool _cbt_binary_build(struct cbt_binary bin, const char *compiler, ...);
void cbt_binary_free(struct cbt_binary bin);
#define CBT_ARRLEN(ARR) (sizeof(ARR) / sizeof(ARR[0])) #define CBT_ARRLEN(ARR) (sizeof(ARR) / sizeof(ARR[0]))
#ifndef CBT_REALLOC #ifndef CBT_REALLOC
@ -95,11 +132,30 @@ int cbt_proc_wait(struct cbt_proc proc);
ARR.size--; \ ARR.size--; \
} }
#define cbt_da_merge(OUT, IN) \
{ \
OUT.cap = OUT.size + IN.size; \
OUT.items = realloc(OUT.items, sizeof(OUT.items[0]) * OUT.cap); \
size_t offset = OUT.size; \
OUT.size = OUT.size + IN.size; \
memmove(&OUT.items[offset], IN.items, sizeof(OUT.items[0]) * IN.size); \
}
#define cbt_da_copy(OUT, IN, T) { \
OUT.size = IN.size; \
OUT.cap = IN.size; \
OUT.items = malloc(sizeof(IN.items[0]) * IN.size); \
memcpy(OUT.items, IN.items, sizeof(IN.items[0]) * IN.size); \
}
#ifdef CBT_IMPLEMENTATION #ifdef CBT_IMPLEMENTATION
//-*- begin cbt_impl.c 5 //-*- begin cbt_impl.c 5
#define __USE_GNU #define __USE_GNU
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <glob.h>
#include <libgen.h>
#include <linux/limits.h>
#include <poll.h> #include <poll.h>
#include <pthread.h> #include <pthread.h>
#include <signal.h> #include <signal.h>
@ -119,8 +175,17 @@ int cbt_proc_wait(struct cbt_proc proc);
abort(); \ abort(); \
}; };
#define CBT_TODO(NAME) \
{ \
cbt_log(CBT_LOG_FATAL, "%s: Not implemented! %s:%d", NAME, __FILE__, \
__LINE__); \
abort(); \
}
enum cbt_loglevel cbt_verbosity = CBT_LOG_INFO; enum cbt_loglevel cbt_verbosity = CBT_LOG_INFO;
char *cbt_cc = NULL; char *cbt_cc = NULL;
char cbt_location[PATH_MAX] = {0};
char *cbt_cache_dir = NULL;
long cbt_start_time = 0; long cbt_start_time = 0;
bool cbt_running = false; bool cbt_running = false;
@ -137,9 +202,9 @@ struct _cbt__autoproc_set {
size_t size, cap; size_t size, cap;
} cbt__autoproc_set = {0}; } cbt__autoproc_set = {0};
struct cbt_procgroup cbt__default_procgroup = {.items = 0, .size = 0, .cap = 4}; struct cbt_procgroup cbt__proc_pool = {0, .cap = 4, .fixed_size = 1};
pthread_t _cbt__autoproc_thread; pthread_t cbt__autoproc_thread;
pthread_mutex_t _cbt__autoproc_mut = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t _cbt__autoproc_mut = PTHREAD_MUTEX_INITIALIZER;
const char *cbt_log__colors[CBT_LOG_ALL + 1] = { const char *cbt_log__colors[CBT_LOG_ALL + 1] = {
@ -154,7 +219,7 @@ void cbt__init(int argc, char **argv, const char *source_file) {
cbt_running = true; cbt_running = true;
(void)argc; (void)argc;
cbt_log(CBT_LOG_INFO, "Running CBT build %s %s from %s", __DATE__, __TIME__, __FILE__); cbt_log(CBT_LOG_INFO, "Running CBT build %s %s", __DATE__, __TIME__);
if (!cbt_cc) if (!cbt_cc)
cbt_cc = getenv("CC"); cbt_cc = getenv("CC");
@ -162,24 +227,35 @@ void cbt__init(int argc, char **argv, const char *source_file) {
cbt_cc = "cc"; cbt_cc = "cc";
cbt_log(CBT_LOG_INFO, "Found C Compiler: %s", cbt_cc); cbt_log(CBT_LOG_INFO, "Found C Compiler: %s", cbt_cc);
CBT_FAIL(readlink("/proc/self/exe", cbt_location, PATH_MAX) == -1);
cbt_log(CBT_LOG_INFO, "Location: %s", cbt_location);
char *cbt_cache_dir = strdup(cbt_location);
cbt_cache_dir = strdup(cbt_fmt("%s/%s", dirname(cbt_cache_dir), "cache"));
cbt_log(CBT_LOG_DEBUG, "Args: %s", cbt_escape_args(argv)); cbt_log(CBT_LOG_DEBUG, "Args: %s", cbt_escape_args(argv));
cbt_log(CBT_LOG_DEBUG, "%s", cbt_fmt("format test: %s", "ok")); cbt_log(CBT_LOG_DEBUG, "%s", cbt_fmt("format test: %s", "ok"));
cbt__default_procgroup.items = cbt_log(CBT_LOG_INFO, "Cache dir: %s", cbt_cache_dir);
calloc(cbt__default_procgroup.cap, sizeof(struct cbt_proc));
cbt__proc_pool.items = calloc(cbt__proc_pool.cap, sizeof(struct cbt_proc));
{
cbt_log(CBT_LOG_DEBUG, "Starting line processor thread"); cbt_log(CBT_LOG_DEBUG, "Starting line processor thread");
int err; int err;
if ((err = pthread_create(&_cbt__autoproc_thread, NULL, cbt__line_processor, NULL)) != 0) { if ((err = pthread_create(&cbt__autoproc_thread, NULL, cbt__line_processor,
cbt_log(CBT_LOG_ERROR, "pthread_create() failed for line processor: %d", err); NULL)) != 0) {
cbt_log(CBT_LOG_ERROR, "pthread_create() failed for line processor: %d",
err);
exit(1); exit(1);
} }
}
if (cbt_needs_recompilation(source_file, argv[0])) { if (cbt_needs_recompilation(source_file, argv[0])) {
cbt_log(CBT_LOG_INFO, "Recompiling..."); cbt_log(CBT_LOG_INFO, "Recompiling...");
struct cbt_proc cc = cbt_proc_new(CBT_PROC_NORMAL, cbt_cc, source_file, struct cbt_proc cc = cbt_proc_new(CBT_PROC_AUTO, cbt_cc, source_file, "-o",
"-o", argv[0], "-Wall", "-Wextra", NULL); argv[0], "-Wall", "-Wextra", NULL);
int status = cbt_proc_wait(cc); int status = cbt_proc_wait(cc);
cbt_log(CBT_LOG_INFO, "CC returned %d", status); cbt_log(CBT_LOG_INFO, "CC returned %d", status);
if (status == 0) { if (status == 0) {
@ -196,7 +272,7 @@ void cbt_cleanup(void) {
pthread_mutex_lock(&_cbt__autoproc_mut); pthread_mutex_lock(&_cbt__autoproc_mut);
cbt_running = false; cbt_running = false;
cbt_log(CBT_LOG_INFO, "cbt shutting down"); cbt_log(CBT_LOG_INFO, "cbt shutting down");
pthread_join(_cbt__autoproc_thread, NULL); pthread_join(cbt__autoproc_thread, NULL);
pthread_mutex_unlock(&_cbt__autoproc_mut); pthread_mutex_unlock(&_cbt__autoproc_mut);
cbt_log(CBT_LOG_INFO, "shutdown complete"); cbt_log(CBT_LOG_INFO, "shutdown complete");
} }
@ -279,6 +355,18 @@ const char *cbt_escape_args(char **args) {
return out; return out;
} }
const char *cbt_escape_argsd(struct cbt_chararray arr) {
if (arr.size == 0 || arr.items[0] == NULL)
return cbt_fmt("");
char *out = (char *)cbt_escape_shell(arr.items[0]);
for (size_t i = 1; i < arr.size; i++) {
if (arr.items[i]) {
out = (char *)cbt_fmt("%s %s", out, cbt_escape_shell(arr.items[i]));
}
}
return out;
}
unsigned long cbt_get_modtime(const char *filename) { unsigned long cbt_get_modtime(const char *filename) {
struct stat st; struct stat st;
int ret = lstat(filename, &st); int ret = lstat(filename, &st);
@ -328,7 +416,7 @@ struct cbt_proc _cbt_proc_new(enum cbt_proc_mode mode, ...) {
struct cbt_proc cbt_proc_newv(enum cbt_proc_mode mode, va_list args) { struct cbt_proc cbt_proc_newv(enum cbt_proc_mode mode, va_list args) {
struct cbt_proc procinfo = {0}; struct cbt_proc procinfo = {0};
struct cbt_proc_args args_da = {0}; struct cbt_chararray args_da = {0};
while (true) { while (true) {
const char *arg = va_arg(args, const char *); const char *arg = va_arg(args, const char *);
if (arg == NULL) if (arg == NULL)
@ -469,6 +557,91 @@ void *cbt__line_processor(void *arg) {
return NULL; return NULL;
} }
struct cbt_lib cbt_lib(const char *libname, const char *basepath) {
return (struct cbt_lib){.type = CBT_LIB_STATIC,
.basepath = basepath,
.libname = libname,
.cflags = {0},
.ldflags = {0},
.sources = {0}};
}
int _cbt_globerr(const char *epath, int eerrno) {
cbt_log(CBT_LOG_WARNING, "glob() failed at %s: %s", epath, strerror(eerrno));
return 0;
}
void _cbt_lib_src(struct cbt_lib *lib, ...) {
va_list args;
va_start(args, lib);
glob_t globbuf;
for (char *arg = va_arg(args, char *); arg; arg = va_arg(args, char *)) {
glob(cbt_fmt("%s/%s", lib->basepath, arg),
GLOB_APPEND | GLOB_BRACE | GLOB_NOCHECK, _cbt_globerr, &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);
}
void _cbt_lib_cflags(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->cflags, arg);
}
va_end(args);
}
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);
}
va_end(args);
}
bool cbt_lib_build(struct cbt_lib lib, const char *compiler) {
cbt_log(CBT_LOG_INFO, "library: %s in %s", lib.libname, lib.basepath);
cbt_log(CBT_LOG_INFO, " cflags: %s", cbt_escape_argsd(lib.cflags));
cbt_log(CBT_LOG_INFO, " ldflags: %s", cbt_escape_argsd(lib.ldflags));
cbt_log(CBT_LOG_INFO, " sources: %s", cbt_escape_argsd(lib.sources));
cbt_log(CBT_LOG_INFO, " cc: %s", compiler ? compiler : cbt_cc);
struct cbt_chararray args = {0};
cbt_da_add(args, (char *)(compiler ? compiler : cbt_cc));
cbt_da_merge(args, lib.cflags);
cbt_log(CBT_LOG_INFO, "args.size: %d", args.size);
cbt_log(CBT_LOG_INFO, "CMD: %s", cbt_escape_argsd(args));
CBT_TODO("cbt_lib_build()");
}
void cbt_lib_free(struct cbt_lib lib) {
free(lib.cflags.items);
free(lib.ldflags.items);
for (size_t i = 0; i < lib.sources.size; i++) {
free(lib.sources.items[i]);
}
free(lib.sources.items);
}
struct cbt_binary cbt_binary(const char *out_path);
void _cbt_binary_add_src(struct cbt_binary bin, ...);
bool _cbt_binary_build(struct cbt_binary bin, const char *compiler, ...);
void cbt_binary_free(struct cbt_binary bin);
#undef CBT_TODO
#undef CBT_FAIL #undef CBT_FAIL
//-*- end //-*- end
#endif #endif