#define _GNU_SOURCE
#include <errno.h>
#include <glob.h>
#include <libgen.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define CBS_PTHREAD
#include "cbs.h"
#define CC "cc"
#define WARNINGS "-Wall", "-Wextra", "-Wpedantic", "-Werror", "-Wno-attributes"
#define CFLAGS_ALL WARNINGS, "-pipe", "-std=c2x"
#define CFLAGS_DBG CFLAGS_ALL, "-g", "-ggdb3", "-Og"
#ifdef __APPLE__
# define CFLAGS_RLS CFLAGS_ALL, "-O3"
#else
# define CFLAGS_RLS CFLAGS_ALL, "-O3", "-march=native", "-mtune=native"
#endif
#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 (0)
#define streq(a, b) (!strcmp(a, b))
#define flagset(o) (flags & (1 << ((o) - 'a')))
static void work(void *);
static int globerr(const char *, int);
static uint32_t flags;
int
main(int argc, char **argv)
{
int opt;
cbsinit(argc, argv);
rebuild();
while ((opt = getopt(argc, argv, "flr")) != -1) {
switch (opt) {
case '?':
fprintf(stderr, "Usage: %s [-flr]\n", *argv);
exit(EXIT_FAILURE);
default:
flags |= 1 << (opt - 'a');
}
}
argc -= optind;
argv += optind;
if (argc >= 1) {
if (streq(*argv, "clean")) {
cmd_t c = {0};
cmdadd(&c, "find", ".", "-name", "*.[ao]", "-delete");
cmdprc(c);
} else {
diex("invalid subcommand -- '%s'", *argv);
exit(EXIT_FAILURE);
}
} else {
cmd_t c = {0};
size_t n;
glob_t g;
tpool_t tp;
if (glob("lib/*/*.c", 0, globerr, &g))
die("glob");
if ((n = nproc()) == -1) {
if (errno)
die("nproc");
n = 8;
}
tpinit(&tp, n);
for (size_t i = 0; i < g.gl_pathc; i++)
tpenq(&tp, work, g.gl_pathv[i], NULL);
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("librune.a", (const char **)g.gl_pathv, g.gl_pathc))
{
cmdadd(&c, "ar", "rcs", "librune.a");
cmdaddv(&c, g.gl_pathv, g.gl_pathc);
cmdprc(c);
}
globfree(&g);
}
return EXIT_SUCCESS;
}
void
work(void *p)
{
cmd_t c = {0};
char *dst, *src = p;
struct strv sv = {0};
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);
if (flagset('l'))
cmdadd(&c, "-flto");
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);
}