diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-03-10 16:35:48 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-03-10 16:35:48 +0200 |
commit | f0cfa029a6470e0171dbb6d6d5ead7535eb1a803 (patch) | |
tree | d8d5662020594006392d1cc9dbb7de410b795e15 /make.c | |
parent | 146f4d8e25149631f9418c70ab47db77bfca8c42 (diff) |
Add make script
Diffstat (limited to 'make.c')
-rw-r--r-- | make.c | 153 |
1 files changed, 153 insertions, 0 deletions
@@ -0,0 +1,153 @@ +#define _GNU_SOURCE +#include <errno.h> +#include <glob.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define CBS_PTHREAD +#include "cbs.h" + +#define CC "gcc" +#define CFLAGS_ALL WARNINGS, "-pipe", "-std=c23", "-Iinclude" +#define CFLAGS_DBG CFLAGS_ALL, "-g", "-ggdb3", "-Og" +#ifdef __APPLE__ +# define CFLAGS_RLS CFLAGS_ALL, "-O3", "-flto" +#else +# define CFLAGS_RLS \ + CFLAGS_ALL, "-O3", "-flto", "-march=native", "-mtune=native" +#endif +#define LIBNAME "libmlib" +#define WARNINGS \ + "-Wall", "-Wextra", "-Wpedantic", "-Werror", "-Wno-attributes", \ + "-Wno-pointer-sign" + +#define CMDPRC(c) \ + do { \ + int ec; \ + cmdput(c); \ + if ((ec = cmdexec(c)) != EXIT_SUCCESS) \ + diex("%s terminated with exit-code %d", *(c)._argv, ec); \ + cmdclr(&(c)); \ + } while (false) + +#define flagset(o) (flags & (1 << ((o) - 'a'))) +#define streq(x, y) (!strcmp(x, y)) + +static int globerr(const char *, int); +static void work(void *); + +static unsigned long flags; + +int +main(int argc, char **argv) +{ + int opt, procs = -1; + + cbsinit(argc, argv); + rebuild(); + + while ((opt = getopt(argc, argv, "fj:r")) != -1) { + switch (opt) { + case '?': + fprintf(stderr, "Usage: %s [-j procs] [-fr]\n", *argv); + exit(EXIT_FAILURE); + case 'j': + procs = atoi(optarg); + break; + default: + flags |= 1 << (opt - 'a'); + } + } + + argc -= optind; + argv += optind; + + if (argc >= 1) { + if (!streq(*argv, "clean")) { + diex("invalid subcommand ā ā%sā", *argv); + exit(EXIT_FAILURE); + } + cmd_t c = {}; + cmdadd(&c, "find", ".", "(", "-name", "*.[ao]", "-or", "-name", "*.so", + ")", "-delete"); + CMDPRC(c); + } else { + cmd_t c = {}; + glob_t g; + tpool_t tp; + + if (glob("lib/*/*.c", 0, globerr, &g)) + die("glob"); + + if (procs == -1 && (procs = nproc()) == -1) { + if (errno) + die("nproc"); + procs = 8; + } + + tpinit(&tp, procs); + for (size_t i = 0; i < g.gl_pathc; i++) + tpenq(&tp, work, g.gl_pathv[i], nullptr); + tpwait(&tp); + tpfree(&tp); + + for (size_t i = 0; i < g.gl_pathc; i++) + g.gl_pathv[i][strlen(g.gl_pathv[i]) - 1] = 'o'; + + if (flagset('f') + || foutdatedv(LIBNAME ".a", (const char **)g.gl_pathv, g.gl_pathc)) + { + cmdadd(&c, "ar", "rcs", LIBNAME ".a"); + cmdaddv(&c, g.gl_pathv, g.gl_pathc); + CMDPRC(c); + } + + if (flagset('f') + || foutdatedv(LIBNAME ".so", (const char **)g.gl_pathv, g.gl_pathc)) + { + struct strv sv = {}; + env_or_default(&sv, "CC", CC); + cmdaddv(&c, sv.buf, sv.len); + cmdadd(&c, "-shared", "-o", LIBNAME ".so"); + cmdaddv(&c, g.gl_pathv, g.gl_pathc); + CMDPRC(c); + } + + globfree(&g); + } + + return EXIT_SUCCESS; +} + +void +work(void *p) +{ + char *dst, *src = p; + cmd_t c = {}; + struct strv sv = {}; + + if (!(dst = strdup(src))) + die("strdup"); + dst[strlen(dst) - 1] = 'o'; + + if (flagset('f') || foutdated(dst, src)) { + env_or_default(&sv, "CC", CC); + if (flagset('r')) + env_or_default(&sv, "CFLAGS", CFLAGS_RLS); + else + env_or_default(&sv, "CFLAGS", CFLAGS_DBG); + cmdaddv(&c, sv.buf, sv.len); + cmdadd(&c, "-Iinclude", "-fPIC", "-o", dst, "-c", src); + CMDPRC(c); + } + + free(dst); +} + +int +globerr(const char *s, int e) +{ + errno = e; + die("glob: %s", s); +} |