mirror of
https://git.kappach.at/lda/Parsee.git
synced 2025-05-12 23:13:48 +02:00
863 lines
18 KiB
C
863 lines
18 KiB
C
/* 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;
|
|
}
|