#include #include #include #include #include #include #include #include #include #define RELEASE_MODE #ifdef RELEASE_MODE #define CC "gcc", "-O3" #else #define CC "gcc", "-fsanitize=address", "-g" #endif #define EXE_NAME "backbencher" int status; #define RUN_CMD(...) do { \ if (fork() == 0) { \ char* args[] = __VA_ARGS__; \ print_cmd(args); \ execvp(args[0], args); \ return 0; \ } else { \ wait(&status); \ } \ } while (0); void print_cmd(char** args) { int i = 0; while (args[i] != NULL) { printf("%s ", args[i++]); } printf("\n"); } // https://github.com/tsoding/nob.h/blob/0a08926d8094fc4ae678155c5d73ae21d1f96f3f/nob.h#L2413 int needs_rebuild(char* bin_file, char* source_file) { struct stat statbuf = {0}; if (stat(bin_file, &statbuf) < 0) { if (errno == ENOENT) return 1; return -1; } time_t output_path_time = statbuf.st_mtime; if (stat(source_file, &statbuf) < 0) { fprintf(stderr, "could not stat %s: %s", source_file, strerror(errno)); return -1; } time_t input_path_time = statbuf.st_mtime; return input_path_time > output_path_time; } void getlibgit2(char *output, int output_max_size) { int link[2]; pid_t pid; pipe(link); pid = fork(); if (pid == 0) { dup2(link[1], STDOUT_FILENO); close(link[0]); close(link[1]); execl("/usr/bin/pkg-config", "--cflags", "--libs", "libgit2", (char*)0); exit(0); } close(link[1]); int nbytes = read(link[0], output, output_max_size); wait(NULL); int i = -1; while (++i < nbytes) { if (output[i] >= 32) continue; nbytes = i - 1; break; } output[nbytes] = 0; return; } int main(int argc, char** argv) { if (needs_rebuild(argv[0], __FILE__)) { RUN_CMD({CC, __FILE__, "-o", argv[0], NULL}); if (status != 0) { // cc error return 0; } print_cmd(argv); execvp(argv[0], argv); } if (argc >= 2 && strcmp(argv[1], "install") == 0) { printf("install -m 755 " EXE_NAME " /usr/local/bin/" EXE_NAME); char dest[PATH_MAX]; snprintf(dest, sizeof(dest), "/usr/local/bin/%s", EXE_NAME); char *install_args[] = {"install", "-m", "755", EXE_NAME, dest, NULL}; execvp("install", install_args); perror("execvp"); return 0; } if (argc >= 2 && strcmp(argv[1], "release") == 0) { char libgit[4096]; getlibgit2(libgit, 4096); RUN_CMD({CC, "src/main.c", libgit, "-o", EXE_NAME, "-O3", NULL}); return 0; } char libgit[4096]; getlibgit2(libgit, 4096); RUN_CMD({CC, "src/main.c", libgit, "-o", EXE_NAME, "-O0", "-g", NULL}); if (status == 0 && argc >= 2) { argv[1] = malloc(1024); strncpy(argv[1], "./" EXE_NAME, 1024); print_cmd(argv + 1); execvp(argv[1], argv + 1); } }