mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 15:15:10 +00:00
[ADD/WIP] build.c script, raise to 0.1
This commit is contained in:
parent
34bd036ab7
commit
8ce69d0829
4 changed files with 844 additions and 5 deletions
4
Makefile
4
Makefile
|
|
@ -20,12 +20,8 @@ CYTO_LIB ?=/usr/local/lib # Where's Cytoplasm's library is
|
||||||
# located.
|
# located.
|
||||||
PREFIX ?=/usr/local
|
PREFIX ?=/usr/local
|
||||||
|
|
||||||
SOURCE=src
|
|
||||||
OBJECT=build
|
|
||||||
AYAS=ayaya
|
AYAS=ayaya
|
||||||
ETC=etc
|
ETC=etc
|
||||||
INCLUDES=src/include
|
|
||||||
CC ?=cc
|
|
||||||
CFLAGS=-I$(SOURCE) -I$(INCLUDES) -I$(CYTO_INC) -DNAME="\"$(NAME)\"" -DVERSION="\"$(VERSION)\"" -DREPOSITORY=\"$(REPOSITORY)\" -DCODE=\"$(CODE)\" -O3 -g -Wall -Werror
|
CFLAGS=-I$(SOURCE) -I$(INCLUDES) -I$(CYTO_INC) -DNAME="\"$(NAME)\"" -DVERSION="\"$(VERSION)\"" -DREPOSITORY=\"$(REPOSITORY)\" -DCODE=\"$(CODE)\" -O3 -g -Wall -Werror
|
||||||
LDFLAGS=-L $(CYTO_LIB) -lCytoplasm -O3 -g
|
LDFLAGS=-L $(CYTO_LIB) -lCytoplasm -O3 -g
|
||||||
AFLAGS=-C "$(ETC)/ayadoc/style.css" -p "$(NAME)"
|
AFLAGS=-C "$(ETC)/ayadoc/style.css" -p "$(NAME)"
|
||||||
|
|
|
||||||
785
build.c
Normal file
785
build.c
Normal file
|
|
@ -0,0 +1,785 @@
|
||||||
|
/* 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/wait.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.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 *cc;
|
||||||
|
} basic;
|
||||||
|
|
||||||
|
char *repo;
|
||||||
|
} buildinfo_t;
|
||||||
|
static void
|
||||||
|
destroy_buildinfo(buildinfo_t *info)
|
||||||
|
{
|
||||||
|
if (!info)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->basic.codename)
|
||||||
|
{
|
||||||
|
free(info->basic.codename);
|
||||||
|
info->basic.codename = NULL;
|
||||||
|
}
|
||||||
|
if (info->basic.version)
|
||||||
|
{
|
||||||
|
free(info->basic.version);
|
||||||
|
info->basic.version = NULL;
|
||||||
|
}
|
||||||
|
if (info->basic.name)
|
||||||
|
{
|
||||||
|
free(info->basic.name);
|
||||||
|
info->basic.name = NULL;
|
||||||
|
}
|
||||||
|
if (info->basic.binary)
|
||||||
|
{
|
||||||
|
free(info->basic.binary);
|
||||||
|
info->basic.binary = NULL;
|
||||||
|
}
|
||||||
|
if (info->basic.src)
|
||||||
|
{
|
||||||
|
free(info->basic.src);
|
||||||
|
info->basic.src = NULL;
|
||||||
|
}
|
||||||
|
if (info->basic.inc)
|
||||||
|
{
|
||||||
|
free(info->basic.inc);
|
||||||
|
info->basic.inc = NULL;
|
||||||
|
}
|
||||||
|
if (info->basic.obj)
|
||||||
|
{
|
||||||
|
free(info->basic.obj);
|
||||||
|
info->basic.obj = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->repo)
|
||||||
|
{
|
||||||
|
free(info->repo);
|
||||||
|
info->repo = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 bool
|
||||||
|
build_file(char *cSource, buildinfo_t info, bool isTool)
|
||||||
|
{
|
||||||
|
char *args[16] = { 0 };
|
||||||
|
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);
|
||||||
|
|
||||||
|
args[i++] = Compiler(info);
|
||||||
|
if (isTool)
|
||||||
|
{
|
||||||
|
args[i++] = "-lCytoplasm";
|
||||||
|
args[i++] = "-I.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
args[i++] = "-c";
|
||||||
|
}
|
||||||
|
args[i++] = cSource;
|
||||||
|
args[i++] = "-o";
|
||||||
|
args[i++] = oFileName;
|
||||||
|
|
||||||
|
args[i++] = "-I";
|
||||||
|
args[i++] = info.basic.inc;
|
||||||
|
args[i++] = "-I";
|
||||||
|
args[i++] = info.basic.src;
|
||||||
|
|
||||||
|
{
|
||||||
|
char *pre = string_cat("\"", info.basic.version);
|
||||||
|
char *pos = string_cat(pre, "\"");
|
||||||
|
vers = string_cat("-DVERSION=", pos);
|
||||||
|
args[i++] = vers;
|
||||||
|
|
||||||
|
free(pos);
|
||||||
|
free(pre);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char *pre = string_cat("\"", info.basic.name);
|
||||||
|
char *pos = string_cat(pre, "\"");
|
||||||
|
name = string_cat("-DNAME=", pos);
|
||||||
|
args[i++] = name;
|
||||||
|
|
||||||
|
free(pos);
|
||||||
|
free(pre);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char *pre = string_cat("\"", info.basic.codename);
|
||||||
|
char *pos = string_cat(pre, "\"");
|
||||||
|
code = string_cat("-DCODE=", pos);
|
||||||
|
args[i++] = code;
|
||||||
|
|
||||||
|
free(pos);
|
||||||
|
free(pre);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char *pre = string_cat("\"", info.repo);
|
||||||
|
char *pos = string_cat(pre, "\"");
|
||||||
|
repo = string_cat("-DREPOSITORY=", pos);
|
||||||
|
args[i++] = repo;
|
||||||
|
|
||||||
|
free(pos);
|
||||||
|
free(pre);
|
||||||
|
}
|
||||||
|
|
||||||
|
args[i++] = NULL;
|
||||||
|
|
||||||
|
ret = exec_code(Compiler(info), 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;
|
||||||
|
size_t i;
|
||||||
|
bool ret = true;
|
||||||
|
if (!arr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = str_array_create();
|
||||||
|
str_array_add(flags, Compiler(info));
|
||||||
|
|
||||||
|
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("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);
|
||||||
|
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
printf("\tCC %s...\n", file);
|
||||||
|
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);
|
||||||
|
/* Step 6: Build every Ayadoc */
|
||||||
|
|
||||||
|
/* Step 7: Good! */
|
||||||
|
|
||||||
|
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/...) */
|
||||||
|
return main_build(argc, argv);
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
CODE=tomboyish-bridges-adventure
|
CODE=tomboyish-bridges-adventure
|
||||||
NAME=Parsee
|
NAME=Parsee
|
||||||
VERSION=0.0.1
|
VERSION=0.1.0
|
||||||
BINARY=parsee
|
BINARY=parsee
|
||||||
|
SOURCE=src
|
||||||
|
INCLUDES=src/include
|
||||||
|
OBJECT=build
|
||||||
|
CC=tcc
|
||||||
|
|
|
||||||
54
tools/b64.c
Normal file
54
tools/b64.c
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/* b64.c - Generates a C string symbol stored as Base64
|
||||||
|
* ============================================================
|
||||||
|
* Under CC0, as its a rather useful example of a KappaChat tool.
|
||||||
|
* See LICENSE for more information about Parsee's licensing. */
|
||||||
|
|
||||||
|
#include <Cytoplasm/HashMap.h>
|
||||||
|
#include <Cytoplasm/Stream.h>
|
||||||
|
#include <Cytoplasm/Base64.h>
|
||||||
|
#include <Cytoplasm/Memory.h>
|
||||||
|
#include <Cytoplasm/Array.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
Main(Array *args, HashMap *env)
|
||||||
|
{
|
||||||
|
char *file = ArrayGet(args, 1);
|
||||||
|
char *symbol = ArrayGet(args, 2);
|
||||||
|
char *out = ArrayGet(args, 3);
|
||||||
|
|
||||||
|
Stream *inStream;
|
||||||
|
uint8_t *bytes;
|
||||||
|
size_t len;
|
||||||
|
int o;
|
||||||
|
|
||||||
|
char *b64;
|
||||||
|
Stream *outStream;
|
||||||
|
|
||||||
|
if (!file || !symbol || !out)
|
||||||
|
{
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inStream = StreamOpen(file, "rb");
|
||||||
|
bytes = NULL;
|
||||||
|
len = 0;
|
||||||
|
while ((o = StreamGetc(inStream)) != EOF)
|
||||||
|
{
|
||||||
|
bytes = Realloc(bytes, len + 1);
|
||||||
|
bytes[len++] = o;
|
||||||
|
}
|
||||||
|
StreamClose(inStream);
|
||||||
|
|
||||||
|
b64 = Base64Encode((const char *) bytes, len);
|
||||||
|
Free(bytes);
|
||||||
|
outStream = StreamOpen(out, "w");
|
||||||
|
StreamPrintf(outStream, "const char %s[] = ", symbol);
|
||||||
|
StreamPrintf(outStream, "\"%s\";\n", b64);
|
||||||
|
Free(b64);
|
||||||
|
StreamFlush(outStream);
|
||||||
|
StreamClose(outStream);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue