mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 16:55:10 +00:00
[META] Death to GNUMakefile and build.c
Soon bound to add a -s flag for static build.
This commit is contained in:
parent
355a9d9b99
commit
9352bf9bba
5 changed files with 625 additions and 953 deletions
|
|
@ -24,6 +24,7 @@ jobs:
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Build Parsee
|
- name: Build Parsee
|
||||||
run: |
|
run: |
|
||||||
|
cc configure.c -o configure && ./configure
|
||||||
echo 'CFLAGS=-Werror -Wall -Wextra -pedantic' >> build.conf
|
echo 'CFLAGS=-Werror -Wall -Wextra -pedantic' >> build.conf
|
||||||
cat build.conf
|
cat build.conf
|
||||||
make && make ayadoc
|
make && make ayadoc
|
||||||
|
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -6,6 +6,8 @@ parsee
|
||||||
.*
|
.*
|
||||||
data
|
data
|
||||||
data/*
|
data/*
|
||||||
|
Makefile
|
||||||
|
configure
|
||||||
|
|
||||||
tools/out
|
tools/out
|
||||||
tools/out/*
|
tools/out/*
|
||||||
|
|
|
||||||
90
Makefile
90
Makefile
|
|
@ -1,90 +0,0 @@
|
||||||
# (GNU)Makefile for building Parsee
|
|
||||||
# ================================
|
|
||||||
# TODO: Consider making something akin to a configure script that checks
|
|
||||||
# for dependencies, or maybe even use *autoconf* (the devil!)
|
|
||||||
|
|
||||||
|
|
||||||
# =========================== Parsee Flags =============================
|
|
||||||
|
|
||||||
include build.conf
|
|
||||||
|
|
||||||
REPOSITORY=$(shell git remote get-url origin)
|
|
||||||
|
|
||||||
# =========================== Compilation Flags ============================
|
|
||||||
CYTO_INC ?=/usr/local/include/ # Where Cytoplasm's include path is
|
|
||||||
# located.
|
|
||||||
CYTO_LIB ?=/usr/local/lib # Where's Cytoplasm's library is
|
|
||||||
# located.
|
|
||||||
PREFIX ?=/usr/local
|
|
||||||
|
|
||||||
AYAS=ayaya
|
|
||||||
ETC=etc
|
|
||||||
FCFLAGS=-I$(SOURCE) -I$(INCLUDES) -I$(CYTO_INC) -DNAME="\"$(NAME)\"" -DVERSION="\"$(VERSION)\"" -DREPOSITORY=\"$(REPOSITORY)\" -DCODE=\"$(CODE)\" $(CFLAGS)
|
|
||||||
FLDFLAGS=-L $(CYTO_LIB) -lCytoplasm $(LDFLAGS)
|
|
||||||
AFLAGS=-C "$(ETC)/ayadoc/style.css" -p "$(NAME)"
|
|
||||||
# ============================ Compilation =================================
|
|
||||||
SRC_FILES:=$(shell find $(SOURCE) -name '*.c') $(shell find $(ETC)/media -name '*.png')
|
|
||||||
OBJ_FILES:=${subst $(ETC)/media/,$(OBJECT)/,${subst $(SOURCE)/,$(OBJECT)/,$(patsubst %.png, %.o, $(patsubst %.c, %.o, $(SRC_FILES)))}}
|
|
||||||
|
|
||||||
CPP_FILES:=$(shell find $(INCLUDES) -name '*.h')
|
|
||||||
AYA_FILES:=${subst $(INCLUDES)/,$(AYAS)/,$(patsubst %.h, %.html, $(CPP_FILES))}
|
|
||||||
|
|
||||||
all: utils binary
|
|
||||||
|
|
||||||
binary: $(OBJ_FILES)
|
|
||||||
$(CC) $(FLDFLAGS) $(OBJ_FILES) -o $(BINARY)
|
|
||||||
tags: $(SRC_FILES)
|
|
||||||
@ctags --recurse $(SOURCE)/
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(OBJECT) $(BINARY) $(AYAS)
|
|
||||||
|
|
||||||
$(OBJECT)/%.o: $(ETC)/media/%.png
|
|
||||||
@mkdir -p $(shell dirname "$@")
|
|
||||||
@echo "const char media_$(shell basename $< .png)[] =" > $@.c
|
|
||||||
@base64 $< | \
|
|
||||||
sed -e 's/^\(.*\)$$/ "\1"/' | \
|
|
||||||
sed -e '$$ s/^\(.*\)$$/\1;/' >> $@.c
|
|
||||||
$(CC) -c $(FCFLAGS) $@.c -o $@
|
|
||||||
$(OBJECT)/%.o: $(SOURCE)/%.c
|
|
||||||
@mkdir -p $(shell dirname "$@")
|
|
||||||
$(CC) -c $(FCFLAGS) $< -o $@
|
|
||||||
|
|
||||||
utils:
|
|
||||||
(cd tools && make)
|
|
||||||
|
|
||||||
ayadoc: utils $(AYA_FILES)
|
|
||||||
|
|
||||||
$(AYAS)/%.html: $(INCLUDES)/%.h
|
|
||||||
@mkdir -p $(shell dirname "$@")
|
|
||||||
tools/out/aya $(AFLAGS) -i $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
# Installs everything.
|
|
||||||
install: binary utils ayadoc install_setup install_parsee install_tools install_aya install_man
|
|
||||||
@echo Installed $(NAME) to $(PREFIX)!
|
|
||||||
|
|
||||||
install_setup:
|
|
||||||
install -dm755 "$(PREFIX)/bin"
|
|
||||||
install -dm755 "$(PREFIX)/share/doc"
|
|
||||||
install -dm755 "$(PREFIX)/man"
|
|
||||||
|
|
||||||
install_parsee:
|
|
||||||
install -Dm755 "$(BINARY)" "$(PREFIX)/bin/$(BINARY)"
|
|
||||||
|
|
||||||
TOOLS:=$(shell find 'tools/out' -name '*')
|
|
||||||
ITOOL:=${subst tools/out/,$(PREFIX)/bin/,$(patsubst tools/out/%, tools/out/$(BINARY)-%, $(TOOLS))}
|
|
||||||
install_tools: $(ITOOL)
|
|
||||||
$(PREFIX)/bin/$(BINARY)-%: tools/out/%
|
|
||||||
install -Dm755 "$<" "$@"
|
|
||||||
|
|
||||||
IHTML:=${subst $(AYAS)/,$(PREFIX)/share/doc/$(BINARY)/,$(AYA_FILES)}
|
|
||||||
install_aya: $(IHTML)
|
|
||||||
$(PREFIX)/share/doc/$(BINARY)/%: $(AYAS)/%
|
|
||||||
install -Dm644 "$<" "$@"
|
|
||||||
|
|
||||||
MPAGE:=$(shell find 'etc/man' -name '*.*')
|
|
||||||
PPAGE:=${subst etc/man/,$(PREFIX)/man/,$(MPAGE)}
|
|
||||||
install_man: $(PPAGE)
|
|
||||||
$(PREFIX)/man/%: etc/man/%
|
|
||||||
install -Dm644 "$<" "$@"
|
|
||||||
863
build.c
863
build.c
|
|
@ -1,863 +0,0 @@
|
||||||
/* build.c - Simple, POSIX, non-Cytoplasm utility to build out
|
|
||||||
* the entirety of Parsee from scratch, without any Makefiles.
|
|
||||||
*
|
|
||||||
* The main reason why this tool exists is merely because the
|
|
||||||
* current Make-based building is not POSIX compliant, and I
|
|
||||||
* am simply not porting it to be. The Makefile shall stay
|
|
||||||
* supported however, but if possible, use build.c.
|
|
||||||
* To run it, just build it with:
|
|
||||||
* cc build.c -o /tmp/build && /tmp/build
|
|
||||||
*
|
|
||||||
* TODO: Parallel jobs, CFLAGS and LDFLAGS.
|
|
||||||
* Note that this bit is formatted differently.
|
|
||||||
* --------------------------------
|
|
||||||
* LICENSE: CC0
|
|
||||||
* Written-By: LDA [lda@freetards.xyz] [@fourier:ari.lt] */
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#define DEFAULT_BUILD_PATH "build.conf"
|
|
||||||
#define DEFAULT_COMPILER "cc"
|
|
||||||
#define Compiler(info) (info.basic.cc ? info.basic.cc : DEFAULT_COMPILER)
|
|
||||||
|
|
||||||
static char *
|
|
||||||
string_rep_ext(char *in, char *ext1, char *ext2)
|
|
||||||
{
|
|
||||||
char *end;
|
|
||||||
size_t inLen;
|
|
||||||
if (!in || !ext1 || !ext2)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
inLen = strlen(in);
|
|
||||||
end = inLen + in;
|
|
||||||
|
|
||||||
while (end >= in)
|
|
||||||
{
|
|
||||||
if (!strcmp(end, ext1))
|
|
||||||
{
|
|
||||||
size_t cpyLen = end - in;
|
|
||||||
size_t extLen = strlen(ext2);
|
|
||||||
char *ret = malloc(cpyLen + extLen + 1);
|
|
||||||
|
|
||||||
memcpy(ret, in, cpyLen);
|
|
||||||
memcpy(ret + cpyLen, ext2, extLen);
|
|
||||||
ret[cpyLen + extLen] = '\0';
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
end--;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
static char *
|
|
||||||
string_dup(char *in)
|
|
||||||
{
|
|
||||||
char *out;
|
|
||||||
size_t len;
|
|
||||||
if (!in)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
len = strlen(in);
|
|
||||||
out = malloc(len + 1);
|
|
||||||
memcpy(out, in, len);
|
|
||||||
out[len] = '\0';
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
static char *
|
|
||||||
string_cat(char *in1, char *in2)
|
|
||||||
{
|
|
||||||
char *out;
|
|
||||||
size_t len1, len2;
|
|
||||||
if (!in1)
|
|
||||||
{
|
|
||||||
return string_dup(in2);
|
|
||||||
}
|
|
||||||
if (!in2)
|
|
||||||
{
|
|
||||||
return string_dup(in1);
|
|
||||||
}
|
|
||||||
|
|
||||||
len1 = strlen(in1);
|
|
||||||
len2 = strlen(in2);
|
|
||||||
out = malloc(len1 + len2 + 1);
|
|
||||||
memcpy(out, in1, len1);
|
|
||||||
memcpy(out + len1, in2, len2);
|
|
||||||
out[len1 + len2] = '\0';
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
static char *
|
|
||||||
trim_nl(char *in)
|
|
||||||
{
|
|
||||||
char *tc;
|
|
||||||
if (!in)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((tc = strrchr(in, '\n')))
|
|
||||||
{
|
|
||||||
*tc = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct str_array {
|
|
||||||
char **values;
|
|
||||||
size_t quantity;
|
|
||||||
} str_array_t;
|
|
||||||
static str_array_t *
|
|
||||||
str_array_create(void)
|
|
||||||
{
|
|
||||||
str_array_t *ret = malloc(sizeof(*ret));
|
|
||||||
|
|
||||||
ret->values = NULL;
|
|
||||||
ret->quantity = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
str_array_free(str_array_t *arr)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
if (!arr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < arr->quantity; i++)
|
|
||||||
{
|
|
||||||
if (arr->values[i]) free(arr->values[i]);
|
|
||||||
}
|
|
||||||
if (arr->values) free(arr->values);
|
|
||||||
free(arr);
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
str_array_set(str_array_t *arr, size_t i, char *str)
|
|
||||||
{
|
|
||||||
if (!arr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i >= arr->quantity)
|
|
||||||
{
|
|
||||||
size_t size = (i+1) * sizeof(*arr->values);
|
|
||||||
size_t j;
|
|
||||||
arr->values = realloc(arr->values, size);
|
|
||||||
for (j = arr->quantity; j <= i; j++)
|
|
||||||
{
|
|
||||||
arr->values[j] = NULL;
|
|
||||||
}
|
|
||||||
arr->quantity = i + 1 ;
|
|
||||||
}
|
|
||||||
if (arr->values[i]) free(arr->values[i]);
|
|
||||||
arr->values[i] = string_dup(str);
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
str_array_add(str_array_t *arr, char *str)
|
|
||||||
{
|
|
||||||
if (!arr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
str_array_set(arr, arr->quantity, str);
|
|
||||||
}
|
|
||||||
static char *
|
|
||||||
str_array_get(str_array_t *arr, size_t i)
|
|
||||||
{
|
|
||||||
if (!arr)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return i < arr->quantity ? arr->values[i] : NULL;
|
|
||||||
}
|
|
||||||
static size_t
|
|
||||||
str_array_len(str_array_t *arr)
|
|
||||||
{
|
|
||||||
return arr ? arr->quantity : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct buildinfo {
|
|
||||||
struct basic {
|
|
||||||
char *codename;
|
|
||||||
char *version;
|
|
||||||
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
char *binary;
|
|
||||||
|
|
||||||
char *src;
|
|
||||||
char *inc;
|
|
||||||
char *obj;
|
|
||||||
|
|
||||||
char *cflags, *ldflags;
|
|
||||||
|
|
||||||
char *cc;
|
|
||||||
} basic;
|
|
||||||
|
|
||||||
char *repo;
|
|
||||||
} buildinfo_t;
|
|
||||||
static void
|
|
||||||
destroy_buildinfo(buildinfo_t *info)
|
|
||||||
{
|
|
||||||
if (!info)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FreeIfExistent(v) do \
|
|
||||||
{ \
|
|
||||||
if (v) \
|
|
||||||
{ \
|
|
||||||
free(v); \
|
|
||||||
v = NULL; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
FreeIfExistent(info->basic.codename);
|
|
||||||
FreeIfExistent(info->basic.version);
|
|
||||||
FreeIfExistent(info->basic.ldflags);
|
|
||||||
FreeIfExistent(info->basic.binary);
|
|
||||||
FreeIfExistent(info->basic.cflags);
|
|
||||||
FreeIfExistent(info->basic.name);
|
|
||||||
FreeIfExistent(info->basic.src);
|
|
||||||
FreeIfExistent(info->basic.inc);
|
|
||||||
FreeIfExistent(info->basic.obj);
|
|
||||||
FreeIfExistent(info->basic.cc);
|
|
||||||
FreeIfExistent(info->repo);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
cmd_stdout(char *cmd)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
char *line = NULL;
|
|
||||||
size_t size;
|
|
||||||
if (!cmd)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (!(f = popen(cmd, "r")))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
getline(&line, &size, f);
|
|
||||||
pclose(f);
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
static int
|
|
||||||
exec_code(char *program, char *argv[])
|
|
||||||
{
|
|
||||||
pid_t forkRet;
|
|
||||||
if (!program || !argv)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
forkRet = fork();
|
|
||||||
if (forkRet == 0)
|
|
||||||
{
|
|
||||||
/* Child */
|
|
||||||
execvp(program, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Parent */
|
|
||||||
int status;
|
|
||||||
if (waitpid(forkRet, &status, 0) == -1)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We're not meant to ever be there, but TCC is stupid. */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
strchrn(char *s, char c)
|
|
||||||
{
|
|
||||||
s = strchr(s, c);
|
|
||||||
return s ? s+1 : NULL;
|
|
||||||
}
|
|
||||||
static char *
|
|
||||||
strchrl(char *s, char c)
|
|
||||||
{
|
|
||||||
char *s1 = NULL;
|
|
||||||
while ((s = strchr(s, c)))
|
|
||||||
{
|
|
||||||
s1 = s;
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
return s1;
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
mkdir_rec(char *dir)
|
|
||||||
{
|
|
||||||
char tmp[PATH_MAX];
|
|
||||||
char *start;
|
|
||||||
if (!dir || strlen(dir) >= PATH_MAX - 1)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(tmp, '\0', sizeof(tmp));
|
|
||||||
for (start = dir; start && *start; start = strchrn(start, '/'))
|
|
||||||
{
|
|
||||||
char subtmp[PATH_MAX];
|
|
||||||
char *next = strchr(start, '/');
|
|
||||||
if (!next)
|
|
||||||
{
|
|
||||||
next = start + strlen(start);
|
|
||||||
}
|
|
||||||
memcpy(subtmp, start, next - start);
|
|
||||||
subtmp[next - start] = '\0';
|
|
||||||
|
|
||||||
{
|
|
||||||
memcpy(tmp, dir, start - dir);
|
|
||||||
tmp[strlen(tmp) - 1] = '\0';
|
|
||||||
mkdir(tmp, 0770);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static str_array_t *
|
|
||||||
split(char *dir)
|
|
||||||
{
|
|
||||||
str_array_t *ret;
|
|
||||||
char *start;
|
|
||||||
if (!dir || strlen(dir) >= PATH_MAX - 1)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = str_array_create();
|
|
||||||
for (start = dir; start; start = strchrn(start, ' '))
|
|
||||||
{
|
|
||||||
char subtmp[PATH_MAX];
|
|
||||||
char *next = strchr(start, ' ');
|
|
||||||
if (!next)
|
|
||||||
{
|
|
||||||
next = start + strlen(start);
|
|
||||||
}
|
|
||||||
memcpy(subtmp, start, next - start);
|
|
||||||
subtmp[next - start] = '\0';
|
|
||||||
|
|
||||||
str_array_add(ret, subtmp);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
static time_t
|
|
||||||
mod_date(char *file)
|
|
||||||
{
|
|
||||||
struct stat s;
|
|
||||||
if (stat(file, &s))
|
|
||||||
{
|
|
||||||
return (time_t) 0;
|
|
||||||
}
|
|
||||||
return s.st_mtime;
|
|
||||||
}
|
|
||||||
static bool
|
|
||||||
build_file(char *cSource, buildinfo_t info, bool isTool)
|
|
||||||
{
|
|
||||||
str_array_t *args, *cflags;
|
|
||||||
char *oFileName, *objPath, *oFile;
|
|
||||||
int ret, i = 0;
|
|
||||||
int srclen;
|
|
||||||
|
|
||||||
char *code, *name, *vers, *repo;
|
|
||||||
if (!cSource)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isTool)
|
|
||||||
{
|
|
||||||
srclen = strncmp(cSource, "src", 3) ?
|
|
||||||
strlen(info.basic.obj) + 1 :
|
|
||||||
strlen(info.basic.src) + 1 ;
|
|
||||||
objPath = string_cat(info.basic.obj, "/");
|
|
||||||
oFile = string_rep_ext(cSource + srclen, ".c", ".o");
|
|
||||||
oFileName = string_cat(objPath, oFile);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
srclen = 6;
|
|
||||||
objPath = string_dup("tools/out/");
|
|
||||||
oFile = string_rep_ext(cSource + srclen, ".c", "");
|
|
||||||
oFileName = string_cat(objPath, oFile);
|
|
||||||
}
|
|
||||||
mkdir_rec(oFileName);
|
|
||||||
|
|
||||||
if (!isTool && (mod_date(cSource) < mod_date(oFileName)))
|
|
||||||
{
|
|
||||||
free(objPath);
|
|
||||||
free(oFileName);
|
|
||||||
free(oFile);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
args = str_array_create();
|
|
||||||
if (!isTool)
|
|
||||||
{
|
|
||||||
printf("\tCC %s...\n", cSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
str_array_add(args, Compiler(info));
|
|
||||||
if (isTool)
|
|
||||||
{
|
|
||||||
str_array_add(args, "-lCytoplasm");
|
|
||||||
str_array_add(args, "-I.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
str_array_add(args, "-c");
|
|
||||||
}
|
|
||||||
str_array_add(args, cSource);
|
|
||||||
|
|
||||||
cflags = split(info.basic.cflags);
|
|
||||||
for (i = 0; i < str_array_len(cflags); i++)
|
|
||||||
{
|
|
||||||
str_array_add(args, str_array_get(cflags, i));
|
|
||||||
}
|
|
||||||
str_array_free(cflags);
|
|
||||||
|
|
||||||
str_array_add(args, "-o");
|
|
||||||
str_array_add(args, oFileName);
|
|
||||||
|
|
||||||
str_array_add(args, "-I");
|
|
||||||
str_array_add(args, info.basic.inc);
|
|
||||||
str_array_add(args, "-I");
|
|
||||||
str_array_add(args, info.basic.src);
|
|
||||||
|
|
||||||
{
|
|
||||||
char *pre = string_cat("\"", info.basic.version);
|
|
||||||
char *pos = string_cat(pre, "\"");
|
|
||||||
vers = string_cat("-DVERSION=", pos);
|
|
||||||
str_array_add(args, vers);
|
|
||||||
|
|
||||||
free(pos);
|
|
||||||
free(pre);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
char *pre = string_cat("\"", info.basic.name);
|
|
||||||
char *pos = string_cat(pre, "\"");
|
|
||||||
name = string_cat("-DNAME=", pos);
|
|
||||||
str_array_add(args, name);
|
|
||||||
|
|
||||||
free(pos);
|
|
||||||
free(pre);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
char *pre = string_cat("\"", info.basic.codename);
|
|
||||||
char *pos = string_cat(pre, "\"");
|
|
||||||
code = string_cat("-DCODE=", pos);
|
|
||||||
str_array_add(args, code);
|
|
||||||
|
|
||||||
free(pos);
|
|
||||||
free(pre);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
char *pre = string_cat("\"", info.repo);
|
|
||||||
char *pos = string_cat(pre, "\"");
|
|
||||||
repo = string_cat("-DREPOSITORY=", pos);
|
|
||||||
str_array_add(args, repo);
|
|
||||||
|
|
||||||
free(pos);
|
|
||||||
free(pre);
|
|
||||||
}
|
|
||||||
|
|
||||||
str_array_add(args, NULL);
|
|
||||||
|
|
||||||
ret = exec_code(Compiler(info), args->values);
|
|
||||||
|
|
||||||
str_array_free(args);
|
|
||||||
free(objPath);
|
|
||||||
free(oFileName);
|
|
||||||
free(oFile);
|
|
||||||
free(vers);
|
|
||||||
free(name);
|
|
||||||
free(code);
|
|
||||||
free(repo);
|
|
||||||
return ret == EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
static bool
|
|
||||||
finalise_file(str_array_t *arr, buildinfo_t info)
|
|
||||||
{
|
|
||||||
str_array_t *flags, *ldflags;
|
|
||||||
size_t i;
|
|
||||||
bool ret = true;
|
|
||||||
if (!arr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
flags = str_array_create();
|
|
||||||
str_array_add(flags, Compiler(info));
|
|
||||||
|
|
||||||
ldflags = split(info.basic.cflags);
|
|
||||||
for (i = 0; i < str_array_len(ldflags); i++)
|
|
||||||
{
|
|
||||||
str_array_add(flags, str_array_get(ldflags, i));
|
|
||||||
}
|
|
||||||
str_array_free(ldflags);
|
|
||||||
|
|
||||||
str_array_add(flags, "-lCytoplasm");
|
|
||||||
|
|
||||||
for (i = 0; i < str_array_len(arr); i++)
|
|
||||||
{
|
|
||||||
char *file = str_array_get(arr, i);
|
|
||||||
if (file)
|
|
||||||
{
|
|
||||||
size_t srclen = strncmp(file, "src", 3) ?
|
|
||||||
strlen(info.basic.obj) + 1 :
|
|
||||||
strlen(info.basic.src) + 1 ;
|
|
||||||
char *objPath = string_cat(info.basic.obj, "/");
|
|
||||||
char *oFile = string_rep_ext(file + srclen, ".c", ".o");
|
|
||||||
char *oFileName = string_cat(objPath, oFile);
|
|
||||||
|
|
||||||
str_array_add(flags, oFileName);
|
|
||||||
|
|
||||||
free(oFileName);
|
|
||||||
free(oFile);
|
|
||||||
free(objPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
str_array_add(flags, "-o");
|
|
||||||
str_array_add(flags, info.basic.binary);
|
|
||||||
str_array_add(flags, NULL);
|
|
||||||
ret = exec_code(Compiler(info), flags->values);
|
|
||||||
|
|
||||||
str_array_free(flags);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static str_array_t *
|
|
||||||
collect_sources(char *dir, bool head, char *ext)
|
|
||||||
{
|
|
||||||
DIR *handle;
|
|
||||||
str_array_t *ret;
|
|
||||||
struct dirent *ent;
|
|
||||||
if (!dir)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = str_array_create();
|
|
||||||
handle = opendir(dir);
|
|
||||||
if (!handle)
|
|
||||||
{
|
|
||||||
printf("error: cannot open directory '%s'\n", dir);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
while ((ent = readdir(handle)))
|
|
||||||
{
|
|
||||||
char *name = ent->d_name;
|
|
||||||
if (*name == '.') continue;
|
|
||||||
|
|
||||||
if (strlen(name) > strlen(ext) &&
|
|
||||||
!strcmp(name + strlen(name) - strlen(ext), ext))
|
|
||||||
{
|
|
||||||
char *d1 = string_cat(dir, "/");
|
|
||||||
char *na = string_cat(d1, name);
|
|
||||||
str_array_add(ret, na);
|
|
||||||
free(d1);
|
|
||||||
free(na);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strchr(name, '.') &&
|
|
||||||
strcmp(name, "out") &&
|
|
||||||
strcmp(name, "Makefile"))
|
|
||||||
{
|
|
||||||
str_array_t *sub;
|
|
||||||
char *d1 = string_cat(dir, "/");
|
|
||||||
char *d2 = string_cat(d1, name);
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
sub = collect_sources(d2, false, ext);
|
|
||||||
for (i = 0; i < str_array_len(sub); i++)
|
|
||||||
{
|
|
||||||
char *file = str_array_get(sub, i);
|
|
||||||
str_array_add(ret, file);
|
|
||||||
}
|
|
||||||
str_array_free(sub);
|
|
||||||
free(d2);
|
|
||||||
free(d1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(handle);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
process_png(char *png, buildinfo_t info)
|
|
||||||
{
|
|
||||||
size_t i = 0;
|
|
||||||
char *symbol;
|
|
||||||
char *cFile, *oFile;
|
|
||||||
char *pcFile, *poFile;
|
|
||||||
char *pcFile1, *poFile1;
|
|
||||||
char *filename, *symbol1;
|
|
||||||
char *arguments[8] = { 0 };
|
|
||||||
if (!png)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(filename = strchrl(png, '/')))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
filename++;
|
|
||||||
|
|
||||||
pcFile1= string_cat(info.basic.obj, "/");
|
|
||||||
pcFile = string_cat(pcFile1, filename);
|
|
||||||
cFile = string_rep_ext(pcFile, ".png", ".c");
|
|
||||||
free(pcFile);
|
|
||||||
free(pcFile1);
|
|
||||||
|
|
||||||
poFile1= string_cat(info.basic.obj, "/");
|
|
||||||
poFile = string_cat(poFile1, filename);
|
|
||||||
oFile = string_rep_ext(poFile, ".png", ".o");
|
|
||||||
free(poFile);
|
|
||||||
free(poFile1);
|
|
||||||
|
|
||||||
symbol1 = string_rep_ext(filename, ".png", "");
|
|
||||||
symbol = string_cat("media_", symbol1);
|
|
||||||
free(symbol1);
|
|
||||||
|
|
||||||
mkdir_rec(oFile);
|
|
||||||
mkdir_rec(cFile);
|
|
||||||
|
|
||||||
/* Build the image into Base64 */
|
|
||||||
arguments[i++] = "tools/out/b64";
|
|
||||||
arguments[i++] = png;
|
|
||||||
arguments[i++] = symbol;
|
|
||||||
arguments[i++] = cFile;
|
|
||||||
arguments[i++] = NULL;
|
|
||||||
|
|
||||||
if (exec_code(arguments[0], arguments))
|
|
||||||
{
|
|
||||||
free(symbol);
|
|
||||||
free(cFile);
|
|
||||||
free(oFile);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compile it out */
|
|
||||||
i = 0;
|
|
||||||
arguments[i++] = Compiler(info);
|
|
||||||
arguments[i++] = "-c";
|
|
||||||
arguments[i++] = cFile;
|
|
||||||
arguments[i++] = "-o";
|
|
||||||
arguments[i++] = oFile;
|
|
||||||
arguments[i++] = NULL;
|
|
||||||
|
|
||||||
if (exec_code(arguments[0], arguments))
|
|
||||||
{
|
|
||||||
free(symbol);
|
|
||||||
free(cFile);
|
|
||||||
free(oFile);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(symbol);
|
|
||||||
free(oFile);
|
|
||||||
return cFile;
|
|
||||||
}
|
|
||||||
/* Builds the entirety of Parsee. */
|
|
||||||
static int
|
|
||||||
main_build(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
buildinfo_t info = { 0 };
|
|
||||||
FILE *buildinfo = NULL;
|
|
||||||
char *line = NULL;
|
|
||||||
size_t size, i;
|
|
||||||
ssize_t nread;
|
|
||||||
str_array_t *sources, *images;
|
|
||||||
|
|
||||||
/* Step 1: Get all basic information from build.conf */
|
|
||||||
if (!(buildinfo = fopen(DEFAULT_BUILD_PATH, "r")))
|
|
||||||
{
|
|
||||||
printf("error: cannot open '%s'\n", DEFAULT_BUILD_PATH);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
while ((nread = getline(&line, &size, buildinfo)) != -1)
|
|
||||||
{
|
|
||||||
char *eq = strchr(line, '=');
|
|
||||||
char *end = strchr(line, '\n');
|
|
||||||
|
|
||||||
char *key, *val;
|
|
||||||
if (!eq)
|
|
||||||
{
|
|
||||||
free(line);
|
|
||||||
printf(
|
|
||||||
"error: line in '%s' does not contain '='\n",
|
|
||||||
DEFAULT_BUILD_PATH
|
|
||||||
);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set delimiters */
|
|
||||||
*eq = '\0';
|
|
||||||
if (end) *end = '\0';
|
|
||||||
|
|
||||||
key = line;
|
|
||||||
val = eq + 1;
|
|
||||||
|
|
||||||
/* Now, we have KV mappings. */
|
|
||||||
#define If(k, v, d) do \
|
|
||||||
{ \
|
|
||||||
if (!strcmp(key, k) && !info.v) \
|
|
||||||
{ \
|
|
||||||
info.v = string_dup(val); \
|
|
||||||
printf("%s: %s\n", d, val); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
If("CODE", basic.codename, "Codename");
|
|
||||||
If("NAME", basic.name, "Name");
|
|
||||||
If("VERSION", basic.version, "Version");
|
|
||||||
If("BINARY", basic.binary, "Binary name");
|
|
||||||
|
|
||||||
If("CFLAGS", basic.cflags, "C compiler arguments");
|
|
||||||
If("LDFLAGS", basic.ldflags, "Linker arguments");
|
|
||||||
|
|
||||||
If("INCLUDES", basic.inc, "Include path");
|
|
||||||
If("SOURCE", basic.src, "Source path");
|
|
||||||
If("OBJECT", basic.obj, "Object path");
|
|
||||||
If("CC", basic.cc, "Compiler");
|
|
||||||
}
|
|
||||||
if (line)
|
|
||||||
{
|
|
||||||
free(line);
|
|
||||||
line = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(buildinfo);
|
|
||||||
buildinfo = NULL;
|
|
||||||
|
|
||||||
/* Step 2: Get all information from commands. */
|
|
||||||
if (!(info.repo = cmd_stdout("git remote get-url origin")))
|
|
||||||
{
|
|
||||||
printf("error: cannot find origins url\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
info.repo = trim_nl(info.repo);
|
|
||||||
|
|
||||||
if (argc >= 2 && !strcmp(argv[1], "clean"))
|
|
||||||
{
|
|
||||||
char *args[8];
|
|
||||||
size_t i;
|
|
||||||
unlink(info.basic.binary);
|
|
||||||
|
|
||||||
args[i++] = "rm";
|
|
||||||
args[i++] = "-r";
|
|
||||||
args[i++] = info.basic.obj;
|
|
||||||
args[i++] = NULL;
|
|
||||||
exec_code(args[0], args);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Step 3: Build all utilities. */
|
|
||||||
sources = collect_sources("tools", true, ".c");
|
|
||||||
for (i = 0; i < str_array_len(sources); i++)
|
|
||||||
{
|
|
||||||
char *file = str_array_get(sources, i);
|
|
||||||
printf("\tTOOL %s...\n", file);
|
|
||||||
if (!build_file(file, info, true))
|
|
||||||
{
|
|
||||||
str_array_free(sources);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
str_array_free(sources);
|
|
||||||
|
|
||||||
/* Step 4: Build all media files. */
|
|
||||||
sources = collect_sources(info.basic.src, true, ".c");
|
|
||||||
images = collect_sources("etc/media", true, ".png");
|
|
||||||
for (i = 0; i < str_array_len(images); i++)
|
|
||||||
{
|
|
||||||
char *file = str_array_get(images, i);
|
|
||||||
char *out;
|
|
||||||
|
|
||||||
out = process_png(file, info);
|
|
||||||
if (!out)
|
|
||||||
{
|
|
||||||
str_array_free(images);
|
|
||||||
str_array_free(sources);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
printf("\tPNG %s\n", file);
|
|
||||||
str_array_add(sources, out);
|
|
||||||
free(out);
|
|
||||||
}
|
|
||||||
str_array_free(images);
|
|
||||||
|
|
||||||
/* Step 5: Build all of Parsee itself */
|
|
||||||
for (i = 0; i < str_array_len(sources); i++)
|
|
||||||
{
|
|
||||||
char *file = str_array_get(sources, i);
|
|
||||||
if (!build_file(file, info, false))
|
|
||||||
{
|
|
||||||
str_array_free(sources);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\tLINK\n");
|
|
||||||
if (!finalise_file(sources, info))
|
|
||||||
{
|
|
||||||
str_array_free(sources);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
str_array_free(sources);
|
|
||||||
/* TODO: Step 6: Build every Ayadoc */
|
|
||||||
end:
|
|
||||||
destroy_buildinfo(&info);
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
fail:
|
|
||||||
if (buildinfo)
|
|
||||||
{
|
|
||||||
fclose(buildinfo);
|
|
||||||
buildinfo = NULL;
|
|
||||||
}
|
|
||||||
destroy_buildinfo(&info);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
/* TODO: Multiple flags(build/install/ayadoc/...) */
|
|
||||||
if ((argc - 1) < 1)
|
|
||||||
{
|
|
||||||
/* No arguments, let's just build. */
|
|
||||||
return main_build(argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(argv[1], "build") ||
|
|
||||||
!strcmp(argv[1], "clean"))
|
|
||||||
{
|
|
||||||
return main_build(argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s: unknown verb: %s\n", argv[0], argv[1]);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
622
configure.c
Normal file
622
configure.c
Normal file
|
|
@ -0,0 +1,622 @@
|
||||||
|
/* configure.c - Simple, POSIX, non-Cytoplasm utility to build out
|
||||||
|
* a Parsee Makefile.
|
||||||
|
* To run it, just build it with:
|
||||||
|
* cc configure.c -o configure && configure
|
||||||
|
* --------------------------------
|
||||||
|
* LICENSE: CC0
|
||||||
|
* Written-By: LDA [lda@freetards.xyz] [@fourier:ari.lt] */
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
static char *
|
||||||
|
string_rep_ext(char *in, char *ext1, char *ext2)
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
size_t inLen;
|
||||||
|
if (!in || !ext1 || !ext2)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inLen = strlen(in);
|
||||||
|
end = inLen + in;
|
||||||
|
|
||||||
|
while (end >= in)
|
||||||
|
{
|
||||||
|
if (!strcmp(end, ext1))
|
||||||
|
{
|
||||||
|
size_t cpyLen = end - in;
|
||||||
|
size_t extLen = strlen(ext2);
|
||||||
|
char *ret = malloc(cpyLen + extLen + 1);
|
||||||
|
|
||||||
|
memcpy(ret, in, cpyLen);
|
||||||
|
memcpy(ret + cpyLen, ext2, extLen);
|
||||||
|
ret[cpyLen + extLen] = '\0';
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static char *
|
||||||
|
string_dup(char *in)
|
||||||
|
{
|
||||||
|
char *out;
|
||||||
|
size_t len;
|
||||||
|
if (!in)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
len = strlen(in);
|
||||||
|
out = malloc(len + 1);
|
||||||
|
memcpy(out, in, len);
|
||||||
|
out[len] = '\0';
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
static char *
|
||||||
|
string_cat(char *in1, char *in2)
|
||||||
|
{
|
||||||
|
char *out;
|
||||||
|
size_t len1, len2;
|
||||||
|
if (!in1)
|
||||||
|
{
|
||||||
|
return string_dup(in2);
|
||||||
|
}
|
||||||
|
if (!in2)
|
||||||
|
{
|
||||||
|
return string_dup(in1);
|
||||||
|
}
|
||||||
|
|
||||||
|
len1 = strlen(in1);
|
||||||
|
len2 = strlen(in2);
|
||||||
|
out = malloc(len1 + len2 + 1);
|
||||||
|
memcpy(out, in1, len1);
|
||||||
|
memcpy(out + len1, in2, len2);
|
||||||
|
out[len1 + len2] = '\0';
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
static char *
|
||||||
|
trim_nl(char *in)
|
||||||
|
{
|
||||||
|
char *tc;
|
||||||
|
if (!in)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((tc = strrchr(in, '\n')))
|
||||||
|
{
|
||||||
|
*tc = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct str_array {
|
||||||
|
char **values;
|
||||||
|
size_t quantity;
|
||||||
|
} str_array_t;
|
||||||
|
static str_array_t *
|
||||||
|
str_array_create(void)
|
||||||
|
{
|
||||||
|
str_array_t *ret = malloc(sizeof(*ret));
|
||||||
|
|
||||||
|
ret->values = NULL;
|
||||||
|
ret->quantity = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
str_array_free(str_array_t *arr)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (!arr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < arr->quantity; i++)
|
||||||
|
{
|
||||||
|
if (arr->values[i]) free(arr->values[i]);
|
||||||
|
}
|
||||||
|
if (arr->values) free(arr->values);
|
||||||
|
free(arr);
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
str_array_set(str_array_t *arr, size_t i, char *str)
|
||||||
|
{
|
||||||
|
if (!arr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= arr->quantity)
|
||||||
|
{
|
||||||
|
size_t size = (i+1) * sizeof(*arr->values);
|
||||||
|
size_t j;
|
||||||
|
arr->values = realloc(arr->values, size);
|
||||||
|
for (j = arr->quantity; j <= i; j++)
|
||||||
|
{
|
||||||
|
arr->values[j] = NULL;
|
||||||
|
}
|
||||||
|
arr->quantity = i + 1 ;
|
||||||
|
}
|
||||||
|
if (arr->values[i]) free(arr->values[i]);
|
||||||
|
arr->values[i] = string_dup(str);
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
str_array_add(str_array_t *arr, char *str)
|
||||||
|
{
|
||||||
|
if (!arr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
str_array_set(arr, arr->quantity, str);
|
||||||
|
}
|
||||||
|
static char *
|
||||||
|
str_array_get(str_array_t *arr, size_t i)
|
||||||
|
{
|
||||||
|
if (!arr)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return i < arr->quantity ? arr->values[i] : NULL;
|
||||||
|
}
|
||||||
|
static size_t
|
||||||
|
str_array_len(str_array_t *arr)
|
||||||
|
{
|
||||||
|
return arr ? arr->quantity : 0;
|
||||||
|
}
|
||||||
|
static char *
|
||||||
|
cmd_stdout(char *cmd)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
char *line = NULL;
|
||||||
|
size_t size;
|
||||||
|
if (!cmd)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(f = popen(cmd, "r")))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
getline(&line, &size, f);
|
||||||
|
pclose(f);
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
static int
|
||||||
|
exec_code(char *program, char *argv[])
|
||||||
|
{
|
||||||
|
pid_t forkRet;
|
||||||
|
if (!program || !argv)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
forkRet = fork();
|
||||||
|
if (forkRet == 0)
|
||||||
|
{
|
||||||
|
/* Child */
|
||||||
|
execvp(program, argv);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Parent */
|
||||||
|
int status;
|
||||||
|
if (waitpid(forkRet, &status, 0) == -1)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We're not meant to ever be there, but TCC is stupid. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
strchrn(char *s, char c)
|
||||||
|
{
|
||||||
|
s = strchr(s, c);
|
||||||
|
return s ? s+1 : NULL;
|
||||||
|
}
|
||||||
|
static char *
|
||||||
|
strchrl(char *s, char c)
|
||||||
|
{
|
||||||
|
char *s1 = NULL;
|
||||||
|
while ((s = strchr(s, c)))
|
||||||
|
{
|
||||||
|
s1 = s;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
return s1;
|
||||||
|
}
|
||||||
|
static str_array_t *
|
||||||
|
split(char *dir)
|
||||||
|
{
|
||||||
|
str_array_t *ret;
|
||||||
|
char *start;
|
||||||
|
if (!dir || strlen(dir) >= PATH_MAX - 1)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = str_array_create();
|
||||||
|
for (start = dir; start; start = strchrn(start, '/'))
|
||||||
|
{
|
||||||
|
char subtmp[PATH_MAX];
|
||||||
|
char *next = strchr(start, '/');
|
||||||
|
if (!next)
|
||||||
|
{
|
||||||
|
next = start + strlen(start);
|
||||||
|
}
|
||||||
|
memcpy(subtmp, start, next - start);
|
||||||
|
subtmp[next - start] = '\0';
|
||||||
|
|
||||||
|
str_array_add(ret, subtmp);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static str_array_t *
|
||||||
|
collect_sources(char *dir, bool head, char *ext)
|
||||||
|
{
|
||||||
|
DIR *handle;
|
||||||
|
str_array_t *ret;
|
||||||
|
struct dirent *ent;
|
||||||
|
if (!dir)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = str_array_create();
|
||||||
|
handle = opendir(dir);
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
printf("error: cannot open directory '%s'\n", dir);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
while ((ent = readdir(handle)))
|
||||||
|
{
|
||||||
|
char *name = ent->d_name;
|
||||||
|
if (*name == '.') continue;
|
||||||
|
|
||||||
|
if (strlen(name) > strlen(ext) &&
|
||||||
|
!strcmp(name + strlen(name) - strlen(ext), ext))
|
||||||
|
{
|
||||||
|
char *d1 = string_cat(dir, "/");
|
||||||
|
char *na = string_cat(d1, name);
|
||||||
|
str_array_add(ret, na);
|
||||||
|
free(d1);
|
||||||
|
free(na);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strchr(name, '.') &&
|
||||||
|
strcmp(name, "out") &&
|
||||||
|
strcmp(name, "Makefile"))
|
||||||
|
{
|
||||||
|
str_array_t *sub;
|
||||||
|
char *d1 = string_cat(dir, "/");
|
||||||
|
char *d2 = string_cat(d1, name);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
sub = collect_sources(d2, false, ext);
|
||||||
|
for (i = 0; i < str_array_len(sub); i++)
|
||||||
|
{
|
||||||
|
char *file = str_array_get(sub, i);
|
||||||
|
str_array_add(ret, file);
|
||||||
|
}
|
||||||
|
str_array_free(sub);
|
||||||
|
free(d2);
|
||||||
|
free(d1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(handle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Builds the entirety of Parsee. */
|
||||||
|
static void
|
||||||
|
write_objects(FILE *makefile, str_array_t *sources)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (!makefile || !sources)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < str_array_len(sources); i++)
|
||||||
|
{
|
||||||
|
char *src = str_array_get(sources, i);
|
||||||
|
char *ofl = string_rep_ext(src, ".c", ".o");
|
||||||
|
char *obj = string_cat("build", ofl + 3);
|
||||||
|
|
||||||
|
fprintf(makefile, " %s", obj);
|
||||||
|
free(ofl);
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
write_images(FILE *makefile, str_array_t *sources)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (!makefile || !sources)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < str_array_len(sources); i++)
|
||||||
|
{
|
||||||
|
char *src = str_array_get(sources, i);
|
||||||
|
char *ofl = string_rep_ext(src, ".png", ".o");
|
||||||
|
char *obj = string_cat("build", ofl + 3 + 1 + 5);
|
||||||
|
|
||||||
|
fprintf(makefile, " %s", obj);
|
||||||
|
free(ofl);
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
write_executable(FILE *makefile, str_array_t *sources)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (!makefile || !sources)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < str_array_len(sources); i++)
|
||||||
|
{
|
||||||
|
char *src = str_array_get(sources, i);
|
||||||
|
char *ofl = string_rep_ext(src, ".c", "");
|
||||||
|
char *obj = string_cat("tools/out", ofl + 5);
|
||||||
|
|
||||||
|
fprintf(makefile, " %s", obj);
|
||||||
|
free(ofl);
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
write_ayas(FILE *makefile, str_array_t *sources)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (!makefile || !sources)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < str_array_len(sources); i++)
|
||||||
|
{
|
||||||
|
char *src = str_array_get(sources, i);
|
||||||
|
char *ofl = string_rep_ext(src, ".h", ".html");
|
||||||
|
char *obj = string_cat("$(AYAYAS)", ofl + 3 + 1 + 7);
|
||||||
|
|
||||||
|
fprintf(makefile, " %s", obj);
|
||||||
|
free(ofl);
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static int
|
||||||
|
main_build(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
FILE *makefile;
|
||||||
|
char *repo = cmd_stdout("git remote get-url origin");
|
||||||
|
size_t size, i;
|
||||||
|
ssize_t nread;
|
||||||
|
str_array_t *sources, *images, *utils, *aya;
|
||||||
|
|
||||||
|
if (strchr(repo, '\n'))
|
||||||
|
{
|
||||||
|
*(strchr(repo, '\n')) = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
makefile = fopen("Makefile", "w");
|
||||||
|
fprintf(makefile, "# Autogenerated POSIX Makefile\n");
|
||||||
|
fprintf(makefile, "# Ideally do not touch.\n\n");
|
||||||
|
fprintf(makefile, ".POSIX: \n");
|
||||||
|
fprintf(makefile, "include build.conf\n\n");
|
||||||
|
fprintf(makefile, "AYAYAS=ayaya\n");
|
||||||
|
fprintf(makefile, "CYTO_LIB=/usr/local/lib\n");
|
||||||
|
fprintf(makefile, "CYTO_INC=/usr/local/include\n");
|
||||||
|
fprintf(makefile, "ETC=etc\n\n");
|
||||||
|
|
||||||
|
fprintf(makefile, "all: utils binary ayadoc\n\n");
|
||||||
|
|
||||||
|
/* Create all objects */
|
||||||
|
sources = collect_sources("src", true, ".c");
|
||||||
|
images = collect_sources("etc/media", true, ".png");
|
||||||
|
fprintf(makefile, "binary:");
|
||||||
|
write_objects(makefile, sources);
|
||||||
|
write_images(makefile, images);
|
||||||
|
fprintf(makefile, "\n\t");
|
||||||
|
{
|
||||||
|
fprintf(makefile, "$(CC) -L $(CYTO_LIB) -lCytoplasm $(LDFLAGS)");
|
||||||
|
write_objects(makefile, sources);
|
||||||
|
write_images(makefile, images);
|
||||||
|
fprintf(makefile, " -o $(BINARY)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write rules for every source */
|
||||||
|
for (i = 0; i < str_array_len(sources); i++)
|
||||||
|
{
|
||||||
|
char *src = str_array_get(sources, i);
|
||||||
|
char *ofl = string_rep_ext(src, ".c", ".o");
|
||||||
|
char *obj = string_cat("build", ofl + 3);
|
||||||
|
|
||||||
|
fprintf(makefile, "%s: %s\n", obj, src);
|
||||||
|
{
|
||||||
|
str_array_t *s = split(obj);
|
||||||
|
ssize_t j;
|
||||||
|
|
||||||
|
fprintf(makefile, "\t@mkdir -p ");
|
||||||
|
for (j = 0; j < str_array_len(s) - 1; j++)
|
||||||
|
{
|
||||||
|
fprintf(makefile, "%s/", str_array_get(s, j));
|
||||||
|
}
|
||||||
|
fprintf(makefile, "\n");
|
||||||
|
str_array_free(s);
|
||||||
|
|
||||||
|
fprintf(makefile, "\t$(CC) -c -Isrc -Isrc/include -I$(CYTO_INC) ");
|
||||||
|
fprintf(makefile, "-DVERSION=\"\\\"$(VERDION)\\\"\" ");
|
||||||
|
fprintf(makefile, "-DNAME=\"\\\"$(NAME)\\\"\" ");
|
||||||
|
fprintf(makefile, "-DCODE=\"\\\"$(CODE)\\\"\" ");
|
||||||
|
fprintf(makefile, "-DREPOSITORY=\"\\\"%s\\\"\" ", repo);
|
||||||
|
fprintf(makefile, "$(CFLAGS) $< -o $@\n");
|
||||||
|
}
|
||||||
|
free(ofl);
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
for (i = 0; i < str_array_len(images); i++)
|
||||||
|
{
|
||||||
|
char *src = str_array_get(images, i);
|
||||||
|
char *ofl = string_rep_ext(src, ".png", ".o");
|
||||||
|
char *obj = string_cat("build", ofl + 3 + 1 + 5);
|
||||||
|
char *cfl = string_cat("build", src + 3 + 1 + 5);
|
||||||
|
|
||||||
|
fprintf(makefile, "%s: %s\n", obj, src);
|
||||||
|
|
||||||
|
{
|
||||||
|
str_array_t *s = split(obj);
|
||||||
|
char *sym;
|
||||||
|
ssize_t j;
|
||||||
|
|
||||||
|
fprintf(makefile, "\t@mkdir -p ");
|
||||||
|
for (j = 0; j < str_array_len(s) - 1; j++)
|
||||||
|
{
|
||||||
|
fprintf(makefile, "%s/", str_array_get(s, j));
|
||||||
|
}
|
||||||
|
fprintf(makefile, "\n");
|
||||||
|
sym = j != -1 ? str_array_get(s, j): NULL;
|
||||||
|
sym = string_rep_ext(sym, ".o", "");
|
||||||
|
str_array_free(s);
|
||||||
|
|
||||||
|
fprintf(makefile, "\ttools/out/b64 $< 'media_%s' '%s.c'\n", sym, obj);
|
||||||
|
fprintf(makefile, "\t$(CC) -c %s.c -o $@\n", obj);
|
||||||
|
free(sym);
|
||||||
|
}
|
||||||
|
free(obj);
|
||||||
|
free(ofl);
|
||||||
|
free(cfl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build utilities */
|
||||||
|
utils = collect_sources("tools", true, ".c");
|
||||||
|
fprintf(makefile, "utils:");
|
||||||
|
write_executable(makefile, utils);
|
||||||
|
fprintf(makefile, "\n");
|
||||||
|
for (i = 0; i < str_array_len(utils); i++)
|
||||||
|
{
|
||||||
|
char *src = str_array_get(utils, i);
|
||||||
|
char *ofl = string_rep_ext(src, ".c", "");
|
||||||
|
char *obj = string_cat("tools/out", ofl + 5);
|
||||||
|
|
||||||
|
fprintf(makefile, "%s: %s\n", obj, src);
|
||||||
|
{
|
||||||
|
fprintf(makefile, "\t@mkdir -p tools/out\n");
|
||||||
|
fprintf(makefile, "\t$(CC) $(CFLAGS) -lCytoplasm $< -o $@\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ofl);
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build Aya */
|
||||||
|
aya = collect_sources("src/include", true, ".h");
|
||||||
|
fprintf(makefile, "ayadoc:");
|
||||||
|
write_ayas(makefile, aya);
|
||||||
|
fprintf(makefile, "\n");
|
||||||
|
for (i = 0; i < str_array_len(aya); i++)
|
||||||
|
{
|
||||||
|
char *src = str_array_get(aya, i);
|
||||||
|
char *ofl = string_rep_ext(src, ".h", ".html");
|
||||||
|
char *obj = string_cat("$(AYAYAS)", ofl + 3 + 1 + 7);
|
||||||
|
|
||||||
|
fprintf(makefile, "%s: %s\n", obj, src);
|
||||||
|
{
|
||||||
|
str_array_t *s = split(obj);
|
||||||
|
ssize_t j;
|
||||||
|
|
||||||
|
fprintf(makefile, "\t@mkdir -p ");
|
||||||
|
for (j = 0; j < str_array_len(s) - 1; j++)
|
||||||
|
{
|
||||||
|
fprintf(makefile, "%s/", str_array_get(s, j));
|
||||||
|
}
|
||||||
|
fprintf(makefile, "\n");
|
||||||
|
str_array_free(s);
|
||||||
|
|
||||||
|
fprintf(makefile,
|
||||||
|
"\ttools/out/aya "
|
||||||
|
"-C etc/ayadoc/style.css "
|
||||||
|
"-p $(NAME) "
|
||||||
|
"-i $< -o $@\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ofl);
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(makefile, "install-parsee: binary\n");
|
||||||
|
{
|
||||||
|
fprintf(makefile, "\tmkdir -m 755 -p $(PREFIX)/bin\n");
|
||||||
|
fprintf(makefile, "\tcp $(BINARY) $(PREFIX)/bin\n");
|
||||||
|
fprintf(makefile, "\tchmod 755 $(PREFIX)/bin/$(BINARY)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(makefile, "install-tools: utils\n");
|
||||||
|
fprintf(makefile, "\tmkdir -m 755 -p $(PREFIX)/bin\n");
|
||||||
|
for (i = 0; i < str_array_len(utils); i++)
|
||||||
|
{
|
||||||
|
char *tool = str_array_get(utils, i);
|
||||||
|
char *ofl = string_rep_ext(tool, ".c", "");
|
||||||
|
char *obj = string_cat("tools/out", ofl + 5);
|
||||||
|
char *bna = basename(obj);
|
||||||
|
|
||||||
|
fprintf(makefile, "\tcp %s $(PREFIX)/bin/parsee-%s\n", obj, bna);
|
||||||
|
fprintf(makefile, "\tchmod 755 $(PREFIX)/bin/parsee-%s\n", bna);
|
||||||
|
|
||||||
|
free(ofl);
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
fprintf(makefile, "install-aya: ayadoc\n");
|
||||||
|
fprintf(makefile, "\tmkdir -m 755 -p $(PREFIX)/aya/$(BINARY)\n");
|
||||||
|
fprintf(makefile, "\tcp -R $(AYAYAS)/* $(PREFIX)/aya/$(BINARY)\n");
|
||||||
|
fprintf(makefile, "install-man:\n");
|
||||||
|
fprintf(makefile, "\tmkdir -m 755 -p $(PREFIX)/share/man\n");
|
||||||
|
fprintf(makefile, "\tcp -R etc/man/* $(PREFIX)/share/man\n");
|
||||||
|
|
||||||
|
fprintf(makefile,
|
||||||
|
"install: "
|
||||||
|
"install-parsee "
|
||||||
|
"install-tools "
|
||||||
|
"install-aya "
|
||||||
|
"install-man\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
fprintf(makefile, "clean:\n\trm -rf ayaya build $(BINARY) tools/out\n");
|
||||||
|
|
||||||
|
str_array_free(sources);
|
||||||
|
str_array_free(images);
|
||||||
|
str_array_free(utils);
|
||||||
|
str_array_free(aya);
|
||||||
|
fflush(makefile);
|
||||||
|
fclose(makefile);
|
||||||
|
free(repo);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
return main_build(argc, argv);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue