]> git.mdlowis.com Git - proto/aos.git/commitdiff
rework build system and adjust style of functions
authorMichael D. Lowis <mike@mdlowis.com>
Sun, 6 Dec 2020 01:16:15 +0000 (20:16 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Sun, 6 Dec 2020 01:16:15 +0000 (20:16 -0500)
12 files changed:
.gitignore
build.c [new file with mode: 0644]
build.sh [new file with mode: 0755]
inc/libui_impl.h [moved from lib/ui/libui_impl.h with 100% similarity]
lib/a/ecalloc.c
lib/a/efopen.c
lib/a/efreadline.c
lib/a/emalloc.c
lib/a/eraise.c
lib/a/erealloc.c
lib/a/esignal.c
lib/a/fatal.c

index 567609b1234a9b8806c5a05da6c866e480aa148d..26fa21f12f10e874b1d98db051eb806dd1c25cd7 100644 (file)
@@ -1 +1,2 @@
 build/
+build.bin
diff --git a/build.c b/build.c
new file mode 100644 (file)
index 0000000..75fa30a
--- /dev/null
+++ b/build.c
@@ -0,0 +1,388 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+enum { F_FILES, F_DIRS };
+
+typedef struct Target {
+    struct Target* next;
+    char** outputs;
+    char** inputs;
+    void (*build)(struct Target*);
+} Target;
+
+int MaxJobs = 4;
+
+char* CCCMD[] = {
+    "cc",
+    "-Wall", "-Wextra", "-Werror",
+    "-Iinc/",
+    "-I/usr/X11/include/",
+    "-I/usr/X11/include/freetype2",
+    "-c", "-o",
+    /* output */
+    /* inputs */
+    NULL
+};
+
+char* ARCMD[] = {
+    "ar", "rcs",
+    NULL
+};
+
+char* LDCMD[] = {
+    "cc",
+    "-L./build/lib",
+    "-L/usr/X11/lib/",
+    "-o",
+    /* output */
+    /* inputs */
+    /* LIBS */
+    NULL
+};
+
+char* LIBS[] = {
+    "-lX11",
+    "-lfontconfig",
+    NULL
+};
+
+Target* Srcs = NULL;
+Target* Libs = NULL;
+Target* Bins = NULL;
+
+/*
+    Helper Routines
+*/
+
+static char* strmcat(char* first, ...)
+{
+    va_list args;
+    /* calculate the length of the final string */
+    size_t len = strlen(first);
+    va_start(args, first);
+    for (char* s = NULL; (s = va_arg(args, char*));)
+    {
+        len += strlen(s);
+    }
+    va_end(args);
+    /* allocate the final string and copy the args into it */
+    char *str  = malloc(len+1), *curr = str;
+    while (first && *first)
+    {
+        *(curr++) = *(first++);
+    }
+    va_start(args, first);
+    for (char* s = NULL; (s = va_arg(args, char*));)
+    {
+        while (s && *s)
+        {
+            *(curr++) = *(s++);
+        }
+    }
+    va_end(args);
+    /* null terminate and return */
+    *curr = '\0';
+    return str;
+}
+
+static char** dir_entries(char* path, int flags)
+{
+    size_t nentries = 0;
+    char** entries = calloc(1, sizeof(char*));
+    struct dirent* entry = NULL;
+    struct stat attrs = {0};
+
+    DIR* dir = opendir(path);
+    while ( (entry = readdir(dir)) )
+    {
+        if (entry->d_name[0] == '.') continue;
+        char* epath = strmcat(path, "/", entry->d_name, 0);
+        memset(&attrs, 0, sizeof(attrs));
+        stat(epath, &attrs);
+        if ( ((flags == F_FILES) && !S_ISDIR(attrs.st_mode)) ||
+             ((flags == F_DIRS) && S_ISDIR(attrs.st_mode)) )
+        {
+            entries = realloc(entries, (nentries+2)*sizeof(char*));
+            entries[nentries++] = epath;
+            entries[nentries] = NULL;
+        }
+    }
+
+    return entries;
+}
+
+char** make_cmd(char*** cmd_parts)
+{
+    size_t count = 0;
+    char** cmd = NULL;
+    for (; *cmd_parts; cmd_parts++)
+    {
+        char** subpart = *cmd_parts;
+        for (; *subpart; subpart++)
+        {
+            cmd = realloc(cmd, ++count * sizeof(char*));
+            cmd[count-1] = *subpart;
+        }
+    }
+    cmd = realloc(cmd, ++count * sizeof(char*));
+    cmd[count-1] = NULL;
+    return cmd;
+}
+
+void print_cmd(char** cmd)
+{
+    for (; *cmd; cmd++)
+    {
+        printf("%s ", *cmd);
+    }
+    puts("");
+}
+
+int wait_for_jobs(int count)
+{
+    int ret_status = 0;
+    do
+    {
+        int status = 0;
+        waitpid(-1, &status, 0);
+        if (WIFEXITED(status))
+        {
+            count--;
+        }
+        int exitcode = WEXITSTATUS(status);
+        ret_status = (!ret_status ? exitcode : ret_status);
+    }
+    while (count > 0);
+    return ret_status;
+}
+
+void make_dirs(char** outputs)
+{
+    for (; *outputs; outputs++)
+    {
+        char* out = strdup(*outputs);
+        char* slash = strrchr(out, '/');
+        if (slash)
+        {
+            *slash = '\0';
+            mkdir(out, 0755);
+        }
+    }
+}
+
+time_t timestamp(char* path)
+{
+    struct stat s;
+    time_t mtime = 0;
+    if (!stat(path, &s))
+    {
+        mtime = s.st_mtime;
+    }
+    return mtime;
+}
+
+int should_rebuild(char** outputs, char** inputs)
+{
+    time_t mtime = 0;
+    for (; *outputs; outputs++)
+    {
+        time_t mt = timestamp(*outputs);
+        mtime = (mt > mtime ? mt : mtime);
+    }
+    for (; *inputs; inputs++)
+    {
+        time_t mt = timestamp(*inputs);
+        if (mt > mtime)
+        {
+            return 1; /* rebuild! */
+        }
+    }
+    return 0; /* no need to rebuild */
+}
+
+/*
+    Build Routines
+*/
+
+void object(Target* tgt)
+{
+    printf("Object %s\n", tgt->outputs[0]);
+    char** cmd = make_cmd((char**[]){ CCCMD, tgt->outputs, tgt->inputs, NULL });
+    make_dirs(tgt->outputs);
+    exit(execvp(cmd[0], cmd));
+}
+
+void library(Target* tgt)
+{
+    printf("Library %s\n", tgt->outputs[0]);
+    char** cmd = make_cmd((char**[]){ ARCMD, tgt->outputs, tgt->inputs, NULL });
+    exit(execvp(cmd[0], cmd));
+}
+
+void binary(Target* tgt)
+{
+    printf("Binary %s\n", tgt->outputs[0]);
+    char** cmd = make_cmd((char**[]){
+        LDCMD, tgt->outputs, tgt->inputs, LIBS, NULL });
+    exit(execvp(cmd[0], cmd));
+}
+
+/*
+    Target List Routines
+*/
+
+void add_target(Target** list, char** outputs, char** inputs, void (*build)(Target*))
+{
+    Target* tgt = calloc(1, sizeof(Target));
+    tgt->next = *list;
+    tgt->outputs = outputs;
+    tgt->inputs = inputs;
+    tgt->build = build;
+    *list = tgt;
+}
+
+/*
+    Target Routines
+*/
+
+char* add_src(char* src)
+{
+    char* obj = strmcat("build/obj/", src, 0);
+    obj[strlen(obj)-1] = 'o';
+    char** outputs = calloc(2, sizeof(char*));
+    outputs[0] = obj;
+    char** inputs = calloc(2, sizeof(char*));
+    inputs[0] = src;
+    add_target(&Srcs, outputs, inputs, object);
+    return obj;
+}
+
+char* add_lib(char* path, char** srcs)
+{
+    char* libname = strrchr(path, '/') + 1;
+    char* lib = strmcat("build/lib/lib", libname, ".a", 0);
+    char** outputs = calloc(2, sizeof(char*));
+    outputs[0] = lib;
+    add_target(&Libs, outputs, srcs, library);
+    return lib;
+}
+
+char* add_bin(char* path, char** srcs)
+{
+    char* binname = strdup(strrchr(path, '/') + 1);
+    char* ext = strrchr(binname, '.');
+
+    if (ext)
+    {
+        *ext = '\0';
+    }
+    char* bin = strmcat("build/bin/", binname, 0);
+    char** outputs = calloc(2, sizeof(char*));
+    outputs[0] = bin;
+    add_target(&Bins, outputs, srcs, binary);
+
+    return bin;
+}
+
+char** add_srcs(char* path)
+{
+    char** srcs = dir_entries(path, F_FILES);
+    for (char** s = srcs; *s; s++)
+    {
+        char* obj = add_src(*s);
+        *s = obj;
+    }
+
+    return srcs;
+}
+
+/*
+    Build Routines
+*/
+
+void build_targets(Target* targets)
+{
+    int exitcode = 0;
+    int count = 0;
+
+    for (; !exitcode && targets; targets = targets->next)
+    {
+        count++;
+        int pid = fork();
+        if (pid == 0)
+        {
+            if (should_rebuild(targets->outputs, targets->inputs))
+            {
+                targets->build(targets);
+            }
+            exit(0);
+        }
+        else if (count >= MaxJobs)
+        {
+            int code = wait_for_jobs(1);
+            exitcode = (!exitcode ? code : exitcode);
+            count--;
+        }
+    }
+    int code = wait_for_jobs(count);
+    exitcode = (!exitcode ? code : exitcode);
+
+    if (exitcode)
+    {
+        printf("Job Failed!\n");
+        exit(exitcode);
+    }
+}
+
+/*
+    Main Routine
+*/
+
+int main(int argc, char** argv)
+{
+    (void)argc, (void)argv;
+
+    /* register all of the libraries */
+    char** libs = dir_entries("lib", F_DIRS);
+    for (; *libs; libs++)
+    {
+        char** srcs = add_srcs(*libs);
+        add_lib(*libs, srcs);
+    }
+
+    /* register all the complex binaries */
+    char** cbins = dir_entries("bin", F_DIRS);
+    for (; *cbins; cbins++)
+    {
+        char** srcs = add_srcs(*cbins);
+        add_bin(*cbins, srcs);
+    }
+
+    /* register all the simple binaries */
+    char** sbins = dir_entries("bin", F_FILES);
+    for (; *sbins; sbins++)
+    {
+        add_bin(*sbins, (char*[]){ *sbins, NULL });
+    }
+
+    /* create output directories */
+    mkdir("build/", 0755);
+    mkdir("build/obj/", 0755);
+    mkdir("build/obj/bin/", 0755);
+    mkdir("build/obj/lib/", 0755);
+    mkdir("build/bin/", 0755);
+    mkdir("build/lib/", 0755);
+
+    /* now build all of the things */
+    build_targets(Srcs);
+    build_targets(Libs);
+    build_targets(Bins);
+
+    return 0;
+}
\ No newline at end of file
diff --git a/build.sh b/build.sh
new file mode 100755 (executable)
index 0000000..064ecc5
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if [ "build.c" -nt "build.bin" ]; then
+  cc -Wall -Wextra -Werror -o build.bin build.c
+fi
+./build.bin
\ No newline at end of file
similarity index 100%
rename from lib/ui/libui_impl.h
rename to inc/libui_impl.h
index af75b3a10734bf9032770c86145fc19c40bdee27..c4b2a31e424240e67c4bce35ce8127c7f8ae93e5 100644 (file)
@@ -5,6 +5,8 @@ void* ecalloc(size_t num, size_t size)
 {
     void* ret;
     if (NULL == (ret = calloc(num,size)))
+    {
         fatal("calloc(%zu, %zu) failed:", num, size);
+    }
     return ret;
 }
index 1d6e01ebc0b66325e79d82145f1e460a1ae17489..7b900f31b36011e2bd16be8584e20d10671a3398 100644 (file)
@@ -6,6 +6,8 @@ FILE* efopen(const char* filename, const char* mode)
     FILE* file;
     errno = 0;
     if (NULL == (file = fopen(filename, mode)) || errno != 0)
+    {
         fatal("fopen(%s, %s) failed:", filename, mode);
+    }
     return file;
 }
index 0fc3a9fd4eeaee57e9c791b8bde2b003555fda90..b2069f0981a61977ccbd6dbc204644d4cac657bd 100644 (file)
@@ -5,22 +5,31 @@ char* efreadline(FILE* input)
 {
     size_t size  = 8;
     size_t index = 0;
-    char*  str   = (char*)emalloc(size);
+    char*  str = (char*)emalloc(size);
     memset(str, 0, 8);
-    if (feof(input)) {
+    if (feof(input))
+    {
         free(str);
         return NULL;
     }
-    while (true) {
+    while (true)
+    {
         char ch = fgetc(input);
-        if (ch == EOF) break;
+        if (ch == EOF)
+        {
+            break;
+        }
         str[index++] = ch;
         str[index]   = '\0';
-        if (index+1 >= size) {
+        if (index+1 >= size)
+        {
             size = size << 1;
             str  = erealloc(str, size);
         }
-        if (ch == '\n') break;
+        if (ch == '\n')
+        {
+            break;
+        }
     }
     return str;
 }
index c4e61e221b4176720d442f0c783c9d3c4f3bafae..ea9f6c197c4c8af31debf6bc43431825b18d4a17 100644 (file)
@@ -5,6 +5,8 @@ void* emalloc(size_t size)
 {
     void* ret;
     if (NULL == (ret = malloc(size)))
+    {
         fatal("malloc(%zu) failed:", size);
+    }
     return ret;
 }
index 25c53daa4cafacb824bb42019a397c0dd4a91257..7c45dd44e6e69efc36a5dfa67740b7f2a35730c7 100644 (file)
@@ -5,6 +5,8 @@ int eraise(int sig)
 {
     int ret;
     if ((ret = raise(sig)) != 0)
+    {
         fatal("raise(%d) failed:", sig);
+    }
     return ret;
 }
index 929ac017f8ba2735fe8e3dc59fbc6accb2acf412..cf9af0135a5192513b515dc2ea47ba2ab440ac0f 100644 (file)
@@ -5,6 +5,8 @@ void* erealloc(void* ptr, size_t size)
 {
     void* ret;
     if (NULL == (ret = realloc(ptr,size)))
+    {
         fatal("realloc(%p, %zu) failed:", ptr, size);
+    }
     return ret;
 }
index 23f6a201f8f2626e12cedddb8145b91f5991404b..7231f514ecbcfb71e587d98494730ca445877be7 100644 (file)
@@ -6,5 +6,7 @@ void esignal(int sig, void (*func)(int))
     errno = 0;
     func  = signal(sig, func);
     if (func == SIG_ERR || errno > 0)
+    {
         fatal("signal(%d, %p) failed:", sig, func);
+    }
 }
index 539a90d8f24eb2eb66c890360979614e5ec7fb30..3e5d08e12d9eddf70e38159ebc7ee018c9d7a4a0 100644 (file)
@@ -4,14 +4,18 @@
 void fatal(const char* fmt, ...)
 {
     fflush(stdout);
-    if (ARGV0) fprintf(stderr, "%s: ", ARGV0);
+    if (ARGV0)
+    {
+        fprintf(stderr, "%s: ", ARGV0);
+    }
     va_list args;
     va_start(args, fmt);
     vfprintf(stderr, fmt, args);
     va_end(args);
     if (*fmt && fmt[strlen(fmt)-1] == ':')
+    {
         fprintf(stderr, " %s", strerror(errno));
+    }
     fprintf(stderr, "\n");
     exit(EXIT_FAILURE);
 }
-