aboutsummaryrefslogtreecommitdiff
path: root/make.c
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-03-10 16:35:48 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-03-10 16:35:48 +0200
commitf0cfa029a6470e0171dbb6d6d5ead7535eb1a803 (patch)
treed8d5662020594006392d1cc9dbb7de410b795e15 /make.c
parent146f4d8e25149631f9418c70ab47db77bfca8c42 (diff)
Add make script
Diffstat (limited to 'make.c')
-rw-r--r--make.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/make.c b/make.c
new file mode 100644
index 0000000..3be57c2
--- /dev/null
+++ b/make.c
@@ -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);
+}