]> Trent Huber's Code - cbs.git/commitdiff
Simplify bootstrapping
authorTrent Huber <trentmhuber@gmail.com>
Wed, 6 Aug 2025 18:17:48 +0000 (14:17 -0400)
committerTrent Huber <trentmhuber@gmail.com>
Wed, 6 Aug 2025 18:17:48 +0000 (14:17 -0400)
README.md
cbs.c

index c1ec22c09cefb850c999d1661908e6bbe2a5c444..7189a3d58dafc2a32df4cc09cebcde1a30779edd 100644 (file)
--- a/README.md
+++ b/README.md
@@ -26,8 +26,6 @@ Next, compile the build file and run the resulting executable, called `build`.
 ```console
 > cc -o build build.c
 > build
-cc -c -o build.o build.c
-cc -o build build.o
 cc -c -o main.o main.c
 cc -o main main.o
 > main
@@ -102,12 +100,8 @@ The `build()` function allows one build executable to run another build executab
 
 If the current directory is passed to `build()`, then it will *recompile its own build file* before rerunning *itself*. Thus, including a statement like `build("./");` at the beginning of your build file means you don't have to manually recompile that build file whenever you modify it.
 
-`build()` uses the `cflags` and `lflags` variables whenever it recompiles build files. The value of each variable is maintained between calls to `build()`.
-
 ```c
 build("./");
 build("../../src/");
-
-cflags = LIST("-Iinclude/");
 build("/usr/local/project/src/");
 ```
diff --git a/cbs.c b/cbs.c
index d5fa83a3330c1ea800447e119e540febc253291b..fcbe83bb7f512baff2815b876fcbc6eb7531f487 100644 (file)
--- a/cbs.c
+++ b/cbs.c
 
 #ifdef __APPLE__
 #define DYEXT ".dylib"
-#define TIME st_mtimespec
+#define SEC st_mtimespec.tv_sec
+#define NSEC st_mtimespec.tv_nsec
 #else
 #define DYEXT ".so"
-#define TIME st_mtim
+#define SEC st_mtim.tv_sec
+#define NSEC st_mtim.tv_nsec
 #endif
 
 #define NONE (char *[]){NULL}
@@ -77,8 +79,7 @@ void await(pid_t cpid, char *what, char *who) {
 
    if (cpid == -1 || waitpid(cpid, &status, 0) == -1)
        err(EXIT_FAILURE, "Unable to %s `%s'", what, who);
-   if (WIFSIGNALED(status))
-       errx(EXIT_FAILURE, "%s", strsignal(WTERMSIG(status)));
+   if (WIFSIGNALED(status)) errx(EXIT_FAILURE, "%s", strsignal(WTERMSIG(status)));
    if (WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS)
        exit(EXIT_FAILURE);
 }
@@ -149,20 +150,11 @@ void load(char type, char *target, char **objs) {
    free(args);
 }
 
-int after(struct stat astat, struct stat bstat) {
-   struct timespec a, b;
-
-   a = astat.TIME;
-   b = bstat.TIME;
-
-   return a.tv_sec == b.tv_sec ? a.tv_nsec > b.tv_nsec : a.tv_sec > b.tv_sec;
-}
-
 void build(char *path) {
    char *absolute, *current;
    pid_t cpid;
-   int self, exists, restart;
-   struct stat src, obj, exe;
+   int self, exists, rebuild;
+   struct stat src, exe;
 
    if (!(absolute = realpath(path, NULL)))
        err(EXIT_FAILURE, "Unable to resolve `%s'", path);
@@ -185,18 +177,15 @@ void build(char *path) {
 
    if (cpid) return;
 
-   if (stat(current = "build.c", &src) == -1)
-       err(EXIT_FAILURE, "Unable to stat `build.c'");
-   if (stat("build.o", &obj) == -1) obj.TIME = (struct timespec){0};
-   if (!(exists = stat("build", &exe) != -1)) exe.TIME = (struct timespec){0};
-
-   if ((restart = after(src, obj) || after(exe, obj))
-       && after(src, exe) && (self || !exists)) {
+   if (stat("build.c", &src) == -1) err(EXIT_FAILURE, "Unable to stat `build.c'");
+   if (!(exists = stat("build", &exe) != -1)) exe.SEC = 0;
+   rebuild = src.SEC == exe.SEC ? src.NSEC > exe.NSEC : src.SEC > exe.SEC;
+   
+   if (!self && !exists || self && rebuild) {
        compile("build");
        load('x', "build", LIST("build"));
-       if (self) current = "build.o";
    }
-   if (utimensat(AT_FDCWD, current, NULL, 0) == -1)
-       err(EXIT_FAILURE, "Unable to update `%s' modification time", current);
-   if (restart) run("!build", LIST("build"), "run", "build");
+   if (!self || rebuild) run("!build", LIST("build"), "run", "build");
+   if (utimensat(AT_FDCWD, "build.c", NULL, 0) == -1)
+       err(EXIT_FAILURE, "Unable to update `build.c' modification time");
 }