mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 13:45: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
|
||||
- name: Build Parsee
|
||||
run: |
|
||||
cc configure.c -o configure && ./configure
|
||||
echo 'CFLAGS=-Werror -Wall -Wextra -pedantic' >> build.conf
|
||||
cat build.conf
|
||||
make && make ayadoc
|
||||
|
|
|
|||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -6,6 +6,8 @@ parsee
|
|||
.*
|
||||
data
|
||||
data/*
|
||||
Makefile
|
||||
configure
|
||||
|
||||
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