Browse Source

Merge pull request #7 from tsoding/0.0.1

[0.0.1] First official release
Alexey Kutepov 4 years ago
parent
commit
0ca90b6e71
5 changed files with 203 additions and 87 deletions
  1. 3 1
      README.md
  2. 1 0
      examples/foreach.c
  3. 1 0
      examples/string.c
  4. 1 0
      nobuild.c
  5. 197 86
      nobuild.h

+ 3 - 1
README.md

@@ -17,8 +17,10 @@ Explore [nobuild.c](./nobuild.c) file and the [examples](./examples) folder to l
 
 ## How to use the library in your own project
 
+Keep in mind that [nobuild.h](./nobuild.h) is an [stb-style](https://github.com/nothings/stb/blob/master/docs/stb_howto.txt) header-only library. That means that just including it does not include the implementations of the functions. You have to define `NOBUILD_IMPLEMENTATION` macro before the include. See our [nobuild.c](./nobuild.c) for an example.
+
 1. Copy [nobuild.h](./nobuild.h) to your project
-2. Create `nobuild.c` in your project with the build recipe. See our own [nobuild.c](./nobuild.c) for an example.
+2. Create `nobuild.c` in your project with the build recipe. See our [nobuild.c](./nobuild.c) for an example.
 3. Bootstrap the `nobuild` executable:
    - `$ cc nobuild.c -o nobuild` on POSIX systems
    - `$ cl.exe nobuild.c` on Windows with MSVC

+ 1 - 0
examples/foreach.c

@@ -1,3 +1,4 @@
+#define NOBUILD_IMPLEMENTATION
 #include "../nobuild.h"
 
 void foreach_vargs(int ignore, ...)

+ 1 - 0
examples/string.c

@@ -1,3 +1,4 @@
+#define NOBUILD_IMPLEMENTATION
 #include "../nobuild.h"
 
 #define DEMO(expr)                              \

+ 1 - 0
nobuild.c

@@ -1,3 +1,4 @@
+#define NOBUILD_IMPLEMENTATION
 #include "./nobuild.h"
 
 void check_example(const char *example)

+ 197 - 86
nobuild.h

@@ -1,3 +1,39 @@
+// 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.0.1 — Header only library for writing build recipes in C.
+//
+// https://github.com/tsoding/nobuild
+//
+// ============================================================
+//
+// ChangeLog (https://semver.org/ is implied)
+//
+//    0.0.1 First Official Release
+
+#ifndef NOBUILD_H_
+#define NOBUILD_H_
+
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -9,88 +45,70 @@
 #   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>
 #endif // _WIN32
 
 // TODO(#1): no way to disable echo in nobuild scripts
 // TODO(#2): no way to ignore fails
 
-#ifdef _WIN32
-struct dirent
-{
-    char d_name[MAX_PATH+1];
-};
-
-typedef struct {
-    HANDLE hFind;
-    WIN32_FIND_DATA data;
-    struct dirent *dirent;
-} DIR;
-
-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) {
-        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)) {
-            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;
-}
-
-void closedir(DIR *dirp)
-{
-    assert(dirp);
-
-    FindClose(dirp->hFind);
-    if (dirp->dirent) {
-        free(dirp->dirent);
-    }
-    free(dirp);
-}
-#else
-#    include <dirent.h>
-#endif // _WIN32
-
 #ifdef _WIN32
 #    define PATH_SEP "\\"
 #else
@@ -133,6 +151,109 @@ void closedir(DIR *dirp)
         closedir(dir);                                  \
     } while(0)
 
+// TODO(#5): there is no way to redirect the output of CMD to a file
+#define CMD(...)                                                \
+    do {                                                        \
+        printf("[INFO] %s\n", CONCAT_SEP(" ", __VA_ARGS__));    \
+        cmd_impl(69, __VA_ARGS__, NULL);                        \
+    } while(0)
+
+const char *concat_impl(int ignore, ...);
+const char *concat_sep_impl(const char *sep, ...);
+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);
+
+#define CONCAT(...) concat_impl(69, __VA_ARGS__, NULL)
+#define CONCAT_SEP(sep, ...) concat_sep_impl(sep, __VA_ARGS__, NULL)
+#define PATH(...) CONCAT_SEP(PATH_SEP, __VA_ARGS__)
+#define MKDIRS(...) mkdirs_impl(69, __VA_ARGS__, NULL)
+
+#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 *concat_sep_impl(const char *sep, ...)
 {
     const size_t sep_len = strlen(sep);
@@ -169,10 +290,6 @@ const char *concat_sep_impl(const char *sep, ...)
     return result;
 }
 
-#define CONCAT_SEP(sep, ...) concat_sep_impl(sep, __VA_ARGS__, NULL)
-
-#define PATH(...) CONCAT_SEP(PATH_SEP, __VA_ARGS__)
-
 void mkdirs_impl(int ignore, ...)
 {
     size_t length = 0;
@@ -218,8 +335,6 @@ void mkdirs_impl(int ignore, ...)
     });
 }
 
-#define MKDIRS(...) mkdirs_impl(69, __VA_ARGS__, NULL)
-
 // TODO(#3): there is no way to remove a folder
 // TODO(#4): there is no way to remove a file
 
@@ -244,7 +359,8 @@ const char *concat_impl(int ignore, ...)
     return result;
 }
 
-#define CONCAT(...) concat_impl(69, __VA_ARGS__, NULL)
+
+
 
 void nobuild_exec(const char **argv)
 {
@@ -322,13 +438,6 @@ void cmd_impl(int ignore, ...)
     nobuild_exec(argv);
 }
 
-// TODO(#5): there is no way to redirect the output of CMD to a file
-#define CMD(...)                                                \
-    do {                                                        \
-        printf("[INFO] %s\n", CONCAT_SEP(" ", __VA_ARGS__));    \
-        cmd_impl(69, __VA_ARGS__, NULL);                        \
-    } while(0)
-
 const char *remove_ext(const char *path)
 {
     size_t n = strlen(path);
@@ -355,3 +464,5 @@ char *shift(int *argc, char ***argv)
     *argc -= 1;
     return result;
 }
+
+#endif // NOBUILD_IMPLEMENTATION