Browse Source

Remove old nobuild

rexim 4 years ago
parent
commit
9e606f7459
2 changed files with 0 additions and 1008 deletions
  1. 0 58
      nobuild.c
  2. 0 950
      nobuild.h

+ 0 - 58
nobuild.c

@@ -1,58 +0,0 @@
-#define NOBUILD_IMPLEMENTATION
-#include "./nobuild.h"
-
-#define CFLAGS "-Wall", "-Wextra", "-std=c11", "-pedantic", "-ggdb"
-
-void check_example(const char *example)
-{
-    const char *example_path = PATH("examples", NOEXT(example));
-
-    INFO("===== %s =====", NOEXT(example));
-
-#ifdef _WIN32
-    CMD("cl.exe", "/Fe.\\examples\\", PATH("examples", example));
-    CMD(CONCAT(example_path, ".exe"));
-#else
-    const char *cc = getenv("CC");
-    if (cc == NULL) cc = "cc";
-
-    CMD(cc, CFLAGS, "-o", example_path, PATH("examples", example));
-    CMD(example_path);
-#endif // _WIN32
-}
-
-void check_examples(void)
-{
-    FOREACH_FILE_IN_DIR(example, "examples", {
-        if (ENDS_WITH(example, ".c")) {
-            check_example(example);
-        }
-    });
-}
-
-void build_tool(const char *tool)
-{
-#ifdef _WIN32
-    CMD("cl.exe", "/Fe.\\tools\\", PATH("tools", CONCAT(tool, ".c")));
-#else
-    const char *cc = getenv("CC");
-    if (cc == NULL) cc = "cc";
-    CMD(cc, "-o", PATH("tools", tool), PATH("tools", CONCAT(tool, ".c")));
-#endif // _WIN32
-}
-
-void build_tools(void)
-{
-    FOREACH_FILE_IN_DIR(tool, "tools", {
-        if (ENDS_WITH(tool, ".c")) {
-            build_tool(NOEXT(tool));
-        }
-    });
-}
-
-int main(int argc, char *argv[])
-{
-    build_tools();
-    check_examples();
-    return 0;
-}

+ 0 - 950
nobuild.h

@@ -1,950 +0,0 @@
-// Copyright 2021 Alexey Kutepov <[email protected]>
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-// ============================================================
-//
-// nobuild — 0.3.0-dev — Header only library for writing build recipes in C.
-//
-// https://github.com/tsoding/nobuild
-//
-// ============================================================
-
-#ifndef NOBUILD_H_
-#define NOBUILD_H_
-
-#ifndef _WIN32
-#define _POSIX_C_SOURCE 200809L
-#endif // _WIN32
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-
-#ifdef _WIN32
-#   define WIN32_LEAN_AND_MEAN
-#   include "windows.h"
-#   include <process.h>
-// minirent.h HEADER BEGIN ////////////////////////////////////////
-    // Copyright 2021 Alexey Kutepov <[email protected]>
-    //
-    // Permission is hereby granted, free of charge, to any person obtaining
-    // a copy of this software and associated documentation files (the
-    // "Software"), to deal in the Software without restriction, including
-    // without limitation the rights to use, copy, modify, merge, publish,
-    // distribute, sublicense, and/or sell copies of the Software, and to
-    // permit persons to whom the Software is furnished to do so, subject to
-    // the following conditions:
-    //
-    // The above copyright notice and this permission notice shall be
-    // included in all copies or substantial portions of the Software.
-    //
-    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-    // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-    // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-    //
-    // ============================================================
-    //
-    // minirent — 0.0.1 — A subset of dirent interface for Windows.
-    //
-    // https://github.com/tsoding/minirent
-    //
-    // ============================================================
-    //
-    // ChangeLog (https://semver.org/ is implied)
-    //
-    //    0.0.1 First Official Release
-
-    #ifndef MINIRENT_H_
-    #define MINIRENT_H_
-
-    #define WIN32_LEAN_AND_MEAN
-    #include "windows.h"
-
-    struct dirent
-    {
-        char d_name[MAX_PATH+1];
-    };
-
-    typedef struct DIR DIR;
-
-    DIR *opendir(const char *dirpath);
-    struct dirent *readdir(DIR *dirp);
-    int closedir(DIR *dirp);
-
-    #endif  // MINIRENT_H_
-// minirent.h HEADER END ////////////////////////////////////////
-#else
-#   include <sys/stat.h>
-#   include <sys/types.h>
-#   include <sys/wait.h>
-#   include <unistd.h>
-#   include <dirent.h>
-#   include <fcntl.h>
-#endif // _WIN32
-
-
-// TODO(#1): no way to disable echo in nobuild scripts
-// TODO(#2): no way to ignore fails
-
-#ifdef _WIN32
-#    define PATH_SEP "\\"
-#else
-#    define PATH_SEP "/"
-#endif // _WIN32
-
-#define PATH_SEP_LEN (sizeof(PATH_SEP) - 1)
-
-#define FOREACH_VARGS_CSTR(param, arg, args, body)          \
-    do {                                                    \
-        va_start(args, param);                              \
-        for (const char *arg = va_arg(args, const char *);  \
-             arg != NULL;                                   \
-             arg = va_arg(args, const char *))              \
-        {                                                   \
-            body;                                           \
-        }                                                   \
-        va_end(args);                                       \
-    } while(0)
-
-#define FOREACH_VARGS(param, arg, args, body)               \
-    do {                                                    \
-        WARN("DEPRECATED: Please don't use FOREACH_VARGS(...). Please use FOREACH_VARGS_CSTR(...) instead. FOREACH_VARGS(...) will be removed on the next major release."); \
-        va_start(args, param);                              \
-        for (const char *arg = va_arg(args, const char *);  \
-             arg != NULL;                                   \
-             arg = va_arg(args, const char *))              \
-        {                                                   \
-            body;                                           \
-        }                                                   \
-        va_end(args);                                       \
-    } while(0)
-
-#define FOREACH_ARRAY(type, item, items, body)  \
-    do {                                        \
-        for (size_t i = 0;                                              \
-             i < sizeof(items) / sizeof((items)[0]);                    \
-             ++i)                                                       \
-        {                                                               \
-            type item = items[i];                                       \
-            body;                                                       \
-        }                                                               \
-    } while(0)
-
-#define FOREACH_FILE_IN_DIR(file, dirpath, body)        \
-    do {                                                \
-        struct dirent *dp = NULL;                       \
-        DIR *dir = opendir(dirpath);                    \
-        while ((dp = readdir(dir))) {                   \
-            const char *file = dp->d_name;              \
-            body;                                       \
-        }                                               \
-        closedir(dir);                                  \
-    } while(0)
-
-// TODO(#5): there is no way to redirect the output of CMD to a file
-#define CMD(...)                                                \
-    do {                                                        \
-        INFO(JOIN(" ", __VA_ARGS__));                           \
-        cmd_impl(69, __VA_ARGS__, NULL);                        \
-    } while(0)
-
-const char *concat_impl(int ignore, ...);
-const char *concat_sep_impl(const char *sep, ...);
-const char *build__join(const char *sep, ...);
-int nobuild__ends_with(const char *str, const char *postfix);
-int nobuild__is_dir(const char *path);
-void mkdirs_impl(int ignore, ...);
-void cmd_impl(int ignore, ...);
-void nobuild_exec(const char **argv);
-const char *remove_ext(const char *path);
-char *shift(int *argc, char ***argv);
-void nobuild__rm(const char *path);
-
-#ifndef _WIN32
-void nobuild__posix_wait_for_pid(pid_t pid);
-#endif
-
-typedef struct {
-    const char **args;
-} Cmd;
-
-const char** nobuild_cstr_vargs_to_array(int *count, ...);
-
-
-// TODO(#20): pipes do not allow redirecting stderr
-typedef struct {
-    const char *input_filepath;  // NULL means stdin
-    const char *output_filepath; // NULL means stdout
-    Cmd *chain;
-    size_t chain_size;
-} Pipe;
-
-#ifndef _WIN32
-pid_t nobuild__posix_spawn_cmd(const Cmd *cmd,
-                               int *fdin,  // NULL means stdin
-                               int *fdout, // NULL means stdout
-                               int *fderr  // NULL means stderr
-                               );
-
-void nobuild__posix_spawn_pipe(Pipe pipe);
-#endif // _WIN32
-
-typedef enum {
-    PIPE_ARG_END,
-    PIPE_ARG_IN,
-    PIPE_ARG_OUT,
-    PIPE_ARG_CHAIN,
-} Pipe_Arg_Type;
-
-typedef struct {
-    Pipe_Arg_Type type;
-    const char** args;
-} Pipe_Arg;
-
-Pipe nobuild__make_pipe(int ignore, ...);
-
-#define CONCAT(...) concat_impl(69, __VA_ARGS__, NULL)
-#define CONCAT_SEP(sep, ...) build__deprecated_concat_sep(sep, __VA_ARGS__, NULL)
-#define JOIN(sep, ...) build__join(sep, __VA_ARGS__, NULL)
-#define PATH(...) JOIN(PATH_SEP, __VA_ARGS__)
-#define MKDIRS(...) mkdirs_impl(69, __VA_ARGS__, NULL)
-#define NOEXT(path) nobuild__remove_ext(path)
-#define ENDS_WITH(str, postfix) nobuild__ends_with(str, postfix)
-#define IS_DIR(path) nobuild__is_dir(path)
-#define RM(path)                                \
-    do {                                        \
-        INFO("rm %s", path);                    \
-        nobuild__rm(path);                      \
-    } while(0)
-
-#ifdef _WIN32
-#define PIPE(...) PANIC("Piping is not implemented on windows yet")
-#else
-#define PIPE(...) nobuild__posix_spawn_pipe(nobuild__make_pipe(69, __VA_ARGS__, NULL))
-#endif // _WIN32
-
-// TODO(#17): IN and OUT are already taken by WinAPI
-#define IN(path)                                                        \
-    ((Pipe_Arg) {                                                       \
-        .type = PIPE_ARG_IN,                                            \
-        .args = nobuild_cstr_vargs_to_array(NULL, path, NULL)           \
-    })
-
-#define OUT(path)                                                       \
-    ((Pipe_Arg) {                                                       \
-        .type = PIPE_ARG_OUT,                                           \
-        .args = nobuild_cstr_vargs_to_array(NULL, path, NULL)           \
-    })
-
-#define CHAIN(...)                                                      \
-    ((Pipe_Arg) {                                                       \
-        .type = PIPE_ARG_CHAIN,                                         \
-        .args = nobuild_cstr_vargs_to_array(NULL, __VA_ARGS__, NULL)    \
-    })
-
-#define END                                     \
-    ((Pipe_Arg) {                               \
-        .type = PIPE_ARG_END                    \
-    })
-
-void nobuild_log(FILE *stream, const char *tag, const char *fmt, ...);
-void nobuild_vlog(FILE *stream, const char *tag, const char *fmt, va_list args);
-
-void INFO(const char *fmt, ...);
-void WARN(const char *fmt, ...);
-void ERRO(const char *fmt, ...);
-void PANIC(const char *fmt, ...);
-
-#endif  // NOBUILD_H_
-
-#ifdef NOBUILD_IMPLEMENTATION
-
-#ifdef _WIN32
-// minirent.h IMPLEMENTATION BEGIN ////////////////////////////////////////
-    struct DIR
-    {
-        HANDLE hFind;
-        WIN32_FIND_DATA data;
-        struct dirent *dirent;
-    };
-
-    DIR *opendir(const char *dirpath)
-    {
-        assert(dirpath);
-
-        char buffer[MAX_PATH];
-        snprintf(buffer, MAX_PATH, "%s\\*", dirpath);
-
-        DIR *dir = (DIR*)calloc(1, sizeof(DIR));
-
-        dir->hFind = FindFirstFile(buffer, &dir->data);
-        if (dir->hFind == INVALID_HANDLE_VALUE) {
-            errno = ENOSYS;
-            goto fail;
-        }
-
-        return dir;
-
-    fail:
-        if (dir) {
-            free(dir);
-        }
-
-        return NULL;
-    }
-
-    struct dirent *readdir(DIR *dirp)
-    {
-        assert(dirp);
-
-        if (dirp->dirent == NULL) {
-            dirp->dirent = (struct dirent*)calloc(1, sizeof(struct dirent));
-        } else {
-            if(!FindNextFile(dirp->hFind, &dirp->data)) {
-                if (GetLastError() != ERROR_NO_MORE_FILES) {
-                    errno = ENOSYS;
-                }
-
-                return NULL;
-            }
-        }
-
-        memset(dirp->dirent->d_name, 0, sizeof(dirp->dirent->d_name));
-
-        strncpy(
-            dirp->dirent->d_name,
-            dirp->data.cFileName,
-            sizeof(dirp->dirent->d_name) - 1);
-
-        return dirp->dirent;
-    }
-
-    int closedir(DIR *dirp)
-    {
-        assert(dirp);
-
-        if(!FindClose(dirp->hFind)) {
-            errno = ENOSYS;
-            return -1;
-        }
-
-        if (dirp->dirent) {
-            free(dirp->dirent);
-        }
-        free(dirp);
-
-        return 0;
-    }
-// minirent.h IMPLEMENTATION END ////////////////////////////////////////
-#endif // _WIN32
-
-const char *build__join(const char *sep, ...)
-{
-    const size_t sep_len = strlen(sep);
-    size_t length = 0;
-    size_t seps_count = 0;
-
-    va_list args;
-
-    FOREACH_VARGS_CSTR(sep, arg, args, {
-        length += strlen(arg);
-        seps_count += 1;
-    });
-    assert(length > 0);
-
-    seps_count -= 1;
-
-    char *result = malloc(length + seps_count * sep_len + 1);
-
-    length = 0;
-    FOREACH_VARGS_CSTR(sep, arg, args, {
-        size_t n = strlen(arg);
-        memcpy(result + length, arg, n);
-        length += n;
-
-        if (seps_count > 0) {
-            memcpy(result + length, sep, sep_len);
-            length += sep_len;
-            seps_count -= 1;
-        }
-    });
-
-    result[length] = '\0';
-
-    return result;
-}
-
-const char *build__deprecated_concat_sep(const char *sep, ...)
-{
-    WARN("DEPRECATED: Please don't use `CONCAT_SEP(sep, ...)`. Please use JOIN(sep, ...) instead. `CONCAT_SEP(sep, ...)` will be removed in the next major release.");
-
-    const size_t sep_len = strlen(sep);
-    size_t length = 0;
-    size_t seps_count = 0;
-
-    va_list args;
-
-    FOREACH_VARGS_CSTR(sep, arg, args, {
-        length += strlen(arg);
-        seps_count += 1;
-    });
-    assert(length > 0);
-
-    seps_count -= 1;
-
-    char *result = malloc(length + seps_count * sep_len + 1);
-
-    length = 0;
-    FOREACH_VARGS_CSTR(sep, arg, args, {
-        size_t n = strlen(arg);
-        memcpy(result + length, arg, n);
-        length += n;
-
-        if (seps_count > 0) {
-            memcpy(result + length, sep, sep_len);
-            length += sep_len;
-            seps_count -= 1;
-        }
-    });
-
-    result[length] = '\0';
-
-    return result;
-}
-
-const char *concat_sep_impl(const char *sep, ...)
-{
-    WARN("DEPRECATED: Please don't use `concat_sep_impl(sep, ...)`. Please use JOIN(sep, ...) instead. `concat_sep_impl(sep, ...)` will be removed in the next major release.");
-
-    const size_t sep_len = strlen(sep);
-    size_t length = 0;
-    size_t seps_count = 0;
-
-    va_list args;
-
-    FOREACH_VARGS_CSTR(sep, arg, args, {
-        length += strlen(arg);
-        seps_count += 1;
-    });
-    assert(length > 0);
-
-    seps_count -= 1;
-
-    char *result = malloc(length + seps_count * sep_len + 1);
-
-    length = 0;
-    FOREACH_VARGS_CSTR(sep, arg, args, {
-        size_t n = strlen(arg);
-        memcpy(result + length, arg, n);
-        length += n;
-
-        if (seps_count > 0) {
-            memcpy(result + length, sep, sep_len);
-            length += sep_len;
-            seps_count -= 1;
-        }
-    });
-
-    result[length] = '\0';
-
-    return result;
-}
-
-void mkdirs_impl(int ignore, ...)
-{
-    size_t length = 0;
-    size_t seps_count = 0;
-
-    va_list args;
-
-    FOREACH_VARGS_CSTR(ignore, arg, args, {
-        length += strlen(arg);
-        seps_count += 1;
-    });
-
-    assert(length > 0);
-    seps_count -= 1;
-
-    char *result = malloc(length + seps_count * PATH_SEP_LEN + 1);
-
-    length = 0;
-    FOREACH_VARGS_CSTR(ignore, arg, args, {
-        size_t n = strlen(arg);
-        memcpy(result + length, arg, n);
-        length += n;
-
-        if (seps_count > 0) {
-            memcpy(result + length, PATH_SEP, PATH_SEP_LEN);
-            length += PATH_SEP_LEN;
-            seps_count -= 1;
-        }
-
-        result[length] = '\0';
-
-        INFO("mkdirs %s", result);
-        if (mkdir(result, 0755) < 0) {
-            if (errno == EEXIST) {
-                WARN("directory %s already exists", result);
-            } else {
-                PANIC("could not create directory %s: %s", result, strerror(errno));
-            }
-        }
-    });
-}
-
-// TODO(#4): there is no way to remove a file
-
-const char *concat_impl(int ignore, ...)
-{
-    size_t length = 0;
-    va_list args;
-    FOREACH_VARGS_CSTR(ignore, arg, args, {
-        length += strlen(arg);
-    });
-
-    char *result = malloc(length + 1);
-
-    length = 0;
-    FOREACH_VARGS_CSTR(ignore, arg, args, {
-        size_t n = strlen(arg);
-        memcpy(result + length, arg, n);
-        length += n;
-    });
-    result[length] = '\0';
-
-    return result;
-}
-
-void nobuild_exec(const char **argv)
-{
-#ifdef _WIN32
-    intptr_t status = _spawnvp(_P_WAIT, argv[0], (char * const*) argv);
-    if (status < 0) {
-        PANIC("could not start child process: %s", strerror(errno));
-    }
-
-    if (status > 0) {
-        PANIC("command exited with exit code %d", status);
-    }
-#else
-    pid_t cpid = fork();
-    if (cpid == -1) {
-        PANIC("could not fork a child process: %s", strerror(errno));
-    }
-
-    if (cpid == 0) {
-        if (execvp(argv[0], (char * const*) argv) < 0) {
-            PANIC("could not execute child process: %s", strerror(errno));
-        }
-    } else {
-        nobuild__posix_wait_for_pid(cpid);
-    }
-#endif // _WIN32
-}
-
-void cmd_impl(int ignore, ...)
-{
-    size_t argc = 0;
-
-    va_list args;
-    FOREACH_VARGS_CSTR(ignore, arg, args, {
-        argc += 1;
-    });
-
-    const char **argv = malloc(sizeof(const char*) * (argc + 1));
-
-    argc = 0;
-    FOREACH_VARGS_CSTR(ignore, arg, args, {
-        argv[argc++] = arg;
-    });
-    argv[argc] = NULL;
-
-    assert(argc >= 1);
-
-    nobuild_exec(argv);
-}
-
-const char *nobuild__remove_ext(const char *path)
-{
-    size_t n = strlen(path);
-    while (n > 0 && path[n - 1] != '.') {
-        n -= 1;
-    }
-
-    if (n > 0) {
-        char *result = malloc(n);
-        memcpy(result, path, n);
-        result[n - 1] = '\0';
-
-        return result;
-    } else {
-        return path;
-    }
-}
-
-const char *remove_ext(const char *path)
-{
-    WARN("DEPRECATED: Please use `NOEXT(path)` instead of `remove_ext(path)`. `remove_ext(path)` will be removed in the next major release.");
-    nobuild__remove_ext(path);
-
-    return NULL;
-}
-
-char *shift(int *argc, char ***argv)
-{
-    assert(*argc > 0);
-    char *result = **argv;
-    *argv += 1;
-    *argc -= 1;
-    return result;
-}
-
-void nobuild_log(FILE *stream, const char *tag, const char *fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    nobuild_vlog(stream, tag, fmt, args);
-    va_end(args);
-}
-
-void nobuild_vlog(FILE *stream, const char *tag, const char *fmt, va_list args)
-{
-    fprintf(stream, "[%s] ", tag);
-    vfprintf(stream, fmt, args);
-    fprintf(stream, "\n");
-}
-
-void INFO(const char *fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    nobuild_vlog(stdout, "INFO", fmt, args);
-    va_end(args);
-}
-
-void WARN(const char *fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    nobuild_vlog(stderr, "WARN", fmt, args);
-    va_end(args);
-}
-
-void ERRO(const char *fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    nobuild_vlog(stderr, "ERRO", fmt, args);
-    va_end(args);
-}
-
-void PANIC(const char *fmt, ...)
-{
-    va_list args;
-    va_start(args, fmt);
-    nobuild_vlog(stderr, "ERRO", fmt, args);
-    va_end(args);
-    exit(1);
-}
-
-int nobuild__ends_with(const char *str, const char *postfix)
-{
-    const size_t str_n = strlen(str);
-    const size_t postfix_n = strlen(postfix);
-    return postfix_n <= str_n && strcmp(str + str_n - postfix_n, postfix) == 0;
-}
-
-int nobuild__is_dir(const char *path)
-{
-#ifdef _WIN32
-    DWORD dwAttrib = GetFileAttributes(path);
-
-    return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
-            (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
-#else
-    struct stat statbuf = {0};
-    if (stat(path, &statbuf) < 0) {
-        if (errno == ENOENT) {
-            return 0;
-        }
-
-        PANIC("could not retrieve information about file %s: %s",
-              path, strerror(errno));
-    }
-
-    return S_ISDIR(statbuf.st_mode);
-#endif // _WIN32
-}
-
-void nobuild__rm(const char *path)
-{
-    if (IS_DIR(path)) {
-        FOREACH_FILE_IN_DIR(file, path, {
-            if (strcmp(file, ".") != 0 && strcmp(file, "..") != 0) {
-                nobuild__rm(PATH(path, file));
-            }
-        });
-
-        if (rmdir(path) < 0) {
-            if (errno == ENOENT) {
-                WARN("directory %s does not exist");
-            } else {
-                PANIC("could not remove directory %s: %s", path, strerror(errno));
-            }
-        }
-    } else {
-        if (unlink(path) < 0) {
-            if (errno == ENOENT) {
-                WARN("file %s does not exist");
-            } else {
-                PANIC("could not remove file %s: %s", path, strerror(errno));
-            }
-        }
-    }
-}
-
-Pipe nobuild__make_pipe(int ignore, ...)
-{
-    Pipe result = {0};
-
-    va_list args;
-    va_start(args, ignore);
-    {
-        Pipe_Arg arg = va_arg(args, Pipe_Arg);
-        while (arg.type != PIPE_ARG_END) {
-            switch (arg.type) {
-            case PIPE_ARG_IN: {
-                if (result.input_filepath == NULL) {
-                    result.input_filepath = arg.args[0];
-                } else {
-                    // TODO(#15): PIPE does not report where exactly a syntactic error has happened
-                    PANIC("input file was already set for the pipe");
-                }
-            } break;
-
-            case PIPE_ARG_OUT: {
-                if (result.output_filepath == NULL) {
-                    result.output_filepath = arg.args[0];
-                } else {
-                    PANIC("output file was already set for the pipe");
-                }
-            } break;
-
-            case PIPE_ARG_CHAIN: {
-                result.chain_size += 1;
-            } break;
-
-            case PIPE_ARG_END:
-            default: {
-                assert(0 && "unreachable");
-            }
-            }
-
-            arg = va_arg(args, Pipe_Arg);
-        }
-    }
-    va_end(args);
-
-    result.chain = malloc(sizeof(Cmd) * result.chain_size);
-
-    result.chain_size = 0;
-    va_start(args, ignore);
-    {
-        Pipe_Arg arg = va_arg(args, Pipe_Arg);
-        while (arg.type != PIPE_ARG_END) {
-            if (arg.type == PIPE_ARG_CHAIN) {
-                result.chain[result.chain_size++].args = arg.args;
-            }
-            arg = va_arg(args, Pipe_Arg);
-        }
-    }
-    va_end(args);
-
-    return result;
-}
-
-#ifndef _WIN32
-void nobuild__posix_wait_for_pid(pid_t pid)
-{
-    for (;;) {
-        int wstatus = 0;
-        waitpid(pid, &wstatus, 0);
-
-        if (WIFEXITED(wstatus)) {
-            int exit_status = WEXITSTATUS(wstatus);
-            if (exit_status != 0) {
-                PANIC("command exited with exit code %d", exit_status);
-            }
-
-            break;
-        }
-
-        if (WIFSIGNALED(wstatus)) {
-            PANIC("command process was terminated by %s", strsignal(WTERMSIG(wstatus)));
-        }
-    }
-}
-#endif
-
-const char** nobuild_cstr_vargs_to_array(int *out_count, ...)
-{
-    size_t count = 0;
-    va_list args;
-    FOREACH_VARGS_CSTR(out_count, arg, args, {
-        count += 1;
-    });
-
-    const char **result = malloc(sizeof(const char *) * (count + 1));
-
-    count = 0;
-    FOREACH_VARGS_CSTR(out_count, arg, args, {
-        result[count++] = arg;
-    });
-
-    result[count] = NULL;
-
-    if (out_count) {
-        *out_count = count;
-    }
-
-    return result;
-}
-
-#ifndef _WIN32
-pid_t nobuild__posix_spawn_cmd(const Cmd *cmd,
-                               int *fdin,  // NULL means stdin
-                               int *fdout, // NULL means stdout
-                               int *fderr  // NULL means stdout
-                               )
-{
-    pid_t cpid = fork();
-
-    if (cpid < 0) {
-        PANIC("could not fork a child: %s", strerror(errno));
-    }
-
-    if (cpid == 0) {
-        if (fdin) {
-            if (dup2(*fdin, STDIN_FILENO) < 0) {
-                PANIC("could not setup stdin for child process: %s", strerror(errno));
-            }
-        }
-
-        if (fdout) {
-            if (dup2(*fdout, STDOUT_FILENO) < 0) {
-                PANIC("could not setup stdout for child process: %s", strerror(errno));
-            }
-        }
-
-        if (fderr) {
-            if (dup2(*fderr, STDERR_FILENO) < 0) {
-                PANIC("could not setup stderr for child process: %s", strerror(errno));
-            }
-        }
-
-        if (execvp(cmd->args[0], (char * const*) cmd->args) < 0) {
-            PANIC("could not exec child process: %s", strerror(errno));
-        }
-    }
-
-    return cpid;
-}
-
-void nobuild__posix_spawn_pipe(Pipe my_pipe)
-{
-    if (my_pipe.chain_size == 0) {
-        return;
-    }
-
-    pid_t *cpids = malloc(sizeof(pid_t) * my_pipe.chain_size);
-
-    int pipefd[2] = {0};
-    int fdin = 0;
-    int *fdprev = NULL;
-
-    if (my_pipe.input_filepath) {
-        fdin = open(my_pipe.input_filepath, O_RDONLY);
-        if (fdin < 0) {
-            PANIC("could not open file %s: %s", my_pipe.input_filepath, strerror(errno));
-        }
-        fdprev = &fdin;
-    }
-
-    for (size_t i = 0; i < my_pipe.chain_size - 1; ++i) {
-        if (pipe(pipefd) < 0) {
-            PANIC("could not create pipe for a child process: %s", strerror(errno));
-        }
-
-        cpids[i] = nobuild__posix_spawn_cmd(
-            &my_pipe.chain[i],
-            fdprev,
-            &pipefd[1],
-            NULL);
-
-        if (fdprev) close(*fdprev);
-        close(pipefd[1]);
-        fdprev = &fdin;
-        fdin = pipefd[0];
-    }
-
-    {
-        int fdout = 0;
-        int *fdnext = NULL;
-
-        if (my_pipe.output_filepath) {
-            fdout = open(my_pipe.output_filepath,
-                         O_WRONLY | O_CREAT | O_TRUNC,
-                         S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-            if (fdout < 0) {
-                PANIC("could not open file %s: %s",
-                      my_pipe.output_filepath,
-                      strerror(errno));
-            }
-            fdnext = &fdout;
-        }
-
-        const size_t last = my_pipe.chain_size - 1;
-        cpids[last] =
-            nobuild__posix_spawn_cmd(
-            &my_pipe.chain[last],
-            fdprev,
-            fdnext,
-            NULL);
-
-        if (fdprev) close(*fdprev);
-        if (fdnext) close(*fdnext);
-    }
-
-    for (size_t i = 0; i < my_pipe.chain_size; ++i) {
-        nobuild__posix_wait_for_pid(cpids[i]);
-    }
-}
-
-#endif // _WIN32
-
-#endif // NOBUILD_IMPLEMENTATION