From 6331282b8e9d1d371d70fd56022cc9f835b524c1 Mon Sep 17 00:00:00 2001 From: "Fernando J. Iglesias Garcia" Date: Sat, 27 Dec 2025 20:03:58 +0100 Subject: [PATCH 1/4] Update CI compilation flags for nob --- .github/workflows/nob.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nob.yml b/.github/workflows/nob.yml index 915c207..537c65e 100644 --- a/.github/workflows/nob.yml +++ b/.github/workflows/nob.yml @@ -17,5 +17,5 @@ jobs: - name: Build & Test run: | - g++ -std=c++20 -ggdb -fsanitize=address,pointer-overflow,signed-integer-overflow,undefined -o nob nob.cpp + g++ -std=c++23 -fsanitize=address,undefined -fsanitize-address-use-after-scope -D_GLIBCXX_DEBUG -o nob nob.cpp ./nob From 699715b11cd0085eca0b8479565ad83d0d635673 Mon Sep 17 00:00:00 2001 From: "Fernando J. Iglesias Garcia" Date: Sat, 27 Dec 2025 20:08:05 +0100 Subject: [PATCH 2/4] Update INFO message location --- nob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nob.cpp b/nob.cpp index 8e3ecbc..d1a7904 100644 --- a/nob.cpp +++ b/nob.cpp @@ -23,13 +23,13 @@ template auto make_cmd(const std::array& strings) Cmd cmd; cmd.line.reserve(strings.size()); for (size_t i = 0; i < N; i++) cmd.line.push_back(std::string{strings[i]}); + INFO("make_cmd: %s", cmd_show(cmd).c_str()); return cmd; } template void make_and_run_cmd(const std::array& strings) { const auto& cmd = make_cmd(strings); - INFO("make_and_run_cmd: %s", cmd_show(cmd).c_str()); cmd_run_sync(cmd); } From 4facd679691bb51ffcce9c02f7162a2108243d7b Mon Sep 17 00:00:00 2001 From: "Fernando J. Iglesias Garcia" Date: Sat, 27 Dec 2025 20:09:49 +0100 Subject: [PATCH 3/4] Remove unused code --- nob.h | 298 ---------------------------------------------------------- 1 file changed, 298 deletions(-) diff --git a/nob.h b/nob.h index 1f4554f..06a1dbd 100644 --- a/nob.h +++ b/nob.h @@ -53,9 +53,6 @@ typedef int Fd; using Cstr_Array = std::vector; -bool cstr_ends_with(const char* cstr, const char* postfix); -#define ENDS_WITH(cstr, postfix) cstr_ends_with(cstr, postfix) - std::string cstr_no_ext(const char* path); #define NOEXT(path) cstr_no_ext(path) @@ -72,15 +69,6 @@ std::string cstr_array_join(const char* sep, const Cstr_Array &cstrs); #define JOIN(sep, ...) cstr_array_join(sep, cstr_array_make(__VA_ARGS__)) #define CONCAT(...) JOIN("", __VA_ARGS__) #define PATH(...) JOIN(PATH_SEP, __VA_ARGS__) -#define GETCWD() path_get_current_dir() -#define SETCWD(path) path_set_current_dir(path) - -typedef struct { - Fd read; - Fd write; -} Pipe; - -Pipe pipe_make(void); typedef struct { Cstr_Array line; @@ -104,57 +92,6 @@ typedef std::vector Cmd_Array; cmd_run_sync(cmd); \ } while (0) -typedef enum { - CHAIN_TOKEN_END = 0, - CHAIN_TOKEN_IN, - CHAIN_TOKEN_OUT, - CHAIN_TOKEN_CMD -} Chain_Token_Type; - -// A single token for the CHAIN(...) DSL syntax -typedef struct { - Chain_Token_Type type; - Cstr_Array args; -} Chain_Token; - -// TODO(#17): IN and OUT are already taken by WinAPI -#define IN(path) \ - (Chain_Token) { \ - .type = CHAIN_TOKEN_IN, \ - .args = cstr_array_make(path) \ - } - -#define OUT(path) \ - (Chain_Token) { \ - .type = CHAIN_TOKEN_OUT, \ - .args = cstr_array_make(path) \ - } - -#define CHAIN_CMD(...) \ - (Chain_Token) { \ - .type = CHAIN_TOKEN_CMD, \ - .args = cstr_array_make(__VA_ARGS__) \ - } - -// TODO(#20): pipes do not allow redirecting stderr -struct Chain { - std::optional input_filepath; - Cmd_Array cmds; - std::optional output_filepath; -}; - -Chain chain_build_from_tokens(Chain_Token first, ...); -void chain_run_sync(const Chain &chain); -void chain_echo(const Chain &chain); - -// TODO(#15): PIPE does not report where exactly a syntactic error has happened -#define CHAIN(...) \ - do { \ - Chain chain = chain_build_from_tokens(__VA_ARGS__, (Chain_Token) {0}); \ - chain_echo(chain); \ - chain_run_sync(chain); \ - } while(0) - #ifndef REBUILD_URSELF # define REBUILD_URSELF(binary_path, source_path) CMD("g++", "-std=c++20", "-o", binary_path, source_path) #endif @@ -203,20 +140,6 @@ void chain_echo(const Chain &chain); void rebuild_urself(const char *binary_path, const char *source_path); -bool path_is_dir(const char* path); -#define IS_DIR(path) path_is_dir(path) - -bool path_exists(const char* path); -#define PATH_EXISTS(path) path_exists(path) - -void path_mkdirs(const Cstr_Array &path); -#define MKDIRS(...) \ - do { \ - Cstr_Array path = cstr_array_make(__VA_ARGS__); \ - INFO("MKDIRS: %s", cstr_array_join(PATH_SEP, path).c_str()); \ - path_mkdirs(path); \ - } while (0) - void path_rename(const char* old_path, const char* new_path); #define RENAME(old_path, new_path) \ do { \ @@ -224,15 +147,6 @@ void path_rename(const char* old_path, const char* new_path); path_rename(old_path, new_path); \ } while (0) -void path_rm(const char* path); -#define RM(path) \ - do { \ - INFO("RM: %s", path); \ - path_rm(path); \ - } while(0) - - - #if defined(__GNUC__) || defined(__clang__) // https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html #define NOBUILD_PRINTF_FORMAT(STRING_INDEX, FIRST_TO_CHECK) __attribute__ ((format (printf, STRING_INDEX, FIRST_TO_CHECK))) @@ -259,16 +173,6 @@ Cstr_Array cstr_array_from_int_char(int argc, char** argv) return result; } -bool cstr_ends_with(const char* cstr, const char* postfix) -{ - std::string_view s(cstr); - std::string_view p(postfix); - if (s.length() < p.length()) { - return false; - } - return s.substr(s.length() - p.length()) == p; -} - std::string cstr_no_ext(const char* path) { std::string_view p(path); @@ -291,21 +195,6 @@ std::string cstr_array_join(const char* sep, const Cstr_Array &cstrs) return ss.str(); } -Pipe pipe_make(void) -{ - Pipe pip = {0}; - - Fd pipefd[2]; - if (pipe(pipefd) < 0) { - PANIC("Could not create pipe: %s", strerror(errno)); - } - - pip.read = pipefd[0]; - pip.write = pipefd[1]; - - return pip; -} - Fd fd_open_for_read(const char* path) { Fd result = open(path, O_RDONLY); @@ -406,166 +295,6 @@ void cmd_run_sync(Cmd cmd) pid_wait(cmd_run_async(cmd, NULL, NULL)); } -Chain chain_build_from_tokens(Chain_Token first, ...) -{ - Chain result; - - auto process_token = [&](Chain_Token token) { - switch (token.type) { - case CHAIN_TOKEN_CMD: { - result.cmds.push_back({.line = token.args}); - } - break; - - case CHAIN_TOKEN_IN: { - if (result.input_filepath) { - PANIC("Input file path was already set"); - } - result.input_filepath = token.args.front(); - } - break; - - case CHAIN_TOKEN_OUT: { - if (result.output_filepath) { - PANIC("Output file path was already set"); - } - result.output_filepath = token.args.front(); - } - break; - - case CHAIN_TOKEN_END: - default: { - assert(0 && "unreachable"); - exit(1); - } - } - }; - - process_token(first); - - va_list args; - va_start(args, first); - Chain_Token next = va_arg(args, Chain_Token); - while (next.type != CHAIN_TOKEN_END) { - process_token(next); - next = va_arg(args, Chain_Token); - } - va_end(args); - - return result; -} - -void chain_run_sync(const Chain &chain) -{ - if (chain.cmds.empty()) { - return; - } - - std::vector cpids; - cpids.reserve(chain.cmds.size()); - - Fd fdin = -1; - if (chain.input_filepath) { - fdin = fd_open_for_read(chain.input_filepath->c_str()); - } - - for (size_t i = 0; i < chain.cmds.size(); ++i) { - Fd* fdin_ptr = (fdin != -1) ? &fdin : nullptr; - bool is_last = (i == chain.cmds.size() - 1); - - if (is_last) { - Fd fdout = -1; - if (chain.output_filepath) { - fdout = fd_open_for_write(chain.output_filepath->c_str()); - } - Fd* fdout_ptr = (fdout != -1) ? &fdout : nullptr; - - cpids.push_back(cmd_run_async(chain.cmds[i], fdin_ptr, fdout_ptr)); - - if (fdin != -1) close(fdin); - if (fdout != -1) close(fdout); - } else { - int pipefd[2]; - if (pipe(pipefd) < 0) { - PANIC("Could not create pipe: %s", strerror(errno)); - } - Fd read_end = pipefd[0]; - Fd write_end = pipefd[1]; - - cpids.push_back(cmd_run_async(chain.cmds[i], fdin_ptr, &write_end)); - - if (fdin != -1) close(fdin); - close(write_end); - fdin = read_end; - } - } - - for (const auto &cpid : cpids) { - pid_wait(cpid); - } -} - -void chain_echo(const Chain &chain) -{ - std::cout << "[INFO] CHAIN:"; - if (chain.input_filepath) { - std::cout << " " << *chain.input_filepath; - } - - for (const auto &cmd : chain.cmds) { - std::cout << " |> " << cmd_show(cmd); - } - - if (chain.output_filepath) { - std::cout << " |> " << *chain.output_filepath; - } - - std::cout << std::endl; -} - -std::string path_get_current_dir() -{ - std::error_code ec; - auto path = std::filesystem::current_path(ec); - if (ec) { - PANIC("could not get current directory: %s", ec.message().c_str()); - } - return path.string(); -} - -void path_set_current_dir(const char* path) -{ - std::error_code ec; - std::filesystem::current_path(path, ec); - if (ec) { - PANIC("could not set current directory to %s: %s", - path, ec.message().c_str()); - } -} - -bool path_exists(const char* path) -{ - std::error_code ec; - bool result = std::filesystem::exists(path, ec); - if (ec) { - PANIC("could not check existence of path %s: %s", path, ec.message().c_str()); - } - return result; -} - -bool path_is_dir(const char* path) -{ - std::error_code ec; - bool result = std::filesystem::is_directory(path, ec); - if (ec) { - if (ec.value() == ENOENT) { - return false; - } - PANIC("could not check if path %s is a directory: %s", path, ec.message().c_str()); - } - return result; -} - void path_rename(const char* old_path, const char* new_path) { std::error_code ec; @@ -575,33 +304,6 @@ void path_rename(const char* old_path, const char* new_path) } } -void path_mkdirs(const Cstr_Array &path) -{ - std::filesystem::path p; - for(const auto& part : path) { - p /= part; - } - - if (p.empty()) { - return; - } - - std::error_code ec; - std::filesystem::create_directories(p, ec); - if (ec) { - PANIC("could not create directories %s: %s", p.c_str(), ec.message().c_str()); - } -} - -void path_rm(const char* path) -{ - std::error_code ec; - std::filesystem::remove_all(path, ec); - if (ec) { - PANIC("could not remove %s: %s", path, ec.message().c_str()); - } -} - bool is_path1_modified_after_path2(const char *path1, const char *path2) { std::error_code ec; From 100be11fd3e0e805759480d4708255dcdf723562 Mon Sep 17 00:00:00 2001 From: "Fernando J. Iglesias Garcia" Date: Sat, 27 Dec 2025 20:31:56 +0100 Subject: [PATCH 4/4] Small refactor --- nob.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/nob.h b/nob.h index 06a1dbd..92f46f1 100644 --- a/nob.h +++ b/nob.h @@ -50,28 +50,28 @@ typedef int Fd; #include #include - -using Cstr_Array = std::vector; +using std::string; +using std::vector; std::string cstr_no_ext(const char* path); #define NOEXT(path) cstr_no_ext(path) template -Cstr_Array cstr_array_make(Args... args) +vector cstr_array_make(Args... args) { - Cstr_Array result; + vector result; (result.emplace_back(args), ...); return result; } -Cstr_Array cstr_array_from_int_char(int argc, char** argv); -std::string cstr_array_join(const char* sep, const Cstr_Array &cstrs); +vector cstr_array_from_int_char(int argc, char** argv); +std::string cstr_array_join(const char* sep, const vector &cstrs); #define JOIN(sep, ...) cstr_array_join(sep, cstr_array_make(__VA_ARGS__)) #define CONCAT(...) JOIN("", __VA_ARGS__) #define PATH(...) JOIN(PATH_SEP, __VA_ARGS__) typedef struct { - Cstr_Array line; + vector line; } Cmd; std::string cmd_show(const Cmd &cmd); @@ -92,8 +92,9 @@ typedef std::vector Cmd_Array; cmd_run_sync(cmd); \ } while (0) +// TODO: make common with nob workflow #ifndef REBUILD_URSELF -# define REBUILD_URSELF(binary_path, source_path) CMD("g++", "-std=c++20", "-o", binary_path, source_path) +# define REBUILD_URSELF(binary_path, source_path) CMD("g++", "-std=c++23", "-fsanitize=address,undefined", "-fsanitize-address-use-after-scope -D_GLIBCXX_DEBUG", "-o", binary_path, source_path) #endif // Go Rebuild Urself™ Technology @@ -164,9 +165,9 @@ void PANIC(const char* fmt, ...) NOBUILD_PRINTF_FORMAT(1, 2); #ifdef NOBUILD_IMPLEMENTATION -Cstr_Array cstr_array_from_int_char(int argc, char** argv) +vector cstr_array_from_int_char(int argc, char** argv) { - Cstr_Array result; + vector result; for (int i = 0; i < argc; ++i) { result.push_back(argv[i]); } @@ -183,7 +184,7 @@ std::string cstr_no_ext(const char* path) return std::string(p); } -std::string cstr_array_join(const char* sep, const Cstr_Array &cstrs) +std::string cstr_array_join(const char* sep, const vector &cstrs) { std::stringstream ss; for (size_t i = 0; i < cstrs.size(); ++i) {