1- /* nob - v1.26 .0 - Public Domain - https://github.com/tsoding/nob.h
1+ /* nob - v1.27 .0 - Public Domain - https://github.com/tsoding/nob.h
22
33 This library is the next generation of the [NoBuild](https://github.com/tsoding/nobuild) idea.
44
5050 }
5151 ```
5252
53- Not all the names have strippable prefixes. All the redefinable names like `NOB_GO_REBUILD_URSELF `
53+ Not all the names have strippable prefixes. All the redefinable names like `NOB_REBUILD_URSELF `
5454 for instance will retain their prefix even if NOB_STRIP_PREFIX is enabled. Notable exception is the
5555 nob_log() function. Stripping away the prefix results in log() which was historically always referring
5656 to the natural logarithmic function that is already defined in math.h. So there is no reason to strip
166166# ifdef __APPLE__
167167# include <mach-o/dyld.h>
168168# endif
169+ # ifdef __FreeBSD__
170+ # include <sys/sysctl.h>
171+ # endif
169172# include <sys/types.h>
170173# include <sys/wait.h>
171174# include <sys/stat.h>
@@ -423,6 +426,8 @@ typedef struct {
423426 Nob_Procs * async ;
424427 // Maximum processes allowed in the .async list. Zero implies nob_nprocs().
425428 size_t max_procs ;
429+ // Do not reset the command after execution.
430+ bool dont_reset ;
426431 // Redirect stdin to file
427432 const char * stdin_path ;
428433 // Redirect stdout to file
@@ -494,7 +499,7 @@ NOBDEF void nob_cmd_render(Nob_Cmd cmd, Nob_String_Builder *render);
494499#define nob_cmd_free (cmd ) NOB_FREE(cmd.items)
495500
496501// Run command asynchronously
497- NOB_DEPRECATED ("Use `nob_cmd_run(&cmd, .async = &procs)` instead, but keep in mind that it always resets the cmd array ." )
502+ NOB_DEPRECATED ("Use `nob_cmd_run(&cmd, .async = &procs, .dont_reset = true)` ." )
498503NOBDEF Nob_Proc nob_cmd_run_async (Nob_Cmd cmd );
499504
500505// nob_cmd_run_async_and_reset() is just like nob_cmd_run_async() except it also resets cmd.count to 0
@@ -507,8 +512,9 @@ NOB_DEPRECATED("Use `nob_cmd_run(&cmd, "
507512 ".async = &procs, "
508513 ".stdin_path = \"path/to/stdin\", "
509514 ".stdout_path = \"path/to/stdout\", "
510- ".stderr_path = \"path/to/stderr\")` instead, "
511- "but keep in mind that it always resets the cmd array." )
515+ ".stderr_path = \"path/to/stderr\", "
516+ ".dont_reset = true"
517+ ")` instead." )
512518NOBDEF Nob_Proc nob_cmd_run_async_redirect (Nob_Cmd cmd , Nob_Cmd_Redirect redirect );
513519
514520// Run redirected command asynchronously and set cmd.count to 0 and close all the opened files
@@ -520,8 +526,7 @@ NOB_DEPRECATED("Use `nob_cmd_run(&cmd, "
520526NOBDEF Nob_Proc nob_cmd_run_async_redirect_and_reset (Nob_Cmd * cmd , Nob_Cmd_Redirect redirect );
521527
522528// Run command synchronously
523- NOB_DEPRECATED ("Use `nob_cmd_run(&cmd)` instead, "
524- "but keep in mind that it always resets the cmd array." )
529+ NOB_DEPRECATED ("Use `nob_cmd_run(&cmd, .dont_reset = true)` instead." )
525530NOBDEF bool nob_cmd_run_sync (Nob_Cmd cmd );
526531
527532// NOTE: nob_cmd_run_sync_and_reset() is just like nob_cmd_run_sync() except it also resets cmd.count to 0
@@ -533,8 +538,9 @@ NOBDEF bool nob_cmd_run_sync_and_reset(Nob_Cmd *cmd);
533538NOB_DEPRECATED ("Use `nob_cmd_run(&cmd, "
534539 ".stdin_path = \"path/to/stdin\", "
535540 ".stdout_path = \"path/to/stdout\", "
536- ".stderr_path = \"path/to/stderr\")` instead, "
537- "but keep in mind that it always resets the cmd array." )
541+ ".stderr_path = \"path/to/stderr\", "
542+ ".dont_reset = true"
543+ ")` instead." )
538544NOBDEF bool nob_cmd_run_sync_redirect (Nob_Cmd cmd , Nob_Cmd_Redirect redirect );
539545
540546// Run redirected command synchronously and set cmd.count to 0 and close all the opened files
@@ -622,7 +628,7 @@ NOBDEF char *nob_temp_running_executable_path(void);
622628
623629#ifndef nob_cc_output
624630# if defined(_MSC_VER ) && !defined(__clang__ )
625- # define nob_cc_output (cmd , output_path ) nob_cmd_append(cmd, nob_temp_sprintf("/Fe:%s", (output_path)))
631+ # define nob_cc_output (cmd , output_path ) nob_cmd_append(cmd, nob_temp_sprintf("/Fe:%s", (output_path)), nob_temp_sprintf("/Fo:%s", (output_path)) )
626632# else
627633# define nob_cc_output (cmd , output_path ) nob_cmd_append(cmd, "-o", (output_path))
628634# endif
@@ -1115,7 +1121,7 @@ NOBDEF bool nob_cmd_run_opt(Nob_Cmd *cmd, Nob_Cmd_Opt opt)
11151121 if (opt_fdin ) nob_fd_close (* opt_fdin );
11161122 if (opt_fdout ) nob_fd_close (* opt_fdout );
11171123 if (opt_fderr ) nob_fd_close (* opt_fderr );
1118- cmd -> count = 0 ;
1124+ if (! opt . dont_reset ) cmd -> count = 0 ;
11191125 return result ;
11201126}
11211127
@@ -1154,8 +1160,8 @@ static Nob_Proc nob__cmd_start_process(Nob_Cmd cmd, Nob_Fd *fdin, Nob_Fd *fdout,
11541160 return NOB_INVALID_PROC ;
11551161 }
11561162
1157- Nob_String_Builder sb = {0 };
11581163#ifndef NOB_NO_ECHO
1164+ Nob_String_Builder sb = {0 };
11591165 nob_cmd_render (cmd , & sb );
11601166 nob_sb_append_null (& sb );
11611167 nob_log (NOB_INFO , "CMD: %s" , sb .items );
@@ -1180,10 +1186,11 @@ static Nob_Proc nob__cmd_start_process(Nob_Cmd cmd, Nob_Fd *fdin, Nob_Fd *fdout,
11801186 PROCESS_INFORMATION piProcInfo ;
11811187 ZeroMemory (& piProcInfo , sizeof (PROCESS_INFORMATION ));
11821188
1183- nob__win32_cmd_quote (cmd , & sb );
1184- nob_sb_append_null (& sb );
1185- BOOL bSuccess = CreateProcessA (NULL , sb .items , NULL , NULL , TRUE, 0 , NULL , NULL , & siStartInfo , & piProcInfo );
1186- nob_sb_free (sb );
1189+ Nob_String_Builder quoted = {0 };
1190+ nob__win32_cmd_quote (cmd , & quoted );
1191+ nob_sb_append_null (& quoted );
1192+ BOOL bSuccess = CreateProcessA (NULL , quoted .items , NULL , NULL , TRUE, 0 , NULL , NULL , & siStartInfo , & piProcInfo );
1193+ nob_sb_free (quoted );
11871194
11881195 if (!bSuccess ) {
11891196 nob_log (NOB_ERROR , "Could not create child process for %s: %s" , cmd .items [0 ], nob_win32_error_message (GetLastError ()));
@@ -2284,6 +2291,12 @@ NOBDEF char *nob_temp_running_executable_path(void)
22842291 if (_NSGetExecutablePath (buf , & size ) != 0 ) return "" ;
22852292 int length = strlen (buf );
22862293 return nob_temp_strndup (buf , length );
2294+ #elif defined(__FreeBSD__ )
2295+ char buf [4096 ];
2296+ int mib [4 ] = { CTL_KERN , KERN_PROC , KERN_PROC_PATHNAME , -1 };
2297+ size_t length = sizeof (buf );
2298+ if (sysctl (mib , 4 , buf , & length , NULL , 0 ) < 0 ) return "" ;
2299+ return nob_temp_strndup (buf , length );
22872300#else
22882301 fprintf (stderr , "%s:%d: TODO: nob_temp_running_executable_path is not implemented for this platform\n" , __FILE__ , __LINE__ );
22892302 return "" ;
@@ -2409,6 +2422,8 @@ NOBDEF int closedir(DIR *dirp)
24092422 // #define log nob_log
24102423 #define shift nob_shift
24112424 #define shift_args nob_shift_args
2425+ #define GO_REBUILD_URSELF NOB_GO_REBUILD_URSELF
2426+ #define GO_REBUILD_URSELF_PLUS NOB_GO_REBUILD_URSELF_PLUS
24122427 #define File_Paths Nob_File_Paths
24132428 #define FILE_REGULAR NOB_FILE_REGULAR
24142429 #define FILE_DIRECTORY NOB_FILE_DIRECTORY
@@ -2513,6 +2528,10 @@ NOBDEF int closedir(DIR *dirp)
25132528/*
25142529 Revision history:
25152530
2531+ 1.27.0 (2025-12-30) Add .dot_reset option to cmd_run (by @Israel77)
2532+ Fix support for FreeBSD (by @cqundefine)
2533+ Strip prefixes from NOB_GO_REBUILD_URSELF and NOB_GO_REBUILD_URSELF_PLUS (by @huwwa)
2534+ Add /Fo flag to MSVC version of nob_cc_output() (by @ratchetfreak)
25162535 1.26.0 (2025-12-28) Introduce customizable log handlers (by @rexim)
25172536 - Add nob_log_handler
25182537 - Add nob_set_log_handler
0 commit comments