From: Trent Huber Date: Fri, 25 Jul 2025 02:53:44 +0000 (-0400) Subject: Scrub, scrub, scrub! X-Git-Url: https://trenthuber.com/code?a=commitdiff_plain;h=47569fbe806a5138763e7ef3447dca254357dff8;p=cbs.git Scrub, scrub, scrub! --- diff --git a/README.md b/README.md index 4e2502c..46d0256 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ cc -o main main.o Hello, world! ``` -Every subsequent time you run `build`, it will rebuild the entire project, including itself. +Every subsequent time you run `build`, it will rebuild the entire project, as well as itself. ```console > build @@ -54,9 +54,9 @@ cbs tries to be as simple as possible, while still remaining powerful. Its simpl void compile(char *src); ``` -The `compile()` function is given a single source file to compile and will generate an object file with the same name. In general, file extensions are unnecessary in your build files as they can usually be inferred based on the function being called. This has the added benefit of being able to reuse lists of file names in both compiling and linking. +The `compile()` function is given a single source file to compile and will generate an object file with the same name. In general, file extensions in your build files are optional as they can usually be inferred based on the function being called. This has the added benefit of being able to reuse lists of file names for compiling and linking. -Before you run `compile()`, the global `cflags` variable has to be initialized with a list of flags to pass to the compiler. If no flags are needed, than the `NONE` macro should be used; otherwise the `LIST()` macro can be used. +Before you run `compile()`, the global `cflags` variable has to be initialized with a list of flags to pass to the compiler. If no flags are needed, than the `NONE` macro should be used; otherwise the `LIST()` macro can be used. The value of `cflags` doesn't change between calls to `compile()`, so the same flags can be used for multiple compilations without having to reinitialize. ```c cflags = LIST("-Wall", "-O3"); @@ -80,18 +80,18 @@ The first argument tells `load()` the type of target file to generate. 'd' - dynamic library ``` -The second argument is the name of the target file. To aid portability, the file extension is optional, as it can be inferred from the target file type. It is also common to prepend `lib` to libraries; this is similarly optional. +The second argument is the name of the target file. For similar reasons to `compile()`, file extensions are optional for the target. Prepending `lib` to library targets is similarly optional. -The third and final argument is a list of object files and libraries that will be linked to create the target file. Here, file extensions *are* required for libraries since they're mixed in with object files. The `LIST()` macro can also be used for this list since it too is expected to be NULL-terminated. +The third argument is a list of object files and libraries that will be linked to create the target file. Here, libraries need to include their file extension so as to disambiguate them from object files. `LIST()` can be used here too since this list must also be NULL-terminated. -Similar to `cflags`, there is a global `lflags` variable used by the linker. +The global `lflags` variable is used to pass flags to the linker, with a behavior identical to `cflags`. ```c lflags = LIST("-lm"); load('s', "main", LIST("first" DYEXT, "second", "third.a")); ``` -`DYEXT` is macro defined to be the platform-specific file extension for dynamic libraries, to aid the portability of build files. +`DYEXT` is a macro defined as the platform-specific file extension for dynamic libraries, to aid the portability of build files. ### Recursive builds diff --git a/cbs.c b/cbs.c index 798b53c..53c44f8 100644 --- a/cbs.c +++ b/cbs.c @@ -32,21 +32,20 @@ void *allocate(size_t s) { } char *extend(char *path, char *ext) { - char *dp, *bp, *e, *r; - size_t d, b, l; + char *bp, *e, *dp, *r; + size_t b, d, l; - bp = (bp = strrchr(dp = path, '/')) ? bp + 1 : dp; - d = bp - dp; + bp = (bp = strrchr(path, '/')) ? bp + 1 : path; b = (e = strrchr(bp, '.')) ? e - bp : (e = ext, strlen(bp)); - if (*ext == '!') e = ++ext; + if (*ext == '!') e = ext + 1; + d = bp - path; if (strcmp(e, DYEXT) == 0) { - path = d ? strndup(dp, d) : strdup("."); - if (!(dp = realpath(path, NULL))) + if (!(dp = realpath(path = d ? strndup(path, d) : strdup("./"), NULL))) err(EXIT_FAILURE, "Unable to get the absolute path of `%s'", path); free(path); d = strlen(dp); dp[d++] = '/'; - } + } else dp = strdup(path); l = (strcmp(e, ".a") == 0 || strcmp(e, DYEXT) == 0) && (b <= 3 || strncmp(bp, "lib", 3) != 0) ? 3 : 0; @@ -56,7 +55,7 @@ char *extend(char *path, char *ext) { strncat(r, bp, b); strcat(r, e); - if (dp != path) free(dp); + free(dp); return r; } @@ -64,11 +63,10 @@ char *extend(char *path, char *ext) { void run(char *file, char **args, char *what, char *who) { size_t i; - if (*file == '!') ++file; - else for (i = 0; args[i]; ++i) { + if (*file != '!') for (i = 0; args[i]; ++i) { fputs(args[i], stdout); putchar(args[i + 1] ? ' ' : '\n'); - } + } else ++file; if (execve(file, args, environ) == -1) err(EXIT_FAILURE, "Unable to %s `%s'", what, who); @@ -79,7 +77,8 @@ 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 (WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS) + if (WIFEXITED(status) && WEXITSTATUS(status) != EXIT_SUCCESS + || WIFSIGNALED(status)) exit(EXIT_FAILURE); } @@ -192,7 +191,6 @@ void build(char *path) { free(absolute); if (leave) return; - if (self || !exists) { c = cflags; l = lflags;