diff options
-rw-r--r-- | README.md | 250 |
1 files changed, 196 insertions, 54 deletions
@@ -68,32 +68,32 @@ static char *cflags[] = {"-Wall", "-Wextra", "-Werror", "-O3"}; int main(int argc, char **argv) { - /* Initialize the library, and rebuild this script if needed */ - cbsinit(argc, argv); - rebuild(); - - /* If the compiled binary isn’t outdated, do nothing */ - if (!foutdatedl("my-file", "my-file.c")) - return EXIT_SUCCESS; - - /* Append ‘cc’ and our cflags to the command, but allow the user to use the - $CC and $CFLAGS environment variables to override them */ - struct strs cmd = {0}; - strspushenvl(&cmd, "CC", "cc"); - strspushenv(&cmd, "CFLAGS", cflags, lengthof(cflags)); - - /* Call pkg-config with the --libs and --cflags options for the library - ‘liblux’, appending the result to our command. If it fails then we - fallback to using -llux */ - if (!pcquery(&cmd, "liblux", PC_LIBS | PC_CFLAGS)) - strspushl(&cmd, "-llux"); - - /* Push the final arguments to our command */ - strspushl(&cmd, "-o", "my-file", "-c", "my-file.c"); - - /* Print our command to stdout, and execute it */ - cmdput(cmd); - return cmdexec(cmd); + /* Initialize the library, and rebuild this script if needed */ + cbsinit(argc, argv); + rebuild(); + + /* If the compiled binary isn’t outdated, do nothing */ + if (!foutdatedl("my-file", "my-file.c")) + return EXIT_SUCCESS; + + /* Append ‘cc’ and our cflags to the command, but allow the user to use the + $CC and $CFLAGS environment variables to override them */ + struct strs cmd = {0}; + strspushenvl(&cmd, "CC", "cc"); + strspushenv(&cmd, "CFLAGS", cflags, lengthof(cflags)); + + /* Call pkg-config with the --libs and --cflags options for the library + ‘liblux’, appending the result to our command. If it fails then we + fallback to using -llux */ + if (!pcquery(&cmd, "liblux", PC_LIBS | PC_CFLAGS)) + strspushl(&cmd, "-llux"); + + /* Push the final arguments to our command */ + strspushl(&cmd, "-o", "my-file", "-c", "my-file.c"); + + /* Print our command to stdout, and execute it */ + cmdput(cmd); + return cmdexec(cmd); } ``` @@ -121,61 +121,203 @@ main(int argc, char **argv) if (!foutdated("my-file", sources, lengthof(sources))) return EXIT_SUCCESS; - /* Get the number of CPUs available. If this fails we fallback to 8. */ - int cpus = nproc(); + /* Get the number of CPUs available. If this fails we fallback to 8. */ + int cpus = nproc(); if (cpus == -1) cpus = 8; - /* Create a thread pool, with one thread per CPU */ - tpool tp; + /* Create a thread pool, with one thread per CPU */ + tpool tp; tpinit(&tp, cpus); - /* For each of our source files, add a task to the thread pool to build - the file ‘sources[i]’ with the function ‘build’ */ + /* For each of our source files, add a task to the thread pool to build + the file ‘sources[i]’ with the function ‘build’ */ for (size_t i = 0; i < lengthof(sources); i++) tpenq(&tp, build, sources[i], NULL); - /* Wait for all the tasks to complete and free the thread pool */ + /* Wait for all the tasks to complete and free the thread pool */ tpwait(&tp); tpfree(&tp); - struct strs cmd = {0}; - strspushenvl(&cmd, "CC", "cc"); - strspushl(&cmd, "-o", "my-file"); + struct strs cmd = {0}; + strspushenvl(&cmd, "CC", "cc"); + strspushl(&cmd, "-o", "my-file"); - for (size_t i = 0; i < lengthof(sources); i++) - strspushl(&cmd, swpext(sources[i], "o")); + for (size_t i = 0; i < lengthof(sources); i++) + strspushl(&cmd, swpext(sources[i], "o")); cmdput(cmd); - return cmdexec(cmd); + return cmdexec(cmd); } void build(void *arg) { - /* This function will be called by the thread pool with ‘arg’ set to a - filename such as ‘foo.c’ */ + /* This function will be called by the thread pool with ‘arg’ set to a + filename such as ‘foo.c’ */ - struct strs cmd = {0}; + struct strs cmd = {0}; - strspushenvl(&cmd, "CC", "cc"); - strspushenv(&cmd, "CFLAGS", cflags, lengthof(cflags)); + strspushenvl(&cmd, "CC", "cc"); + strspushenv(&cmd, "CFLAGS", cflags, lengthof(cflags)); - /* Allocate a copy of the string ‘arg’, with the file extension replaced. - This will for example return ‘foo.o’ when given ‘foo.c’ */ - char *object = swpext(arg, "o"); + /* Allocate a copy of the string ‘arg’, with the file extension replaced. + This will for example return ‘foo.o’ when given ‘foo.c’ */ + char *object = swpext(arg, "o"); - strspushl(&cmd, "-o", object, "-c", arg); + strspushl(&cmd, "-o", object, "-c", arg); - cmdput(cmd); - if (cmdexec(cmd) != EXIT_SUCCESS) - exit(EXIT_FAILURE); - free(object); - strsfree(&cmd); + cmdput(cmd); + if (cmdexec(cmd) != EXIT_SUCCESS) + exit(EXIT_FAILURE); + free(object); + strsfree(&cmd); } ``` ## Documentation -Coming soon! +### Macros + +```c +#define CBS_NO_THREADS +``` + +If this macro is defined before including `cbs.h`, then support for thread pools +won’t be included meaning you don’t need to link with `-lpthread` when +bootstrapping the build script. + +--- + +```c +#define lengthof(xs) /* … */ +``` + +Return the number of elements in the static array `xs`. + +### Startup Functions + +These two functions should be called at the very beginning of your `main()` +function in the order in which they are documented here for everything to work +properly. + +--- + +```c +void cbsinit(int argc, char **argv) +``` + +Should be the first function called in `main()` and passed the same parameters +received from `main()`. It initializes some internal data, but it also changes +the current working directory so that the running process is in the same +directory as the location of the process. For example if your build script is +called `make` and you call it as `./build/make`, this function will change your +working directory to `./build`. + +--- + +```c +#define rebuild() /* … */ +``` + +Should be called right after `cbsinit()`. This function-like macro checks to +see if the build script is outdated compared to its source file. If it finds +that the build script is outdated it rebuilds it before executing the new build +script. + +### String Array Types and Functions + +The following types and functions all work on dynamically-allocated arrays of +string, which make gradually composing a complete command that can be executed +very simple. + +--- + +```c +struct strs { + char **buf; + size_t len, cap; +}; +``` + +A type representing a dynamic array of strings. The `len` and `cap` fields hold +the length and capacity of the string array respectively, and the `buf` field is +the actual array itself. Despite being a sized array, `buf` is also guaranteed +by all the functions that act on this structure to always be null-terminated. + +There is no initialization function for the `strs` structure. To initialize the +structure simply zero-initialize it: + +```c +int +main(int argc, char **argv) +{ + /* … */ + struct strs cmd = {0}; + strspush(&cmd, "cc"); + /* … */ +} +``` + +--- + +```c +void strsfree(struct strs *xs) +``` + +Deallocates all memory associated with the string array `xs`. Note that this +does **not** deallocate memory associated with the individual elements in the +string array — that must still be done manually. + +This function also zeros `xs` after freeing memory, so that the same structure +can be safely reused afterwards. + +--- + +```c +void strszero(struct strs *xs) +``` + +Zeros the string array `xs` **without** deallocating any memory used by the +string array. This allows you to reuse the same structure for a different +purpose without needing to reallocate a fresh new array, instead reusing the old +one. + +--- + +```c +void strspush(struct strs *xs, char **ys, size_t n) +``` + +Append `n` strings from the string array `ys` to the end of `xs`. + +--- + +```c +#define strspushl(xs, ...) /* … */ +``` + +Append the strings specified by the provided variable-arguments to the end of +`xs`. + +--- + +```c +void strspushenv(struct strs *xs, const char *ev, char **ys, size_t n) +``` + +Append the value of the environment variable `ev` to the end of `xs`. If the +provided environment variable doesn’t exist or has the value of the empty +string, then fallback to appending `n` strings from `ys` to the end of `xs`. + +--- + +```c +#define strspushenvl(xs, ev, ...) +``` + +Append the value of the environment variable `ev` to the end of `xs`. If the +provided environment variable doesn’t exist or has the value of the empty +string, then fallback to appending the strings specified by the provided +variable-arguments to the end of `xs`. |