summaryrefslogtreecommitdiff
path: root/build.c
diff options
context:
space:
mode:
Diffstat (limited to 'build.c')
-rw-r--r--build.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/build.c b/build.c
new file mode 100644
index 0000000..8fc29be
--- /dev/null
+++ b/build.c
@@ -0,0 +1,126 @@
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <linux/limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+
+#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, 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);
+ }
+}