[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