Created
August 9, 2019 04:59
-
-
Save brimonk/f9d07cc0929f725f11af989203584588 to your computer and use it in GitHub Desktop.
A Trial Run Building Program to Replace Makefiles
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Brian Chrzanowski | |
* Fri Aug 09, 2019 00:58 | |
* | |
* Brian's Cool Builder (bcb) | |
* | |
* TODO | |
* 1. Add more wait end conditions, in 'recompile' | |
* 2. Add the ".d" dependency files | |
* 3. Add a mechanism to clean up the source tree | |
* 4. Add mechanisms to have sub-build targets | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <time.h> | |
#include <assert.h> | |
#include <errno.h> | |
#include <sys/types.h> | |
#include <sys/time.h> | |
#include <sys/stat.h> | |
#include <sys/wait.h> | |
#include <unistd.h> | |
#define CC "gcc" | |
#define CARGS "-Wall -g3 -march=native" | |
#define LARGS "-lm -ldl" | |
#define TARGET "build" | |
#define ARRSIZE(x) (sizeof((x))/sizeof((x)[0])) | |
#define MKOBJNAME(x) (*(strstr((x),".c")+1)='o') | |
#define BUFSIZE 4096 | |
int recompile_check(char *src, char *obj); | |
int recompile(char *src, char *obj); | |
int relink(char **objects, int objlen); | |
int main(int argc, char **argv) | |
{ | |
int rc, i, relinkflg; | |
char objname[BUFSIZE]; | |
char *sources[] = { "build.c" }; | |
char *objects[ARRSIZE(sources)]; | |
relinkflg = rc = 0; | |
// init objects | |
for (i = 0; i < ARRSIZE(objects); i++) { | |
objects[i] = strdup(sources[i]); | |
MKOBJNAME(objects[i]); | |
} | |
// compare the timestamp of current files with what we currently have | |
// recompile and re-link everything that's different | |
for (i = 0; i < ARRSIZE(sources); i++) { | |
memset(objname, 0, sizeof objname); | |
memcpy(objname, sources[i], strlen(sources[i])); | |
MKOBJNAME(objname); // get the name of the obj file | |
switch (recompile_check(sources[i], objname)) { | |
case -1: | |
fprintf(stderr, "File %s doesn't exist! Check the sources arr\n", sources[i]); | |
return -1; | |
case 0: | |
continue; | |
case 1: | |
relinkflg = 1; | |
rc = recompile(sources[i], objname); | |
break; | |
default: // shouldn't get here! | |
assert(0); | |
break; | |
} | |
} | |
if (relinkflg) | |
relink(objects, ARRSIZE(objects)); | |
// cleanup, cleanup, everybody everywhere... | |
for (i = 0; i < ARRSIZE(objects); i++) | |
free(objects[i]); | |
return rc; | |
} | |
/* recompile_check : determine if a file needs to be recompiled */ | |
int recompile_check(char *src, char *obj) | |
{ | |
struct stat srcstat, objstat; | |
struct timespec srctime, objtime; | |
// first, check if both files even exist | |
if (access(src, F_OK) == -1) | |
return -2; // source doesn't exist | |
if (access(obj, F_OK) == -1) | |
return 1; // recompile | |
// now figure out their timestamps | |
stat(src, &srcstat); | |
stat(obj, &objstat); | |
// copy the timevalues | |
srctime = srcstat.st_mtim; | |
objtime = objstat.st_mtim; | |
// compare the two, remember, we want to recompile only if src is newer than | |
// the corresponding object file | |
if (srctime.tv_sec > objtime.tv_sec) | |
if (srctime.tv_nsec > objtime.tv_nsec) | |
return 1; | |
return 0; | |
} | |
/* recompile : recompile src into obj */ | |
int recompile(char *src, char *obj) | |
{ | |
// WARN (brian) this function isn't robust (obviously) | |
pid_t imforked; | |
int len, i, wstatus; | |
char prog[BUFSIZE]; | |
char args[BUFSIZE]; | |
char *argv[32]; | |
char *s; | |
// create the path arg for exec | |
len = snprintf(prog, sizeof prog, "%s", CC); | |
assert(len != sizeof prog); | |
// len = snprintf(args, sizeof args, "%s -o %s %s", CARGS, obj, src); | |
len = snprintf(args, sizeof args, "%s -c %s -o %s %s", CC, CARGS, obj, src); | |
assert(len != sizeof args); | |
printf("%s\n", args); | |
// not robust if arguments have quoted strings | |
for (i = 0, s = strtok(args, " "); i < ARRSIZE(argv) - 1 && s; i++, s = strtok(NULL, " ")) { | |
argv[i] = s; | |
} | |
argv[i] = NULL; | |
// now we can fork and exec | |
imforked = fork(); | |
if (imforked) { | |
wait(&wstatus); | |
return WEXITSTATUS(wstatus); | |
} else { | |
umask(S_IWGRP | S_IWOTH); | |
wstatus = execvp(prog, argv); | |
if (wstatus < 0) { | |
fprintf(stderr, "We Died Compiling!\n"); | |
exit(-1); | |
} | |
} | |
return -1; | |
} | |
/* relink : create our relink command, then execute it */ | |
int relink(char **objects, int objlen) | |
{ | |
// WARN (brian) this function isn't robust (obviously) | |
// be careful, the way you link with gcc is pretty freaking jank, | |
// program, cargs, objects, then linker flags | |
// ugh | |
pid_t imforked; | |
int len, i, wstatus; | |
char prog[BUFSIZE]; | |
char args[BUFSIZE]; | |
char *argv[32]; | |
char *s; | |
// create the path arg for exec | |
len = snprintf(prog, sizeof prog, "%s", CC); | |
assert(len != sizeof prog); | |
// len = snprintf(args, sizeof args, "%s -o %s %s", CARGS, obj, src); | |
len = snprintf(args, sizeof args, "%s %s -o %s", CC, CARGS, TARGET); | |
assert(len != sizeof args); | |
for (i = 0; i < objlen; i++) { // print all the objects into the args buf | |
len += snprintf(args + len, sizeof(args) - len, " %s", objects[i]); | |
assert(len != sizeof args); // link line too long :) | |
} | |
// now we have to print the linker flags at the end of args | |
len += snprintf(args + len, sizeof(args) - len, " %s", LARGS); | |
assert(len != sizeof args); // link line too long :) | |
printf("%s\n", args); | |
// not robust if arguments have quoted strings | |
for (i = 0, s = strtok(args, " "); i < ARRSIZE(argv) - 1 && s; i++, s = strtok(NULL, " ")) { | |
argv[i] = s; | |
} | |
argv[i] = NULL; | |
// now we can fork and exec | |
imforked = fork(); | |
if (imforked) { | |
wait(&wstatus); | |
return WEXITSTATUS(wstatus); | |
} else { | |
umask(S_IWGRP | S_IWOTH); | |
wstatus = execvp(prog, argv); | |
if (wstatus < 0) { | |
fprintf(stderr, "We Died Linking!\n"); | |
exit(-1); | |
} | |
} | |
return -1; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment