From: Trent Huber Date: Wed, 23 Jul 2025 01:49:19 +0000 (-0400) Subject: Added NONE macro X-Git-Url: https://trenthuber.com/code?a=commitdiff_plain;h=439b76ac2eac74b109b31f0bda1bb8aece31440b;p=cbs.git Added NONE macro --- diff --git a/README.md b/README.md index 17f8f0f..d1b92ea 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,10 @@ To build a project, you first need to make a file called `build.c` which describ int main(void) { build("./"); + cflags = NONE; compile("main"); + lflags = NONE; load('x', "main", LIST("main")); return EXIT_SUCCESS; @@ -44,7 +46,7 @@ cc -o main main.o ``` ## Detailed usage -cbs tries to be as simple as possible, while still remaining powerful. Its simplicity is rooted in its intentionally limited scope to just build C projects. Thus, cbs just needs to worry about compiling and linking C code, and calling other build executables. +cbs tries to be as simple as possible, while still remaining powerful. Its simplicity is rooted in its intentionally limited scope of only building C projects. Thus, cbs only needs to compile and link C code, as well as call other build executables. ### Compiling source files @@ -54,7 +56,7 @@ 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. -To define flags for the compiler to use, you can set the global `cflags` variable to a list of strings of flags. This list is expected to be NULL-terminated, an easy thing to forget, so a simple C macro has been defined to avoid the issue altogether. +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. ```c cflags = LIST("-Wall", "-O3"); @@ -82,14 +84,14 @@ The second argument is the name of the target file. To aid portability, the file 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. -Similar to the global `cflags` variable, there is a global `lflags` variable used by the linker. +Similar to `cflags`, there is a global `lflags` variable used by the linker. ```c lflags = LIST("-lm"); load('s', "main", LIST("first" DYEXT, "second", "third.a")); ``` -`DYEXT` is another macro defined as the platform-specific file extension for dynamic libraries, this time to aid the portability of build files. +`DYEXT` is macro defined to be 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 2ae59c4..fa4b22e 100644 --- a/cbs.c +++ b/cbs.c @@ -14,6 +14,7 @@ #define DYEXT ".so" #endif +#define NONE (char *[]){NULL} #define LIST(...) (char *[]){__VA_ARGS__, NULL} extern char **environ; @@ -32,9 +33,7 @@ char *extend(char *path, char *ext) { char *dp, *bp, *e, *r; size_t d, b, l; - if (!(dp = path)) return NULL; - - bp = (bp = strrchr(dp, '/')) ? bp + 1 : dp; + bp = (bp = strrchr(dp = path, '/')) ? bp + 1 : dp; d = bp - dp; b = (e = strrchr(bp, '.')) ? e - bp : (e = ext, strlen(bp)); if (*ext == '!') e = ++ext; @@ -63,10 +62,11 @@ char *extend(char *path, char *ext) { void run(char *file, char **args, char *what, char *who) { size_t i; - if (*args) for (i = 0; args[i]; ++i) { + if (*file == '!') ++file; + else for (i = 0; args[i]; ++i) { fputs(args[i], stdout); putchar(args[i + 1] ? ' ' : '\n'); - } else ++args; + } if (execve(file, args, environ) == -1) err(EXIT_FAILURE, "Unable to %s `%s'", what, who); @@ -83,24 +83,24 @@ void await(pid_t cpid, char *what, char *who) { void compile(char *src) { size_t f; - char **args, **p; + char **args, **p, *obj; pid_t cpid; - f = 0; - if (cflags) while (cflags[f]) ++f; + for (f = 0; cflags[f]; ++f); p = args = allocate((2 + f + 3 + 1) * sizeof*args); *p++ = "cc"; *p++ = "-c"; - if (cflags) for (f = 0; cflags[f]; *p++ = cflags[f++]); + for (f = 0; cflags[f]; *p++ = cflags[f++]); *p++ = "-o"; - *p++ = extend(src, "!.o"); + *p++ = obj = extend(src, "!.o"); *p++ = src = extend(src, ".c"); if ((cpid = fork()) == -1) err(EXIT_FAILURE, "Unable to fork"); else if (!cpid) run("/usr/bin/cc", args, "compile", src); await(cpid, "compile", src); + free(obj); free(src); free(args); } @@ -110,9 +110,8 @@ void load(char type, char *target, char **objs) { char **args, **p, **a, **fp, *path; pid_t cpid; - f = o = 0; - while (objs[o]) ++o; - if (lflags) while (lflags[f]) ++f; + for (o = 0; objs[o]; ++o); + for (f = 0; lflags[f]; ++f); args = allocate((3 + o + 1 + f + 1) * sizeof*args); fp = (a = (p = args) + 3) + o; @@ -137,9 +136,8 @@ void load(char type, char *target, char **objs) { errx(EXIT_FAILURE, "Unknown target type `%c'", type); } *p++ = target; - f = o = 0; - while (objs[o]) *p++ = extend(objs[o++], ".o"); - if (lflags) while (lflags[f]) *fp++ = lflags[f++]; + for (o = 0; objs[o]; *p++ = extend(objs[o++], ".o")); + for (f = 0; lflags[f]; *fp++ = lflags[f++]); if ((cpid = fork()) == -1) err(EXIT_FAILURE, "Unable to fork"); else if (!cpid) run(path, args, "link", target); @@ -196,14 +194,16 @@ void build(char *path) { if (self || !exists) { c = cflags; l = lflags; - lflags = cflags = NULL; + cflags = NONE; compile("build"); + + lflags = NONE; load('x', "build", LIST("build")); cflags = c; lflags = l; } - run("build", LIST(NULL, "build"), "run", "build"); + run("!build", LIST("build"), "run", "build"); }