[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tyndur-devel] [PATCH] build hinzugefuegt
+ build: Erster Commit des Buildtools fuer tyndur
---
src/modules/c/build/Makefile.all | 7 ++
src/modules/c/build/build.c | 202 +++++++++++++++++++++++++++++++++++
src/modules/c/build/dir.c | 138 ++++++++++++++++++++++++
src/modules/c/build/include/build.h | 41 +++++++
src/modules/c/build/main.c | 61 +++++++++++
5 files changed, 449 insertions(+), 0 deletions(-)
create mode 100644 src/modules/c/build/Makefile.all
create mode 100644 src/modules/c/build/build.c
create mode 100644 src/modules/c/build/dir.c
create mode 100644 src/modules/c/build/include/build.h
create mode 100644 src/modules/c/build/main.c
diff --git a/src/modules/c/build/Makefile.all b/src/modules/c/build/Makefile.all
new file mode 100644
index 0000000..8c9b17a
--- /dev/null
+++ b/src/modules/c/build/Makefile.all
@@ -0,0 +1,7 @@
+shopt -s extglob
+source $LOST_BUILDMK_ROOT/config.sh
+
+echo "LD $1/apps/build"
+
+$LOST_TOOLS_LD -obuild -Ttext=0x40000000 *.o --start-group $2 --end-group
+$LOST_TOOLS_STRIP -s build -o $1/apps/build
diff --git a/src/modules/c/build/build.c b/src/modules/c/build/build.c
new file mode 100644
index 0000000..391e025
--- /dev/null
+++ b/src/modules/c/build/build.c
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "build.h"
+
+#if 0
+static const char* cflags = "-m32 -g -O0 -Wall -fno-stack-protector -nostdinc"
+ " -fno-leading-underscore -fno-omit-frame-pointer -fno-strict-aliasing"
+ " -fno-builtin -c";
+#else
+//static const char* cflags = "-c -combine";
+static const char* cflags = "-c";
+#endif
+
+static const char* fpcflags = "-n -Cn -CX -Tlost";
+static const char* nasmflags = "-felf -O99";
+static const char* gasflags = "-32";
+
+static int dry_run = 0;
+static char* root_path;
+
+extern int verbose;
+
+static void do_command(const char* path, const char* binary,
+ const char* args_fmt, ...)
+{
+ char* buf;
+ char* buf2;
+ char* dirname;
+ va_list ap;
+
+ asprintf(&dirname, "%s/%s", root_path, path);
+ if (verbose) {
+ printf(">>> cd %s\n", dirname);
+ }
+ chdir(dirname);
+
+ va_start(ap, args_fmt);
+ vasprintf(&buf, args_fmt, ap);
+ va_end(ap);
+
+ asprintf(&buf2, "%s %s", binary, buf);
+
+ if (verbose) {
+ printf(">>> %s\n", buf2);
+ }
+ if (!dry_run) {
+ system(buf2);
+ }
+
+ free(buf);
+ free(buf2);
+ chdir(root_path);
+}
+
+static char* get_obj_files(const char* path)
+{
+ struct build_dir* dir;
+ struct build_dir* subdir;
+ struct build_file* file;
+ char* tmp = NULL;
+ char* subdir_files;
+ char* file_list = strdup("");
+ int i;
+
+ dir = scan_directory(NULL, path);
+ for (i = 0; (file = list_get_element_at(dir->obj_files, i)); i++) {
+ tmp = file_list;
+ asprintf(&file_list, "%s %s/%s", tmp, dir->path, file->name);
+ free(tmp);
+ }
+
+ for (i = 0; (subdir = list_get_element_at(dir->subdirs, i)); i++) {
+ tmp = file_list;
+ subdir_files = get_obj_files(subdir->path);
+ asprintf(&file_list, "%s %s", tmp, subdir_files);
+ free(subdir_files);
+ free(tmp);
+ }
+
+ return file_list;
+}
+
+static void compile(const char* path, list_t* files, const char* compiler,
+ const char* flags, const char* include)
+{
+ struct build_file* file;
+ char* file_list = strdup("");
+ char* tmp;
+ int i;
+
+ for (i = 0; (file = list_get_element_at(files, i)); i++) {
+ tmp = file_list;
+ asprintf(&file_list, "%s %s", tmp, file->name);
+ free(tmp);
+ }
+
+ if (*file_list) {
+ do_command(path, compiler, "%s -I %s/%s %s %s",
+ flags, root_path, path, include, file_list);
+ }
+}
+
+static void do_build(struct build_dir* dir, const char* parent_include,
+ const char* parent_lib, int depth)
+{
+ char* include;
+ char* lib;
+ char* tmp = NULL;
+
+ char* objs;
+ struct build_dir* subdir;
+ struct build_file* file;
+ int i;
+
+ for (i = 0; i < depth; i++) {
+ printf("| ");
+ }
+ printf("+ %s\n", dir->path);
+
+ // Ggf. include-Verzeichnis anhaengen
+ if (dir->has_include) {
+ asprintf(&include, "%s -I %s/%s/include",
+ parent_include, root_path, dir->path);
+ } else {
+ include = strdup(parent_include);
+ }
+
+ if (dir->has_arch_include) {
+ tmp = include;
+ asprintf(&include, "%s -I %s/%s/include/arch/%s",
+ tmp, root_path, dir->path, arch);
+ free(tmp);
+ }
+
+ // Ggf. Lib-Verzeichnis anhaengen
+ if (dir->lib != NULL) {
+ asprintf(&lib, "%s %s/%s/lib/library.a",
+ parent_lib, root_path, dir->path);
+ } else {
+ lib = strdup(parent_lib);
+ }
+
+ // lib-Verzeichnis wird als erstes kompiliert
+ if (dir->lib) {
+ do_build(dir->lib, include, lib, depth + 1);
+ objs = get_obj_files(dir->lib->path);
+ do_command(".", "ar", "rs %s/library.a %s",
+ dir->lib->path, objs);
+ free(objs);
+ }
+
+ // Dann alle anderen Unterverzeichnisse
+ for (i = 0; (subdir = list_get_element_at(dir->subdirs, i)); i++) {
+ do_build(subdir, include, lib, depth + 1);
+ }
+
+ // Und schliesslich noch die einzelnen Dateien
+ // TODO Pruefen, ob sich Abhaengigkeiten veraendert haben
+ printf("%s: Kompilieren (C)...", dir->path);
+ fflush(stdout);
+ compile(dir->path, dir->src_files[LANG_C], "gcc", cflags, include);
+
+ printf("\r%s: Kompilieren (Pascal)...\033[K", dir->path);
+ fflush(stdout);
+ compile(dir->path, dir->src_files[LANG_PAS], "fpc", fpcflags, include);
+
+ printf("\r%s: Assemblieren (gas)...\033[K", dir->path);
+ fflush(stdout);
+ compile(dir->path, dir->src_files[LANG_ASM_GAS], "as", gasflags, include);
+
+ for (i = 0; (file = list_get_element_at(dir->src_files[LANG_ASM_NASM], i)); i++) {
+ do_command(dir->path, "nasm", "%s %s", nasmflags, file->name);
+ }
+
+ // Im Wurzelverzeichnis wird gelinkt (TODO einstellbar machen)
+ if (dir->parent == NULL) {
+ printf("\r%s: Linken...\033[K", dir->path);
+ fflush(stdout);
+
+ objs = get_obj_files(dir->path);
+ do_command(".", "gcc", "-o %s/run %s %s", dir->path, lib, objs);
+ free(objs);
+ }
+
+ printf("\r\033[K");
+ fflush(stdout);
+
+ free(include);
+ free(lib);
+}
+
+void build(struct build_dir* root)
+{
+ root_path = getcwd(NULL, 0);
+ do_build(root, "", "", 0);
+ printf("Fertig gebaut.\n");
+ free(root_path);
+}
diff --git a/src/modules/c/build/dir.c b/src/modules/c/build/dir.c
new file mode 100644
index 0000000..0a9210f
--- /dev/null
+++ b/src/modules/c/build/dir.c
@@ -0,0 +1,138 @@
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "build.h"
+
+struct build_dir* scan_directory(struct build_dir* parent, const char* path)
+{
+ DIR* dir = opendir(path);
+ struct dirent* ent;
+ char* suffix;
+ struct build_file* file;
+ enum filetype filetype;
+ struct stat stat_buf;
+ struct build_dir* build_dir;
+ struct build_dir* subdir;
+ char* file_path;
+ int i;
+
+ int nobuild = 0;
+ int ignorenobuild = 0;
+
+ if (dir == NULL) {
+ fprintf(stderr, "Verzeichnis %s kann nicht geoeffnet werden.\n",
+ path);
+ return NULL;
+ }
+
+ build_dir = calloc(1, sizeof(*build_dir));
+ build_dir->path = strdup(path);
+ build_dir->parent = parent;
+ build_dir->subdirs = list_create();
+ build_dir->obj_files = list_create();
+ for (i = 0; i < MAX_LANG; i++) {
+ build_dir->src_files[i] = list_create();
+ }
+
+// printf("---> %s\n", path);
+ while ((ent = readdir(dir))) {
+
+ filetype = OTHER_FILE;
+ suffix = strrchr(ent->d_name, '.');
+
+ asprintf(&file_path, "%s/%s", path, ent->d_name);
+ stat(file_path, &stat_buf);
+
+ if (!strcmp(ent->d_name, ".nobuild")) {
+ nobuild = 1;
+ goto next;
+ } else if (!strcmp(ent->d_name, ".ignorenobuild")) {
+ ignorenobuild = 1;
+ goto next;
+ } else if (*ent->d_name == '.') {
+ goto next;
+ } else if (S_ISDIR(stat_buf.st_mode)) {
+ filetype = SUBDIR;
+ } else if (suffix == NULL) {
+ filetype = OTHER_FILE;
+ } else if (!strcmp(suffix, ".o")) {
+ filetype = OBJ;
+ } else if (!strcmp(suffix, ".c")) {
+ filetype = LANG_C;
+ } else if (!strcmp(suffix, ".pas")) {
+ filetype = LANG_PAS;
+ } else if (!strcmp(suffix, ".asm")) {
+ filetype = LANG_ASM_NASM;
+ } else if (!strcmp(suffix, ".S")) {
+ filetype = LANG_ASM_GAS;
+ }
+
+// printf("[%s] %s\n", filetype_str[filetype], ent->d_name);
+
+ if (filetype == OTHER_FILE) {
+ goto next;
+ }
+
+ file = calloc(1, sizeof(*file));
+ file->type = LANG_ASM_GAS;
+ file->name = strdup(ent->d_name);
+
+ switch (filetype) {
+ case SUBDIR:
+ if (!strcmp(file->name, "include")) {
+ DIR* arch_dir;
+ char* tmp;
+
+ build_dir->has_include = 1;
+
+ asprintf(&tmp, "include/arch/%s", arch);
+ arch_dir = opendir(tmp);
+ free(tmp);
+
+ if (arch_dir != NULL) {
+ closedir(arch_dir);
+ build_dir->has_arch_include = 1;
+ }
+
+ } else if (!strcmp(file->name, "lib")) {
+ build_dir->lib = scan_directory(build_dir, file_path);
+ } else if (!strcmp(file->name, "arch")) {
+ char* tmp;
+ asprintf(&tmp, "%s/%s", file_path, arch);
+ subdir = scan_directory(build_dir, tmp);
+ free(tmp);
+ if (subdir != NULL) {
+ list_push(build_dir->subdirs, subdir);
+ }
+ } else {
+ subdir = scan_directory(build_dir, file_path);
+ if (subdir != NULL) {
+ list_push(build_dir->subdirs, subdir);
+ }
+ }
+ break;
+ case OBJ:
+ list_push(build_dir->obj_files, file);
+ break;
+ default:
+ list_push(build_dir->src_files[filetype], file);
+ break;
+ }
+
+ next:
+ free(file_path);
+ }
+// printf("<--- %s\n", path);
+
+ closedir(dir);
+
+ if (nobuild && !ignorenobuild) {
+ // TODO Freigeben
+ return NULL;
+ }
+
+ return build_dir;
+}
diff --git a/src/modules/c/build/include/build.h b/src/modules/c/build/include/build.h
new file mode 100644
index 0000000..2bd2326
--- /dev/null
+++ b/src/modules/c/build/include/build.h
@@ -0,0 +1,41 @@
+#ifndef _BUILD_H_
+#define _BUILD_H_
+
+#include "collections.h"
+
+enum filetype {
+ LANG_C,
+ LANG_PAS,
+ LANG_ASM_GAS,
+ LANG_ASM_NASM,
+
+#define MAX_LANG OTHER_FILE
+ OTHER_FILE,
+ SUBDIR,
+ OBJ,
+};
+
+
+extern char* filetype_str[];
+extern char* arch;
+
+struct build_dir {
+ int has_include;
+ int has_arch_include;
+ char* path;
+ struct build_dir* parent;
+ struct build_dir* lib;
+ list_t* src_files[MAX_LANG];
+ list_t* obj_files;
+ list_t* subdirs;
+};
+
+struct build_file {
+ enum filetype type;
+ char* name;
+};
+
+struct build_dir* scan_directory(struct build_dir* parent, const char* path);
+void build(struct build_dir* root);
+
+#endif
diff --git a/src/modules/c/build/main.c b/src/modules/c/build/main.c
new file mode 100644
index 0000000..ef91ea8
--- /dev/null
+++ b/src/modules/c/build/main.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "build.h"
+
+char* filetype_str[] = {
+ [OTHER_FILE] = " ? ",
+ [SUBDIR] = "DIR",
+ [OBJ] = "OBJ",
+ [LANG_C] = " C ",
+ [LANG_PAS] = "PAS",
+ [LANG_ASM_GAS] = "ASM",
+ [LANG_ASM_NASM] = "ASM",
+};
+
+char* arch = "i386";
+int verbose = 0;
+
+static void usage(char* binary)
+{
+ fprintf(stderr, "Aufruf: %s [-v] [<Wurzelverzeichnis>]\n", binary);
+ exit(1);
+}
+
+int main(int argc, char** argv)
+{
+ struct build_dir* rootdir;
+ int i;
+ char* rootdir_path = NULL;
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-v")) {
+ verbose = 1;
+ } else if (argv[i][0] == '-') {
+ usage(argv[0]);
+ } else if (rootdir_path) {
+ usage(argv[0]);
+ } else {
+ rootdir_path = argv[i];
+ }
+ }
+
+ if (rootdir_path) {
+ if (chdir(argv[i])) {
+ fprintf(stderr, "Verzeichnis nicht gefunden\n");
+ return 1;
+ }
+ }
+
+ rootdir = scan_directory(NULL, ".");
+ if (rootdir == NULL) {
+ fprintf(stderr, "Verzeichnis nicht gefunden\n");
+ return 1;
+ }
+
+ build(rootdir);
+
+ return 0;
+}
--
1.5.6.5