diff options
Diffstat (limited to 'make.c')
-rw-r--r-- | make.c | 226 |
1 files changed, 226 insertions, 0 deletions
@@ -0,0 +1,226 @@ +#include <assert.h> +#include <getopt.h> +#include <glob.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define CBS_NO_THREADS +#include "cbs.h" + +static void cc(void *); +static void ld(void); +static int globerr(const char *, int); + +static char *warnings[] = { + "-Wall", + "-Wextra", + "-Wpedantic", + "-Wno-parentheses", +}; + +static char *cflags_all[] = { + "-std=c11", +#if __GLIBC__ + "-D_GNU_SOURCE", +#endif +}; + +static char *cflags_dbg[] = { + "-g3", + "-ggdb3", + "-O0", +}; + +static char *cflags_rls[] = { + "-DNDEBUG=1", + "-flto", + "-fomit-frame-pointer", + "-march=native", + "-mtune=native", + "-O3", +}; + +static const char *argv0; +static bool fflag, Sflag, rflag; +static char *oflag = "totp", *pflag = "generic"; + +static void +usage(void) +{ + fprintf(stderr, + "Usage: %s [-p generic|x64] [-fSr]\n" + " %s clean\n", + argv0, argv0); + exit(EXIT_FAILURE); +} + +int +main(int argc, char **argv) +{ + cbsinit(argc, argv); + rebuild(); + + argv0 = argv[0]; + + int opt; + static const struct option longopts[] = { + {"force", no_argument, 0, 'f'}, + {"no-sanitizer", no_argument, 0, 'S'}, + {"output", required_argument, 0, 'o'}, + {"profile", required_argument, 0, 'p'}, + {"release", no_argument, 0, 'r'}, + {0}, + }; + + while ((opt = getopt_long(argc, argv, "fSo:p:r", longopts, NULL)) != -1) { + switch (opt) { + case 'f': + fflag = true; + break; + case 'r': + rflag = true; + /* fallthrough */ + case 'S': + Sflag = true; + break; + case 'o': + oflag = strdup(optarg); + assert(oflag != NULL); + break; + case 'p': + if (strcmp(optarg, "generic") == 0 || strcmp(optarg, "x64") == 0) { + pflag = strdup(optarg); + assert(pflag != NULL); + } else { + fprintf(stderr, "%s: invalid profile -- '%s'\n", argv0, optarg); + usage(); + } + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; + + if (argc > 1) + usage(); + if (argc == 1) { + if (strcmp(argv[0], "clean") != 0) { + fprintf(stderr, "%s: invalid subcommand -- '%s'\n", argv0, *argv); + usage(); + } + struct strs cmd = {0}; + strspushl(&cmd, "find", ".", + "(", + "-name", "totp", + "-or", "-name", "totp-*", + "-or", "-name", "*.o", + ")", "-delete" + ); + cmdput(cmd); + return cmdexec(cmd); + } + + glob_t g; + assert(glob("src/*.c", 0, globerr, &g) == 0); + + char *ext = malloc(strlen(pflag) + sizeof("-.c")); + assert(ext != NULL); + sprintf(ext, "-%s.c", pflag); + + for (size_t i = 0; i < g.gl_pathc; i++) { + if (strchr(g.gl_pathv[i], '-') != NULL + && strstr(g.gl_pathv[i], ext) == NULL) + { + continue; + } + cc(g.gl_pathv[i]); + } + + globfree(&g); + + ld(); +} + +void +cc(void *arg) +{ + struct strs cmd = {0}; + char *dst = swpext(arg, "o"), *src = arg; + + if (!fflag && fmdnewer(dst, src)) + goto out; + + strspushenvl(&cmd, "CC", "cc"); + strspush(&cmd, cflags_all, lengthof(cflags_all)); + if (rflag) + strspushenv(&cmd, "CFLAGS", cflags_rls, lengthof(cflags_rls)); + else { + strspushenv(&cmd, "CFLAGS", cflags_dbg, lengthof(cflags_dbg)); + if (strstr(arg, "-x64.c") != NULL) + strspushl(&cmd, "-msha", "-mssse3"); + } + if (!Sflag) + strspushl(&cmd, "-fsanitize=address,undefined"); + strspushl(&cmd, "-o", dst, "-c", src); + + cmdput(cmd); + cmdexec(cmd); + strsfree(&cmd); +out: + free(dst); +} + +void +ld(void) +{ + glob_t g; + bool dobuild = fflag; + struct strs cmd = {0}; + + strspushenvl(&cmd, "CC", "cc"); + strspush(&cmd, cflags_all, lengthof(cflags_all)); + if (rflag) + strspushenv(&cmd, "CFLAGS", cflags_rls, lengthof(cflags_rls)); + else + strspushenv(&cmd, "CFLAGS", cflags_dbg, lengthof(cflags_dbg)); + if (!Sflag) + strspushl(&cmd, "-fsanitize=address,undefined"); + strspushl(&cmd, "-o", oflag); + + assert(glob("src/*.o", 0, globerr, &g) == 0); + + char *ext = malloc(strlen(pflag) + sizeof("-.o")); + assert(ext != NULL); + sprintf(ext, "-%s.o", pflag); + + for (size_t i = 0; i < g.gl_pathc; i++) { + if (strchr(g.gl_pathv[i], '-') != NULL + && strstr(g.gl_pathv[i], ext) == NULL) + { + continue; + } + if (fmdolder("totp", g.gl_pathv[i])) + dobuild = true; + strspushl(&cmd, g.gl_pathv[i]); + } + + if (dobuild) { + cmdput(cmd); + cmdexec(cmd); + } + + globfree(&g); + strsfree(&cmd); +} + +int +globerr(const char *s, int e) +{ + fprintf(stderr, "glob: %s: %s\n", s, strerror(e)); + exit(EXIT_FAILURE); +} |