diff --git a/nob.c b/nob.c index 001192f0..d70a1485 100644 --- a/nob.c +++ b/nob.c @@ -1,4 +1,5 @@ #include "shared.h" +#define NOBDEF static inline #define NOB_IMPLEMENTATION #define NOB_STRIP_PREFIX #define NOB_EXPERIMENTAL_DELETE_OLD diff --git a/nob.h b/nob.h index 6c286404..4f8694c1 100644 --- a/nob.h +++ b/nob.h @@ -1,4 +1,4 @@ -/* nob - v1.21.0 - Public Domain - https://github.com/tsoding/nob.h +/* nob - v1.22.0 - Public Domain - https://github.com/tsoding/nob.h This library is the next generation of the [NoBuild](https://github.com/tsoding/nobuild) idea. @@ -168,6 +168,14 @@ #define _CRT_SECURE_NO_WARNINGS (1) #endif +#ifndef NOBDEF +/* + Goes before declarations and definitions of the nob functions. Useful to `#define NOBDEF static inline` + if your source code is a single file and you want the compiler to remove unused functions. +*/ +#define NOBDEF +#endif /* NOBDEF */ + #ifndef NOB_ASSERT #include #define NOB_ASSERT assert @@ -246,7 +254,7 @@ typedef enum { // Any messages with the level below nob_minimal_log_level are going to be suppressed. extern Nob_Log_Level nob_minimal_log_level; -void nob_log(Nob_Log_Level level, const char *fmt, ...) NOB_PRINTF_FORMAT(2, 3); +NOBDEF void nob_log(Nob_Log_Level level, const char *fmt, ...) NOB_PRINTF_FORMAT(2, 3); // It is an equivalent of shift command from bash. It basically pops an element from // the beginning of a sized array. @@ -270,13 +278,13 @@ typedef enum { NOB_FILE_OTHER, } Nob_File_Type; -bool nob_mkdir_if_not_exists(const char *path); -bool nob_copy_file(const char *src_path, const char *dst_path); -bool nob_copy_directory_recursively(const char *src_path, const char *dst_path); -bool nob_read_entire_dir(const char *parent, Nob_File_Paths *children); -bool nob_write_entire_file(const char *path, const void *data, size_t size); -Nob_File_Type nob_get_file_type(const char *path); -bool nob_delete_file(const char *path); +NOBDEF bool nob_mkdir_if_not_exists(const char *path); +NOBDEF bool nob_copy_file(const char *src_path, const char *dst_path); +NOBDEF bool nob_copy_directory_recursively(const char *src_path, const char *dst_path); +NOBDEF bool nob_read_entire_dir(const char *parent, Nob_File_Paths *children); +NOBDEF bool nob_write_entire_file(const char *path, const void *data, size_t size); +NOBDEF Nob_File_Type nob_get_file_type(const char *path); +NOBDEF bool nob_delete_file(const char *path); #define nob_return_defer(value) do { result = (value); goto defer; } while(0) @@ -359,8 +367,8 @@ typedef struct { size_t capacity; } Nob_String_Builder; -bool nob_read_entire_file(const char *path, Nob_String_Builder *sb); -int nob_sb_appendf(Nob_String_Builder *sb, const char *fmt, ...) NOB_PRINTF_FORMAT(2, 3); +NOBDEF bool nob_read_entire_file(const char *path, Nob_String_Builder *sb); +NOBDEF int nob_sb_appendf(Nob_String_Builder *sb, const char *fmt, ...) NOB_PRINTF_FORMAT(2, 3); // Append a sized buffer to a string builder #define nob_sb_append_buf(sb, buf, size) nob_da_append_many(sb, buf, size) @@ -393,9 +401,9 @@ typedef int Nob_Fd; #define NOB_INVALID_FD (-1) #endif // _WIN32 -Nob_Fd nob_fd_open_for_read(const char *path); -Nob_Fd nob_fd_open_for_write(const char *path); -void nob_fd_close(Nob_Fd fd); +NOBDEF Nob_Fd nob_fd_open_for_read(const char *path); +NOBDEF Nob_Fd nob_fd_open_for_write(const char *path); +NOBDEF void nob_fd_close(Nob_Fd fd); typedef struct { Nob_Proc *items; @@ -404,13 +412,13 @@ typedef struct { } Nob_Procs; // Wait until the process has finished -bool nob_proc_wait(Nob_Proc proc); +NOBDEF bool nob_proc_wait(Nob_Proc proc); // Wait until all the processes have finished -bool nob_procs_wait(Nob_Procs procs); +NOBDEF bool nob_procs_wait(Nob_Procs procs); // Wait until all the processes have finished and empty the procs array -bool nob_procs_wait_and_reset(Nob_Procs *procs); +NOBDEF bool nob_procs_wait_and_reset(Nob_Procs *procs); // Append a new process to procs array and if procs.count reaches max_procs_count call nob_procs_wait_and_reset() on it -bool nob_procs_append_with_flush(Nob_Procs *procs, Nob_Proc proc, size_t max_procs_count); +NOBDEF bool nob_procs_append_with_flush(Nob_Procs *procs, Nob_Proc proc, size_t max_procs_count); // A command - the main workhorse of Nob. Nob is all about building commands and running them typedef struct { @@ -441,7 +449,7 @@ typedef struct { // Render a string representation of a command into a string builder. Keep in mind the the // string builder is not NULL-terminated by default. Use nob_sb_append_null if you plan to // use it as a C string. -void nob_cmd_render(Nob_Cmd cmd, Nob_String_Builder *render); +NOBDEF void nob_cmd_render(Nob_Cmd cmd, Nob_String_Builder *render); // TODO: implement C++ support for nob.h #define nob_cmd_append(cmd, ...) \ @@ -459,28 +467,28 @@ void nob_cmd_render(Nob_Cmd cmd, Nob_String_Builder *render); #define nob_cmd_run_async(cmd) nob_cmd_run_async_redirect(cmd, (Nob_Cmd_Redirect) {0}) // NOTE: nob_cmd_run_async_and_reset() is just like nob_cmd_run_async() except it also resets cmd.count to 0 // so the Nob_Cmd instance can be seamlessly used several times in a row -Nob_Proc nob_cmd_run_async_and_reset(Nob_Cmd *cmd); +NOBDEF Nob_Proc nob_cmd_run_async_and_reset(Nob_Cmd *cmd); // Run redirected command asynchronously -Nob_Proc nob_cmd_run_async_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect); +NOBDEF Nob_Proc nob_cmd_run_async_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect); // Run redirected command asynchronously and set cmd.count to 0 and close all the opened files -Nob_Proc nob_cmd_run_async_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect); +NOBDEF Nob_Proc nob_cmd_run_async_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect); // Run command synchronously -bool nob_cmd_run_sync(Nob_Cmd cmd); +NOBDEF bool nob_cmd_run_sync(Nob_Cmd cmd); // NOTE: nob_cmd_run_sync_and_reset() is just like nob_cmd_run_sync() except it also resets cmd.count to 0 // so the Nob_Cmd instance can be seamlessly used several times in a row -bool nob_cmd_run_sync_and_reset(Nob_Cmd *cmd); +NOBDEF bool nob_cmd_run_sync_and_reset(Nob_Cmd *cmd); // Run redirected command synchronously -bool nob_cmd_run_sync_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect); +NOBDEF bool nob_cmd_run_sync_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect); // Run redirected command synchronously and set cmd.count to 0 and close all the opened files -bool nob_cmd_run_sync_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect); +NOBDEF bool nob_cmd_run_sync_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect); #ifndef NOB_TEMP_CAPACITY #define NOB_TEMP_CAPACITY (8*1024*1024) #endif // NOB_TEMP_CAPACITY -char *nob_temp_strdup(const char *cstr); -void *nob_temp_alloc(size_t size); -char *nob_temp_sprintf(const char *format, ...) NOB_PRINTF_FORMAT(1, 2); +NOBDEF char *nob_temp_strdup(const char *cstr); +NOBDEF void *nob_temp_alloc(size_t size); +NOBDEF char *nob_temp_sprintf(const char *format, ...) NOB_PRINTF_FORMAT(1, 2); // nob_temp_reset() - Resets the entire temporary storage to 0. // // It is generally not recommended to call this function ever. What you usually want to do is let's say you have a loop, @@ -502,19 +510,19 @@ char *nob_temp_sprintf(const char *format, ...) NOB_PRINTF_FORMAT(1, 2); // That way all the temporary allocations created before the loop are still valid even after the loop. // Such save/rewind blocks define lifetime boundaries of the temporary objects which also could be nested. // This turns the temporary storage into kind of a second stack with a more manual management. -void nob_temp_reset(void); -size_t nob_temp_save(void); -void nob_temp_rewind(size_t checkpoint); +NOBDEF void nob_temp_reset(void); +NOBDEF size_t nob_temp_save(void); +NOBDEF void nob_temp_rewind(size_t checkpoint); // Given any path returns the last part of that path. // "/path/to/a/file.c" -> "file.c"; "/path/to/a/directory" -> "directory" -const char *nob_path_name(const char *path); -bool nob_rename(const char *old_path, const char *new_path); -int nob_needs_rebuild(const char *output_path, const char **input_paths, size_t input_paths_count); -int nob_needs_rebuild1(const char *output_path, const char *input_path); -int nob_file_exists(const char *file_path); -const char *nob_get_current_dir_temp(void); -bool nob_set_current_dir(const char *path); +NOBDEF const char *nob_path_name(const char *path); +NOBDEF bool nob_rename(const char *old_path, const char *new_path); +NOBDEF int nob_needs_rebuild(const char *output_path, const char **input_paths, size_t input_paths_count); +NOBDEF int nob_needs_rebuild1(const char *output_path, const char *input_path); +NOBDEF int nob_file_exists(const char *file_path); +NOBDEF const char *nob_get_current_dir_temp(void); +NOBDEF bool nob_set_current_dir(const char *path); // TODO: we should probably document somewhere all the compiler we support @@ -538,7 +546,7 @@ bool nob_set_current_dir(const char *path); #ifndef nob_cc_flags # if defined(_MSC_VER) && !defined(__clang__) -# define nob_cc_flags(...) // TODO: Add some cool recommended flags for MSVC (I don't really know any) +# define nob_cc_flags(cmd) nob_cmd_append(cmd, "/W4", "/nologo", "/D_CRT_SECURE_NO_WARNINGS") # else # define nob_cc_flags(cmd) nob_cmd_append(cmd, "-Wall", "-Wextra") # endif @@ -585,7 +593,7 @@ bool nob_set_current_dir(const char *path); // return 0; // } // -// After your added this macro every time you run ./nob it will detect +// After you added this macro every time you run ./nob it will detect // that you modified its original source code and will try to rebuild itself // before doing any actual work. So you only need to bootstrap your build system // once. @@ -598,7 +606,7 @@ bool nob_set_current_dir(const char *path); // do not recommend since the whole idea of NoBuild is to keep the process of bootstrapping // as simple as possible and doing all of the actual work inside of ./nob) // -void nob__go_rebuild_urself(int argc, char **argv, const char *source_path, ...); +NOBDEF void nob__go_rebuild_urself(int argc, char **argv, const char *source_path, ...); #define NOB_GO_REBUILD_URSELF(argc, argv) nob__go_rebuild_urself(argc, argv, __FILE__, NULL) // Sometimes your nob.c includes additional files, so you want the Go Rebuild Urself™ Technology to check // if they also were modified and rebuild nob.c accordingly. For that we have NOB_GO_REBUILD_URSELF_PLUS(): @@ -622,18 +630,18 @@ typedef struct { const char *data; } Nob_String_View; -const char *nob_temp_sv_to_cstr(Nob_String_View sv); - -Nob_String_View nob_sv_chop_by_delim(Nob_String_View *sv, char delim); -Nob_String_View nob_sv_chop_left(Nob_String_View *sv, size_t n); -Nob_String_View nob_sv_trim(Nob_String_View sv); -Nob_String_View nob_sv_trim_left(Nob_String_View sv); -Nob_String_View nob_sv_trim_right(Nob_String_View sv); -bool nob_sv_eq(Nob_String_View a, Nob_String_View b); -bool nob_sv_end_with(Nob_String_View sv, const char *cstr); -bool nob_sv_starts_with(Nob_String_View sv, Nob_String_View expected_prefix); -Nob_String_View nob_sv_from_cstr(const char *cstr); -Nob_String_View nob_sv_from_parts(const char *data, size_t count); +NOBDEF const char *nob_temp_sv_to_cstr(Nob_String_View sv); + +NOBDEF Nob_String_View nob_sv_chop_by_delim(Nob_String_View *sv, char delim); +NOBDEF Nob_String_View nob_sv_chop_left(Nob_String_View *sv, size_t n); +NOBDEF Nob_String_View nob_sv_trim(Nob_String_View sv); +NOBDEF Nob_String_View nob_sv_trim_left(Nob_String_View sv); +NOBDEF Nob_String_View nob_sv_trim_right(Nob_String_View sv); +NOBDEF bool nob_sv_eq(Nob_String_View a, Nob_String_View b); +NOBDEF bool nob_sv_end_with(Nob_String_View sv, const char *cstr); +NOBDEF bool nob_sv_starts_with(Nob_String_View sv, Nob_String_View expected_prefix); +NOBDEF Nob_String_View nob_sv_from_cstr(const char *cstr); +NOBDEF Nob_String_View nob_sv_from_parts(const char *data, size_t count); // nob_sb_to_sv() enables you to just view Nob_String_Builder as Nob_String_View #define nob_sb_to_sv(sb) nob_sv_from_parts((sb).items, (sb).count) @@ -711,7 +719,7 @@ static int closedir(DIR *dirp); #ifdef _WIN32 -char *nob_win32_error_message(DWORD err); +NOBDEF char *nob_win32_error_message(DWORD err); #endif // _WIN32 @@ -732,7 +740,7 @@ Nob_Log_Level nob_minimal_log_level = NOB_INFO; #define NOB_WIN32_ERR_MSG_SIZE (4 * 1024) #endif // NOB_WIN32_ERR_MSG_SIZE -char *nob_win32_error_message(DWORD err) { +NOBDEF char *nob_win32_error_message(DWORD err) { static char win32ErrMsg[NOB_WIN32_ERR_MSG_SIZE] = {0}; DWORD errMsgSize = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, LANG_USER_DEFAULT, win32ErrMsg, NOB_WIN32_ERR_MSG_SIZE, NULL); @@ -763,7 +771,7 @@ char *nob_win32_error_message(DWORD err) { #endif // _WIN32 // The implementation idea is stolen from https://github.com/zhiayang/nabs -void nob__go_rebuild_urself(int argc, char **argv, const char *source_path, ...) +NOBDEF void nob__go_rebuild_urself(int argc, char **argv, const char *source_path, ...) { const char *binary_path = nob_shift(argv, argc); #ifdef _WIN32 @@ -818,7 +826,7 @@ void nob__go_rebuild_urself(int argc, char **argv, const char *source_path, ...) static size_t nob_temp_size = 0; static char nob_temp[NOB_TEMP_CAPACITY] = {0}; -bool nob_mkdir_if_not_exists(const char *path) +NOBDEF bool nob_mkdir_if_not_exists(const char *path) { #ifdef _WIN32 int result = _mkdir(path); @@ -838,7 +846,7 @@ bool nob_mkdir_if_not_exists(const char *path) return true; } -bool nob_copy_file(const char *src_path, const char *dst_path) +NOBDEF bool nob_copy_file(const char *src_path, const char *dst_path) { nob_log(NOB_INFO, "copying %s -> %s", src_path, dst_path); #ifdef _WIN32 @@ -900,7 +908,7 @@ bool nob_copy_file(const char *src_path, const char *dst_path) #endif } -void nob_cmd_render(Nob_Cmd cmd, Nob_String_Builder *render) +NOBDEF void nob_cmd_render(Nob_Cmd cmd, Nob_String_Builder *render) { for (size_t i = 0; i < cmd.count; ++i) { const char *arg = cmd.items[i]; @@ -959,7 +967,7 @@ static void nob__win32_cmd_quote(Nob_Cmd cmd, Nob_String_Builder *quoted) } #endif -Nob_Proc nob_cmd_run_async_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect) +NOBDEF Nob_Proc nob_cmd_run_async_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect) { if (cmd.count < 1) { nob_log(NOB_ERROR, "Could not run empty command"); @@ -1049,14 +1057,14 @@ Nob_Proc nob_cmd_run_async_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect) #endif } -Nob_Proc nob_cmd_run_async_and_reset(Nob_Cmd *cmd) +NOBDEF Nob_Proc nob_cmd_run_async_and_reset(Nob_Cmd *cmd) { Nob_Proc proc = nob_cmd_run_async(*cmd); cmd->count = 0; return proc; } -Nob_Proc nob_cmd_run_async_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect) +NOBDEF Nob_Proc nob_cmd_run_async_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect) { Nob_Proc proc = nob_cmd_run_async_redirect(*cmd, redirect); cmd->count = 0; @@ -1075,7 +1083,7 @@ Nob_Proc nob_cmd_run_async_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect red return proc; } -Nob_Fd nob_fd_open_for_read(const char *path) +NOBDEF Nob_Fd nob_fd_open_for_read(const char *path) { #ifndef _WIN32 Nob_Fd result = open(path, O_RDONLY); @@ -1108,7 +1116,7 @@ Nob_Fd nob_fd_open_for_read(const char *path) #endif // _WIN32 } -Nob_Fd nob_fd_open_for_write(const char *path) +NOBDEF Nob_Fd nob_fd_open_for_write(const char *path) { #ifndef _WIN32 Nob_Fd result = open(path, @@ -1143,7 +1151,7 @@ Nob_Fd nob_fd_open_for_write(const char *path) #endif // _WIN32 } -void nob_fd_close(Nob_Fd fd) +NOBDEF void nob_fd_close(Nob_Fd fd) { #ifdef _WIN32 CloseHandle(fd); @@ -1152,7 +1160,7 @@ void nob_fd_close(Nob_Fd fd) #endif // _WIN32 } -bool nob_procs_wait(Nob_Procs procs) +NOBDEF bool nob_procs_wait(Nob_Procs procs) { bool success = true; for (size_t i = 0; i < procs.count; ++i) { @@ -1161,14 +1169,14 @@ bool nob_procs_wait(Nob_Procs procs) return success; } -bool nob_procs_wait_and_reset(Nob_Procs *procs) +NOBDEF bool nob_procs_wait_and_reset(Nob_Procs *procs) { bool success = nob_procs_wait(*procs); procs->count = 0; return success; } -bool nob_proc_wait(Nob_Proc proc) +NOBDEF bool nob_proc_wait(Nob_Proc proc) { if (proc == NOB_INVALID_PROC) return false; @@ -1225,7 +1233,7 @@ bool nob_proc_wait(Nob_Proc proc) #endif } -bool nob_procs_append_with_flush(Nob_Procs *procs, Nob_Proc proc, size_t max_procs_count) +NOBDEF bool nob_procs_append_with_flush(Nob_Procs *procs, Nob_Proc proc, size_t max_procs_count) { nob_da_append(procs, proc); @@ -1236,28 +1244,28 @@ bool nob_procs_append_with_flush(Nob_Procs *procs, Nob_Proc proc, size_t max_pro return true; } -bool nob_cmd_run_sync_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect) +NOBDEF bool nob_cmd_run_sync_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect) { Nob_Proc p = nob_cmd_run_async_redirect(cmd, redirect); if (p == NOB_INVALID_PROC) return false; return nob_proc_wait(p); } -bool nob_cmd_run_sync(Nob_Cmd cmd) +NOBDEF bool nob_cmd_run_sync(Nob_Cmd cmd) { Nob_Proc p = nob_cmd_run_async(cmd); if (p == NOB_INVALID_PROC) return false; return nob_proc_wait(p); } -bool nob_cmd_run_sync_and_reset(Nob_Cmd *cmd) +NOBDEF bool nob_cmd_run_sync_and_reset(Nob_Cmd *cmd) { bool p = nob_cmd_run_sync(*cmd); cmd->count = 0; return p; } -bool nob_cmd_run_sync_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect) +NOBDEF bool nob_cmd_run_sync_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect) { bool p = nob_cmd_run_sync_redirect(*cmd, redirect); cmd->count = 0; @@ -1276,7 +1284,7 @@ bool nob_cmd_run_sync_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect return p; } -void nob_log(Nob_Log_Level level, const char *fmt, ...) +NOBDEF void nob_log(Nob_Log_Level level, const char *fmt, ...) { if (level < nob_minimal_log_level) return; @@ -1302,7 +1310,7 @@ void nob_log(Nob_Log_Level level, const char *fmt, ...) fprintf(stderr, "\n"); } -bool nob_read_entire_dir(const char *parent, Nob_File_Paths *children) +NOBDEF bool nob_read_entire_dir(const char *parent, Nob_File_Paths *children) { bool result = true; DIR *dir = NULL; @@ -1338,7 +1346,7 @@ bool nob_read_entire_dir(const char *parent, Nob_File_Paths *children) return result; } -bool nob_write_entire_file(const char *path, const void *data, size_t size) +NOBDEF bool nob_write_entire_file(const char *path, const void *data, size_t size) { bool result = true; @@ -1370,7 +1378,7 @@ bool nob_write_entire_file(const char *path, const void *data, size_t size) return result; } -Nob_File_Type nob_get_file_type(const char *path) +NOBDEF Nob_File_Type nob_get_file_type(const char *path) { #ifdef _WIN32 DWORD attr = GetFileAttributesA(path); @@ -1396,7 +1404,7 @@ Nob_File_Type nob_get_file_type(const char *path) #endif // _WIN32 } -bool nob_delete_file(const char *path) +NOBDEF bool nob_delete_file(const char *path) { nob_log(NOB_INFO, "deleting %s", path); #ifdef _WIN32 @@ -1414,7 +1422,7 @@ bool nob_delete_file(const char *path) #endif // _WIN32 } -bool nob_copy_directory_recursively(const char *src_path, const char *dst_path) +NOBDEF bool nob_copy_directory_recursively(const char *src_path, const char *dst_path) { bool result = true; Nob_File_Paths children = {0}; @@ -1478,7 +1486,7 @@ bool nob_copy_directory_recursively(const char *src_path, const char *dst_path) return result; } -char *nob_temp_strdup(const char *cstr) +NOBDEF char *nob_temp_strdup(const char *cstr) { size_t n = strlen(cstr); char *result = nob_temp_alloc(n + 1); @@ -1488,7 +1496,7 @@ char *nob_temp_strdup(const char *cstr) return result; } -void *nob_temp_alloc(size_t requested_size) +NOBDEF void *nob_temp_alloc(size_t requested_size) { size_t word_size = sizeof(uintptr_t); size_t size = (requested_size + word_size - 1)/word_size*word_size; @@ -1498,7 +1506,7 @@ void *nob_temp_alloc(size_t requested_size) return result; } -char *nob_temp_sprintf(const char *format, ...) +NOBDEF char *nob_temp_sprintf(const char *format, ...) { va_list args; va_start(args, format); @@ -1516,22 +1524,22 @@ char *nob_temp_sprintf(const char *format, ...) return result; } -void nob_temp_reset(void) +NOBDEF void nob_temp_reset(void) { nob_temp_size = 0; } -size_t nob_temp_save(void) +NOBDEF size_t nob_temp_save(void) { return nob_temp_size; } -void nob_temp_rewind(size_t checkpoint) +NOBDEF void nob_temp_rewind(size_t checkpoint) { nob_temp_size = checkpoint; } -const char *nob_temp_sv_to_cstr(Nob_String_View sv) +NOBDEF const char *nob_temp_sv_to_cstr(Nob_String_View sv) { char *result = nob_temp_alloc(sv.count + 1); NOB_ASSERT(result != NULL && "Extend the size of the temporary allocator"); @@ -1540,7 +1548,7 @@ const char *nob_temp_sv_to_cstr(Nob_String_View sv) return result; } -int nob_needs_rebuild(const char *output_path, const char **input_paths, size_t input_paths_count) +NOBDEF int nob_needs_rebuild(const char *output_path, const char **input_paths, size_t input_paths_count) { #ifdef _WIN32 BOOL bSuccess; @@ -1608,12 +1616,12 @@ int nob_needs_rebuild(const char *output_path, const char **input_paths, size_t #endif } -int nob_needs_rebuild1(const char *output_path, const char *input_path) +NOBDEF int nob_needs_rebuild1(const char *output_path, const char *input_path) { return nob_needs_rebuild(output_path, &input_path, 1); } -const char *nob_path_name(const char *path) +NOBDEF const char *nob_path_name(const char *path) { #ifdef _WIN32 const char *p1 = strrchr(path, '/'); @@ -1626,7 +1634,7 @@ const char *nob_path_name(const char *path) #endif // _WIN32 } -bool nob_rename(const char *old_path, const char *new_path) +NOBDEF bool nob_rename(const char *old_path, const char *new_path) { nob_log(NOB_INFO, "renaming %s -> %s", old_path, new_path); #ifdef _WIN32 @@ -1643,7 +1651,7 @@ bool nob_rename(const char *old_path, const char *new_path) return true; } -bool nob_read_entire_file(const char *path, Nob_String_Builder *sb) +NOBDEF bool nob_read_entire_file(const char *path, Nob_String_Builder *sb) { bool result = true; @@ -1678,7 +1686,7 @@ bool nob_read_entire_file(const char *path, Nob_String_Builder *sb) return result; } -int nob_sb_appendf(Nob_String_Builder *sb, const char *fmt, ...) +NOBDEF int nob_sb_appendf(Nob_String_Builder *sb, const char *fmt, ...) { va_list args; @@ -1700,7 +1708,7 @@ int nob_sb_appendf(Nob_String_Builder *sb, const char *fmt, ...) return n; } -Nob_String_View nob_sv_chop_by_delim(Nob_String_View *sv, char delim) +NOBDEF Nob_String_View nob_sv_chop_by_delim(Nob_String_View *sv, char delim) { size_t i = 0; while (i < sv->count && sv->data[i] != delim) { @@ -1720,7 +1728,7 @@ Nob_String_View nob_sv_chop_by_delim(Nob_String_View *sv, char delim) return result; } -Nob_String_View nob_sv_chop_left(Nob_String_View *sv, size_t n) +NOBDEF Nob_String_View nob_sv_chop_left(Nob_String_View *sv, size_t n) { if (n > sv->count) { n = sv->count; @@ -1734,7 +1742,7 @@ Nob_String_View nob_sv_chop_left(Nob_String_View *sv, size_t n) return result; } -Nob_String_View nob_sv_from_parts(const char *data, size_t count) +NOBDEF Nob_String_View nob_sv_from_parts(const char *data, size_t count) { Nob_String_View sv; sv.count = count; @@ -1742,7 +1750,7 @@ Nob_String_View nob_sv_from_parts(const char *data, size_t count) return sv; } -Nob_String_View nob_sv_trim_left(Nob_String_View sv) +NOBDEF Nob_String_View nob_sv_trim_left(Nob_String_View sv) { size_t i = 0; while (i < sv.count && isspace(sv.data[i])) { @@ -1752,7 +1760,7 @@ Nob_String_View nob_sv_trim_left(Nob_String_View sv) return nob_sv_from_parts(sv.data + i, sv.count - i); } -Nob_String_View nob_sv_trim_right(Nob_String_View sv) +NOBDEF Nob_String_View nob_sv_trim_right(Nob_String_View sv) { size_t i = 0; while (i < sv.count && isspace(sv.data[sv.count - 1 - i])) { @@ -1762,17 +1770,17 @@ Nob_String_View nob_sv_trim_right(Nob_String_View sv) return nob_sv_from_parts(sv.data, sv.count - i); } -Nob_String_View nob_sv_trim(Nob_String_View sv) +NOBDEF Nob_String_View nob_sv_trim(Nob_String_View sv) { return nob_sv_trim_right(nob_sv_trim_left(sv)); } -Nob_String_View nob_sv_from_cstr(const char *cstr) +NOBDEF Nob_String_View nob_sv_from_cstr(const char *cstr) { return nob_sv_from_parts(cstr, strlen(cstr)); } -bool nob_sv_eq(Nob_String_View a, Nob_String_View b) +NOBDEF bool nob_sv_eq(Nob_String_View a, Nob_String_View b) { if (a.count != b.count) { return false; @@ -1781,7 +1789,7 @@ bool nob_sv_eq(Nob_String_View a, Nob_String_View b) } } -bool nob_sv_end_with(Nob_String_View sv, const char *cstr) +NOBDEF bool nob_sv_end_with(Nob_String_View sv, const char *cstr) { size_t cstr_count = strlen(cstr); if (sv.count >= cstr_count) { @@ -1793,7 +1801,7 @@ bool nob_sv_end_with(Nob_String_View sv, const char *cstr) } -bool nob_sv_starts_with(Nob_String_View sv, Nob_String_View expected_prefix) +NOBDEF bool nob_sv_starts_with(Nob_String_View sv, Nob_String_View expected_prefix) { if (expected_prefix.count <= sv.count) { Nob_String_View actual_prefix = nob_sv_from_parts(sv.data, expected_prefix.count); @@ -1807,7 +1815,7 @@ bool nob_sv_starts_with(Nob_String_View sv, Nob_String_View expected_prefix) // 0 - file does not exists // 1 - file exists // -1 - error while checking if file exists. The error is logged -int nob_file_exists(const char *file_path) +NOBDEF int nob_file_exists(const char *file_path) { #if _WIN32 // TODO: distinguish between "does not exists" and other errors @@ -1824,7 +1832,7 @@ int nob_file_exists(const char *file_path) #endif } -const char *nob_get_current_dir_temp(void) +NOBDEF const char *nob_get_current_dir_temp(void) { #ifdef _WIN32 DWORD nBufferLength = GetCurrentDirectory(0, NULL); @@ -1851,7 +1859,7 @@ const char *nob_get_current_dir_temp(void) #endif // _WIN32 } -bool nob_set_current_dir(const char *path) +NOBDEF bool nob_set_current_dir(const char *path) { #ifdef _WIN32 if (!SetCurrentDirectory(path)) { @@ -1877,7 +1885,7 @@ struct DIR struct dirent *dirent; }; -DIR *opendir(const char *dirpath) +NOBDEF DIR *opendir(const char *dirpath) { NOB_ASSERT(dirpath); @@ -1905,7 +1913,7 @@ DIR *opendir(const char *dirpath) return NULL; } -struct dirent *readdir(DIR *dirp) +NOBDEF struct dirent *readdir(DIR *dirp) { NOB_ASSERT(dirp); @@ -1934,7 +1942,7 @@ struct dirent *readdir(DIR *dirp) return dirp->dirent; } -int closedir(DIR *dirp) +NOBDEF int closedir(DIR *dirp) { NOB_ASSERT(dirp); @@ -2071,6 +2079,8 @@ int closedir(DIR *dirp) /* Revision history: + 1.22.0 (2025-08-12) Add NOBDEF macro to the beginning of function declarations (by @minefreak19) + Add more flags to MSVC nob_cc_flags() (by @PieVieRo) 1.21.0 (2025-08-11) Add NOB_NO_MINIRENT guard for "minirent.h" (by @fietec) 1.20.9 (2025-08-11) Fix warnings on Windows: Define _CRT_SECURE_NO_WARNINGS, Rename mkdir to _mkdir (by @OetkenPurveyorOfCode) 1.20.8 (2025-08-11) Fix the bug with nob_get_file_type() not identifying symlinks correctly on POSIX (By @samuellieberman) diff --git a/shared.h b/shared.h index d80b1463..c5a235d8 100644 --- a/shared.h +++ b/shared.h @@ -9,7 +9,7 @@ #define TESTS_FOLDER "tests/" #if defined(_MSC_VER) -# define nob_cc_flags(cmd) cmd_append(cmd, "-I.") +# define nob_cc_flags(cmd) cmd_append(cmd, "/W4", "/nologo", "/D_CRT_SECURE_NO_WARNINGS", "-I.") #elif defined(__APPLE__) || defined(__MACH__) // TODO: "-std=c99", "-D_POSIX_C_SOURCE=200112L" didn't work for MacOS, don't know why, don't really care that much at the moment. // Anybody who does feel free to investigate.