tbd: library definitions
This commit is contained in:
parent
fed1c0a3ca
commit
cdacf0868b
13
cbt.c
13
cbt.c
|
@ -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
|
||||
#include "cbt.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CBT_INIT(argc, argv);
|
||||
|
||||
struct cbt_proc proc =
|
||||
cbt_proc_new(CBT_PROC_NORMAL, "sh", "-c", "echo 'owo'");
|
||||
cbt_proc_wait(proc);
|
||||
cbt_shell(CBT_PROC_AUTO, "sh", "-c", "echo 'owo'");
|
||||
|
||||
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();
|
||||
return 0;
|
||||
|
|
211
cbt.h
211
cbt.h
|
@ -15,9 +15,14 @@ enum cbt_loglevel {
|
|||
CBT_LOG_ALL
|
||||
};
|
||||
|
||||
struct cbt_chararray {
|
||||
char **items;
|
||||
size_t size, cap;
|
||||
};
|
||||
|
||||
extern long cbt_start_time;
|
||||
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_cleanup(void);
|
||||
|
@ -27,11 +32,15 @@ extern const char *cbt_log__colors[CBT_LOG_ALL + 1];
|
|||
extern const char *cbt_log__typecolors[8];
|
||||
|
||||
void cbt_log(enum cbt_loglevel lvl, const char *fmt, ...);
|
||||
|
||||
long cbt_get_time(void);
|
||||
|
||||
unsigned long cbt_get_modtime(const char *filename);
|
||||
bool cbt_needs_recompilation(const char *input, const char *output);
|
||||
|
||||
const char *cbt_escape_shell(char *arg);
|
||||
const char *cbt_escape_args(char **args);
|
||||
const char *cbt_escape_argsd(struct cbt_chararray arr);
|
||||
|
||||
#ifndef CBT_FMT_NBUFS
|
||||
#define CBT_FMT_NBUFS 64
|
||||
|
@ -43,11 +52,6 @@ const char *cbt_escape_args(char **args);
|
|||
|
||||
const char *cbt_fmt(const char *fmt, ...);
|
||||
|
||||
struct cbt_proc_args {
|
||||
char **items;
|
||||
size_t size, cap;
|
||||
};
|
||||
|
||||
struct cbt_proc {
|
||||
FILE *fp_stdin, *fp_stdout, *fp_stderr;
|
||||
int pid;
|
||||
|
@ -56,20 +60,53 @@ struct cbt_proc {
|
|||
struct cbt_procgroup {
|
||||
struct cbt_proc *items;
|
||||
size_t size, cap;
|
||||
bool fixed_size;
|
||||
};
|
||||
|
||||
enum cbt_proc_mode {
|
||||
CBT_PROC_NORMAL = 0,
|
||||
CBT_PROC_AUTO = 0,
|
||||
CBT_PROC_R = 1,
|
||||
CBT_PROC_W = 2,
|
||||
CBT_PROC_RW = 3,
|
||||
};
|
||||
|
||||
#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_newv(enum cbt_proc_mode mode, va_list args);
|
||||
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]))
|
||||
|
||||
#ifndef CBT_REALLOC
|
||||
|
@ -95,11 +132,30 @@ int cbt_proc_wait(struct cbt_proc proc);
|
|||
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
|
||||
//-*- begin cbt_impl.c 5
|
||||
#define __USE_GNU
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <glob.h>
|
||||
#include <libgen.h>
|
||||
#include <linux/limits.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
@ -119,8 +175,17 @@ int cbt_proc_wait(struct cbt_proc proc);
|
|||
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;
|
||||
char *cbt_cc = NULL;
|
||||
char cbt_location[PATH_MAX] = {0};
|
||||
char *cbt_cache_dir = NULL;
|
||||
long cbt_start_time = 0;
|
||||
bool cbt_running = false;
|
||||
|
||||
|
@ -137,9 +202,9 @@ struct _cbt__autoproc_set {
|
|||
size_t size, cap;
|
||||
} 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;
|
||||
|
||||
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;
|
||||
(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)
|
||||
cbt_cc = getenv("CC");
|
||||
|
@ -162,24 +227,35 @@ void cbt__init(int argc, char **argv, const char *source_file) {
|
|||
cbt_cc = "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, "%s", cbt_fmt("format test: %s", "ok"));
|
||||
|
||||
cbt__default_procgroup.items =
|
||||
calloc(cbt__default_procgroup.cap, sizeof(struct cbt_proc));
|
||||
cbt_log(CBT_LOG_INFO, "Cache dir: %s", cbt_cache_dir);
|
||||
|
||||
cbt__proc_pool.items = calloc(cbt__proc_pool.cap, sizeof(struct cbt_proc));
|
||||
|
||||
{
|
||||
cbt_log(CBT_LOG_DEBUG, "Starting line processor thread");
|
||||
|
||||
int err;
|
||||
if ((err = pthread_create(&_cbt__autoproc_thread, NULL, cbt__line_processor, NULL)) != 0) {
|
||||
cbt_log(CBT_LOG_ERROR, "pthread_create() failed for line processor: %d", err);
|
||||
if ((err = pthread_create(&cbt__autoproc_thread, NULL, cbt__line_processor,
|
||||
NULL)) != 0) {
|
||||
cbt_log(CBT_LOG_ERROR, "pthread_create() failed for line processor: %d",
|
||||
err);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (cbt_needs_recompilation(source_file, argv[0])) {
|
||||
cbt_log(CBT_LOG_INFO, "Recompiling...");
|
||||
struct cbt_proc cc = cbt_proc_new(CBT_PROC_NORMAL, cbt_cc, source_file,
|
||||
"-o", argv[0], "-Wall", "-Wextra", NULL);
|
||||
struct cbt_proc cc = cbt_proc_new(CBT_PROC_AUTO, cbt_cc, source_file, "-o",
|
||||
argv[0], "-Wall", "-Wextra", NULL);
|
||||
int status = cbt_proc_wait(cc);
|
||||
cbt_log(CBT_LOG_INFO, "CC returned %d", status);
|
||||
if (status == 0) {
|
||||
|
@ -196,7 +272,7 @@ void cbt_cleanup(void) {
|
|||
pthread_mutex_lock(&_cbt__autoproc_mut);
|
||||
cbt_running = false;
|
||||
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);
|
||||
cbt_log(CBT_LOG_INFO, "shutdown complete");
|
||||
}
|
||||
|
@ -279,6 +355,18 @@ const char *cbt_escape_args(char **args) {
|
|||
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) {
|
||||
struct stat 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 procinfo = {0};
|
||||
|
||||
struct cbt_proc_args args_da = {0};
|
||||
struct cbt_chararray args_da = {0};
|
||||
while (true) {
|
||||
const char *arg = va_arg(args, const char *);
|
||||
if (arg == NULL)
|
||||
|
@ -469,6 +557,91 @@ void *cbt__line_processor(void *arg) {
|
|||
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
|
||||
//-*- end
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue