On Sun, Mar 29 22:17, Kevin Wolf wrote: > + build: Erster Commit des Buildtools fuer tyndur > > Compilegetestet ist diese neue Version sogar ;-) > --- > src/modules/c/build/Makefile.all | 7 + > src/modules/c/build/build.c | 272 +++++++++++++++++++++++++++++++++++ > src/modules/c/build/dir.c | 235 ++++++++++++++++++++++++++++++ > src/modules/c/build/include/build.h | 80 ++++++++++ > src/modules/c/build/main.c | 121 ++++++++++++++++ > 5 files changed, 715 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/dir.c b/src/modules/c/build/dir.c > new file mode 100644 > index 0000000..1919fb0 > --- /dev/null > +++ b/src/modules/c/build/dir.c > @@ -0,0 +1,235 @@ > +/* > + * Copyright (c) 2009 The tyndur Project. All rights reserved. > + * > + * This code is derived from software contributed to the tyndur Project > + * by Kevin Wolf. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. All advertising materials mentioning features or use of this software > + * must display the following acknowledgement: > + * This product includes software developed by the tyndur Project > + * and its contributors. > + * 4. Neither the name of the tyndur Project nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED > + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, > + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, > + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; > + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR > + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF > + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#include <dirent.h> > +#include <stdio.h> > +#include <string.h> > +#include <stdlib.h> > +#include <sys/stat.h> > + > +#include "build.h" > + > +/** > + * Durchsucht ein Verzeichnis und speichert alle fuer das Bauen noetige > + * Informationen in dynamisch allozierten Datenstrukturen, die vom Aufrufer > + * mir free_directory() freigegeben werden muss. > + * > + * Das bedeutet: > + * - Alle Quellcodedateien sammeln (*.c, *.pas, ...) > + * - Includeverzeichnisse speichern > + * - lib-Verzeichnisse erfassen > + * - Bei arch/-Verzeichnissen nur die richtige Architektur beruecksichtigen > + * - .nobuild und .ignorenobuild beachten > + */ > +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; > + } > + > + // Speicher fuer Verzeichnis-struct anlegen und initialiseren > + 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(); > + } > + > + // Dateien und Unterverzeichnisse einlesen > + 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); > + > + // Dateityp erkennen > + 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; > + } > + > + // Wenn bis hierher nichts verwertbares gefunden wurde, wird die Datei > + // einfach ignoriert. > + if (filetype == OTHER_FILE) { > + goto next; > + } > + > + // Datei je nach Typ verarbeiten > + file = calloc(1, sizeof(*file)); > + file->type = filetype; > + file->name = strdup(ent->d_name); > + > + switch (filetype) { > + case SUBDIR: > + // Unterverzeichnisse werden je nach Namen unterschiedlich > + // erfasst: > + // > + // - include/ wird zu den Includepfaden hinzugefuegt, das > + // Verzeicnis wird nicht weiter durchsucht > + // - In include/arch/ und arch/ wird nur das richtige > + // Unterverzeichnis weiterverfolgt > + // - lib/ wird gesondert gespeichert, damit es vor allen > + // anderen Verzeichnissen gebaut werden kann > + // - Alles andere wird einfach als Unterverzeichnis gemerkt > + 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: > + // Objektdateien haben ihre eigene Liste > + list_push(build_dir->obj_files, file); > + break; > + default: > + // Quellcodedateien werden nach Sprache getrennt gespeichert > + list_push(build_dir->src_files[filetype], file); > + break; > + } > + > + next: > + free(file_path); > + } > + > + closedir(dir); > + > + // Wenn das Verzeichnis gar nicht gebaut werden soll, besser nichts > + // zurueckgeben > + if (nobuild && !ignorenobuild) { > + free_directory(build_dir); > + return NULL; > + } > + > + return build_dir; > +} > + > +/** > + * Gibt die Datenstrukturen fuer ein Verzeichnis wieder frei > + */ > +void free_directory(struct build_dir* dir) > +{ > + int i; > + struct build_dir* subdir; > + struct build_file* file; > + > + if (dir == NULL) { > + return; > + } > + > + while ((subdir = list_pop(dir->subdirs))) { > + free_directory(subdir); > + } > + > + while ((file = list_pop(dir->obj_files))) { > + free(file->name); > + free(file); > + } Bräuchtest du da nicht noch irgend ein list_destroy() oder zwei? > + > + for (i = 0; i < MAX_LANG; i++) { > + while ((file = list_pop(dir->src_files[i]))) { > + free(file->name); > + free(file); > + } > + } > + Oder drei... > + free_directory(dir->lib); > + free(dir->path); > + free(dir); > +} > diff --git a/src/modules/c/build/main.c b/src/modules/c/build/main.c > new file mode 100644 > index 0000000..0f725cc > --- /dev/null > +++ b/src/modules/c/build/main.c > @@ -0,0 +1,121 @@ > +/* > + * Copyright (c) 2009 The tyndur Project. All rights reserved. > + * > + * This code is derived from software contributed to the tyndur Project > + * by Kevin Wolf. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. All advertising materials mentioning features or use of this software > + * must display the following acknowledgement: > + * This product includes software developed by the tyndur Project > + * and its contributors. > + * 4. Neither the name of the tyndur Project nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED > + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, > + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, > + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; > + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR > + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF > + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#include <stdio.h> > +#include <unistd.h> > +#include <stdlib.h> > +#include <string.h> > + > +#include "build.h" > + > +/** > + * Legt Kuerzel fuer Dateitypen fest, die fuer die Anzeige benutzt werden > + * koennen, waehrend die Datei verarbeitet wird > + */ > +char* filetype_str[] = { > + [OTHER_FILE] = " ? ", > + [SUBDIR] = "DIR", > + [OBJ] = "OBJ", > + [LANG_C] = " C ", > + [LANG_PAS] = "PAS", > + [LANG_ASM_GAS] = "ASM", > + [LANG_ASM_NASM] = "ASM", > +}; > + > +/** > + * Legt die aktuelle Architektur fest. > + * > + * Wird benutzt, falls arch/-Verzeichnisse im Projekt existieren > + */ > +char* arch = "i386"; > + > +/** > + * Mit verbose != 0 wird die Kommandozeile aller aufgerufenen Tools angezeigt. > + * Sonst wird nur eine kurze Statusmeldung ausgegeben. > + */ > +int verbose = 0; > + > +/// Nur Meldungen ausgeben, aber nichts wirklich aufrufen > +int dryrun= 0; > + > + > +static void usage(char* binary) > +{ > + fprintf(stderr, "Aufruf: %s [-v] [--dry-run] [<Wurzelverzeichnis>]\n", > + binary); > + exit(1); > +} > + > +int main(int argc, char** argv) > +{ > + struct build_dir* rootdir; > + int i; > + char* rootdir_path = NULL; > + > + // Verarbeitung der Kommandozeilenparameter > + for (i = 1; i < argc; i++) { > + if (!strcmp(argv[i], "-v")) { > + verbose = 1; > + } else if (!strcmp(argv[i], "--dry-run")) { > + dry_run = 1; > + } else if (argv[i][0] == '-') { > + usage(argv[0]); > + } else if (rootdir_path) { > + usage(argv[0]); > + } else { > + rootdir_path = argv[i]; > + } > + } > + > + // Ins Wurzelverzeichnis des Projekts wechseln > + if (rootdir_path) { > + if (chdir(argv[i])) { > + fprintf(stderr, "Verzeichnis nicht gefunden\n"); > + return 1; > + } > + } > + > + // Alle zu kompilierenden Dateien, Includeverzeichnisse usw. erfassen > + rootdir = scan_directory(NULL, "."); > + if (rootdir == NULL) { > + fprintf(stderr, "Verzeichnis nicht gefunden\n"); > + return 1; > + } > + > + // Bauen! > + build(rootdir); > + Vielleich noch ein free_directory(rootdir)? ;-) > + return 0; > +} Mehr kann ich momentan leider nich bemängeln. ;-) -- Antoine Kaufmann <toni@xxxxxxxxxxxxxxxx>
Attachment:
pgp2_coKVoLhv.pgp
Description: PGP signature