From e9f481c0d0776f07dd59136ee8166e0d8e6f049f Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Fri, 27 Jan 2006 05:33:47 +0000 Subject: [PATCH] Separate Makefile output functions --- src/Makefile | 5 +- src/configure.c | 1020 +++++----------------------------------------- src/configure.h | 80 ++++ src/makefile.c | 913 +++++++++++++++++++++++++++++++++++++++++ src/makefile.h | 21 + src/project.conf | 2 +- 6 files changed, 1116 insertions(+), 925 deletions(-) create mode 100644 src/configure.h create mode 100644 src/makefile.c create mode 100644 src/makefile.h diff --git a/src/Makefile b/src/Makefile index 03af076..bcba026 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,7 +13,7 @@ INSTALL = install all: $(TARGETS) -configure_OBJS = configure.o +configure_OBJS = configure.o makefile.o configure_CFLAGS = $(CFLAGSF) $(CFLAGS) configure: $(configure_OBJS) $(CC) $(LDFLAGSF) $(LDFLAGS) -o configure $(configure_OBJS) @@ -21,6 +21,9 @@ configure: $(configure_OBJS) configure.o: configure.c $(CC) $(configure_CFLAGS) -c configure.c +makefile.o: makefile.c + $(CC) $(configure_CFLAGS) -c makefile.c + clean: $(RM) $(configure_OBJS) diff --git a/src/configure.c b/src/configure.c index 0c6b4f1..7040ed1 100644 --- a/src/configure.c +++ b/src/configure.c @@ -2,39 +2,38 @@ -#include +#include #include #include #include -#include - -ARRAY(Config *, config); +#include "makefile.h" +#include "configure.h" -#define PROJECT_CONF "project.conf" -#define MAKEFILE "Makefile" - - -/* types */ -typedef enum _TargetType { TT_BINARY = 0, TT_LIBRARY, TT_OBJECT, TT_UNKNOWN -} TargetType; -#define TT_LAST TT_UNKNOWN -String * sTargetType[TT_LAST] = { "binary", "library", "object" }; -static TargetType _target_type(String const * target) +/* configure */ +/* variables */ +const String * sHostArch[HA_LAST+1] = { - int i; + "i386", "i486", "i586", "i686", + "sparc", + "unknown" +}; +const String * sHostOS[HO_LAST+1] = +{ + "Linux", + "FreeBSD", "NetBSD", "OpenBSD", + "unknown" +}; +const String * sHostKernel[HK_LAST+1] = +{ + "2.0", "2.2", "2.4", "2.6", + "2.0", + "unknown" +}; - for(i = 0; i < TT_LAST; i++) - if(string_compare(sTargetType[i], target) == 0) - return i; - return TT_UNKNOWN; -} - -typedef enum _ObjectType { OT_C_SOURCE = 0, OT_ASM_SOURCE, OT_UNKNOWN -} ObjectType; -#define OT_LAST OT_UNKNOWN -String * sObjectType[OT_LAST] = { "c", "S" }; -static String * _source_extension(String * source) +const String * sTargetType[TT_LAST] = { "binary", "library", "object" }; +const String * sObjectType[OT_LAST] = { "c", "S" }; +String * _source_extension(String * source) { int len; @@ -43,49 +42,70 @@ static String * _source_extension(String * source) return &source[len+1]; return NULL; } -static ObjectType _object_type(String * extension) -{ - int i; - - for(i = 0; i < OT_LAST; i++) - if(string_compare(sObjectType[i], extension) == 0) - return i; - return OT_UNKNOWN; -} - - -/* configure */ -/* types */ -typedef int Prefs; -#define PREFS_n 0x1 -#define PREFS_v 0x2 /* functions */ -static int _configure_error(char const * message, int ret); +int configure_error(char const * message, int ret) +{ + fprintf(stderr, "%s", "configure: "); + perror(message); + return ret; +} + + +int enum_string(int last, const String * strings[], String * str) +{ + int i; + + for(i = 0; i < last; i++) + if(string_compare(strings[i], str) == 0) + return i; + return last; +} + + +int enum_string_short(int last, const String * strings[], String * str) +{ + int i; + + for(i = 0; i < last; i++) + if(string_compare_length(strings[i], str, + string_length(strings[i])) == 0) + return i; + return last; +} + + +/* Configure */ +static void _configure_detect(Configure * configure); static int _configure_load(Prefs * prefs, char const * directory, configArray * ca); -static int _configure_do(Prefs * prefs, configArray * ca); +static int _configure_do(Configure * configure, configArray * ca); static int _configure(Prefs * prefs, char const * directory) { + Configure cfgr; configArray * ca; int ret; int i; Config * p; - int prefs2; if((ca = configarray_new()) == NULL) - return _configure_error("libSystem", 2); + return configure_error("libSystem", 2); + cfgr.prefs = *prefs; + _configure_detect(&cfgr); ret = _configure_load(prefs, directory, ca); if(ret == 0) { if(*prefs & PREFS_n) - ret = _configure_do(prefs, ca); + ret = _configure_do(&cfgr, ca); else { - prefs2 = PREFS_n; - if(_configure_do(&prefs2, ca) == 0) - ret = _configure_do(prefs, ca); + cfgr.prefs = PREFS_n; + if(_configure_do(&cfgr, ca) == 0) + { + cfgr.prefs = *prefs; + ret = _configure_do(&cfgr, ca); + } } } for(i = array_count(ca); i > 0; i--) @@ -97,11 +117,29 @@ static int _configure(Prefs * prefs, char const * directory) return ret; } -static int _configure_error(char const * message, int ret) + +/* private */ +static void _configure_detect(Configure * configure) { - fprintf(stderr, "%s", "configure: "); - perror(message); - return ret; + struct utsname un; + + if(uname(&un) != 0) + { + configure_error("system detection failed", 0); + configure->arch = HA_UNKNOWN; + configure->os = HO_UNKNOWN; + configure->kernel = HK_UNKNOWN; + return; + } + configure->arch = enum_string(HA_LAST, sHostArch, un.machine); + configure->os = enum_string(HO_LAST, sHostOS, un.sysname); + configure->kernel = enum_string_short(HK_LAST, sHostKernel, + un.release); + if(configure->prefs & PREFS_v) + fprintf(stderr, "Detected system %s version %s on %s\n", + sHostOS[configure->os], + sHostKernel[configure->kernel], + sHostArch[configure->arch]); } @@ -116,19 +154,19 @@ static int _configure_load(Prefs * prefs, String const * directory, String * subdirs = NULL; if((path = string_new(directory)) == NULL) - return _configure_error(directory, 1); + return configure_error(directory, 1); if(string_append(&path, "/") != 0 || string_append(&path, PROJECT_CONF) != 0 || (config = config_new()) == NULL) { string_delete(path); - return _configure_error(directory, 1); + return configure_error(directory, 1); } config_set(config, "", "directory", directory); if(*prefs & PREFS_v) printf("%s%s%s", "Loading project file ", path, "\n"); if(config_load(config, path) != 0) - ret = _configure_error(path, 1); + ret = configure_error(path, 1); else { array_append(ca, &config); @@ -184,9 +222,7 @@ static int _load_subdirs_subdir(Prefs * prefs, char const * directory, } -static int _do_makefile(Prefs * prefs, Config * config, String * directory, - configArray * ca, int from, int to); -static int _configure_do(Prefs * prefs, configArray * ca) +static int _configure_do(Configure * configure, configArray * ca) { int i; int cnt = array_count(ca); @@ -207,874 +243,12 @@ static int _configure_do(Prefs * prefs, configArray * ca) if(string_find(dj, di) == NULL) break; } - if(_do_makefile(prefs, ci, di, ca, i, j) != 0) + if(makefile(configure, ci, di, ca, i, j) != 0) break; } return i == cnt ? 0 : 1; } -static int _makefile_write(Prefs * prefs, Config * config, FILE * fp, - configArray * ca, int from, int to); -static int _do_makefile(Prefs * prefs, Config * config, String * directory, - configArray * ca, int from, int to) -{ - String * makefile; - FILE * fp = NULL; - int ret = 0; - - makefile = string_new(directory); - string_append(&makefile, "/"); - string_append(&makefile, MAKEFILE); - if(!(*prefs & PREFS_n) && (fp = fopen(makefile, "w")) == NULL) - ret = _configure_error(makefile, 1); - else - { - if(*prefs & PREFS_v) - printf("%s%s%s%s%s", "Creating ", MAKEFILE, " in ", - directory, "\n"); - ret += _makefile_write(prefs, config, fp, ca, from, to); - if(fp != NULL) - fclose(fp); - } - string_delete(makefile); - return ret; -} - -static int _write_variables(Prefs * prefs, Config * config, FILE * fp); -static int _write_targets(Prefs * prefs, Config * config, FILE * fp); -static int _write_objects(Prefs * prefs, Config * config, FILE * fp); -static int _write_clean(Prefs * prefs, Config * config, FILE * fp); -static int _write_distclean(Prefs * prefs, Config * config, FILE * fp); -static int _write_dist(Prefs * prefs, Config * config, FILE * fp, - configArray * ca, int from, int to); -static int _write_install(Prefs * prefs, Config * config, FILE * fp); -static int _write_uninstall(Prefs * prefs, Config * config, FILE * fp); -static int _makefile_write(Prefs * prefs, Config * config, FILE * fp, - configArray * ca, int from, int to) -{ - if(_write_variables(prefs, config, fp) != 0 - || _write_targets(prefs, config, fp) != 0 - || _write_objects(prefs, config, fp) != 0 - || _write_clean(prefs, config, fp) != 0 - || _write_distclean(prefs, config, fp) != 0 - || _write_dist(prefs, config, fp, ca, from, to) != 0 - || _write_install(prefs, config, fp) != 0 - || _write_uninstall(prefs, config, fp) != 0) - return 1; - return 0; -} - -static int _variables_package(Prefs * prefs, Config * config, FILE * fp, - String const * directory); -static int _variables_print(Prefs * prefs, Config * config, FILE * fp, - char const * input, char const * output); -static int _variables_targets(Prefs * prefs, Config * config, FILE * fp); -static int _variables_executables(Prefs * prefs, Config * config, FILE * fp); -static int _write_variables(Prefs * prefs, Config * config, FILE * fp) -{ - String const * directory = config_get(config, "", "directory"); - int ret = 0; - - ret += _variables_package(prefs, config, fp, directory); - ret += _variables_print(prefs, config, fp, "subdirs", "SUBDIRS"); - ret += _variables_targets(prefs, config, fp); - ret += _variables_executables(prefs, config, fp); - if(!(*prefs & PREFS_n)) - fputc('\n', fp); - return ret; -} - -static int _variables_package(Prefs * prefs, Config * config, FILE * fp, - String const * directory) -{ - String * package; - String * version; - - if((package = config_get(config, "", "package")) == NULL) - return 0; - if(*prefs & PREFS_v) - printf("%s%s", "Package: ", package); - if((version = config_get(config, "", "version")) == NULL) - { - if(*prefs & PREFS_v) - fputc('\n', stdout); - fprintf(stderr, "%s%s%s", "configure: ", directory, - ": \"package\" needs \"version\"\n"); - return 1; - } - if(*prefs & PREFS_v) - printf("%s%s%s", " ", version, "\n"); - if(fp != NULL) - fprintf(fp, "%s%s%s%s%s", "PACKAGE\t= ", package, - "\nVERSION\t= ", version, "\n"); - return 0; -} - -static int _variables_print(Prefs * prefs, Config * config, FILE * fp, - char const * input, char const * output) -{ - String * prints; - int i; - char c; - - if(*prefs & PREFS_n) - return 0; - if((prints = config_get(config, "", input)) == NULL) - return 0; - fprintf(fp, "%s%s", output, "\t="); - for(i = 0;; i++) - { - if(prints[i] != ',' && prints[i] != '\0') - continue; - c = prints[i]; - prints[i] = '\0'; - fprintf(fp, " %s", prints); - if(c == '\0') - break; - prints[i] = c; - prints+=i+1; - i = 0; - } - fputc('\n', fp); - return 0; -} - -static int _variables_targets(Prefs * prefs, Config * config, FILE * fp) -{ - String * prints; - int i; - char c; - String * type; - - if(*prefs & PREFS_n) - return 0; - if((prints = config_get(config, "", "targets")) == NULL) - return 0; - fprintf(fp, "%s%s", "TARGETS", "\t="); - for(i = 0;; i++) - { - if(prints[i] != ',' && prints[i] != '\0') - continue; - c = prints[i]; - prints[i] = '\0'; - if((type = config_get(config, prints, "type")) == NULL) - fprintf(fp, " %s", prints); - else - switch(_target_type(type)) - { - case TT_BINARY: - case TT_OBJECT: - case TT_UNKNOWN: - fprintf(fp, " %s", prints); - break; - case TT_LIBRARY: - fprintf(fp, " %s%s%s%s", prints, ".a ", - prints, ".so"); - break; - } - if(c == '\0') - break; - prints[i] = c; - prints+=i+1; - i = 0; - } - fputc('\n', fp); - return 0; -} - -static int _executables_variables(Config * config, FILE * fp, String * target); -static int _variables_executables(Prefs * prefs, Config * config, FILE * fp) -{ - String * targets; - int i; - char c; - - if(*prefs & PREFS_n) - return 0; - if((targets = config_get(config, "", "targets")) != NULL) - { - for(i = 0;; i++) - { - if(targets[i] != ',' && targets[i] != '\0') - continue; - c = targets[i]; - targets[i] = '\0'; - _executables_variables(config, fp, targets); - if(c == '\0') - break; - targets[i] = c; - targets+=i+1; - i = 0; - } - fprintf(fp, "%s", "RM\t= rm -f\n"); - } - if(config_get(config, "", "package")) - fprintf(fp, "%s", "LN\t= ln -sf\nTAR\t= tar cfzv\n"); - if(targets != NULL) - { - fprintf(fp, "%s", "MKDIR\t= mkdir -p\n"); - fprintf(fp, "%s", "INSTALL\t= install\n"); - } - return 0; -} - -static int _executables_variables(Config * config, FILE * fp, String * target) -{ - static Config * flag = NULL; - String * type; - char done[TT_LAST]; /* FIXME even better if'd be variable by variable */ - String * p; - TargetType tt; - - if(flag != config) - { - flag = config; - memset(done, 0, sizeof(done)); - } - if((type = config_get(config, target, "type")) == NULL) - return 0; - if(done[(tt = _target_type(type))]) - return 0; - switch(tt) - { - case TT_BINARY: - if(!done[TT_LIBRARY]) - { - fprintf(fp, "%s", "PREFIX\t= /usr/local\n"); - fprintf(fp, "%s", "DESTDIR\t=\n"); - } - fprintf(fp, "%s", "BINDIR\t= $(PREFIX)/bin\n"); - if(!done[TT_LIBRARY]) - { - fprintf(fp, "%s", "CC\t= cc\n"); - if((p = config_get(config, "", "cflags_force")) - != NULL) - fprintf(fp, "%s%s%s", "CFLAGSF\t= ", p, - "\n"); - if((p = config_get(config, "", "cflags")) - != NULL) - fprintf(fp, "%s%s%s", "CFLAGS\t= ", p, - "\n"); - } - if((p = config_get(config, "", "ldflags_force")) - != NULL) - fprintf(fp, "%s%s%s", "LDFLAGSF= ", p, "\n"); - if((p = config_get(config, "", "ldflags")) != NULL) - fprintf(fp, "%s%s%s", "LDFLAGS\t= ", p, "\n"); - break; - case TT_LIBRARY: - if(!done[TT_LIBRARY]) - { - fprintf(fp, "%s", "PREFIX\t= /usr/local\n"); - fprintf(fp, "%s", "DESTDIR\t=\n"); - } - fprintf(fp, "%s", "LIBDIR\t= $(PREFIX)/lib\n"); - if(!done[TT_BINARY]) - { - fprintf(fp, "%s", "CC\t= cc\n"); - if((p = config_get(config, "", "cflags_force")) - != NULL) - fprintf(fp, "%s%s%s", "CFLAGSF\t= ", p, - "\n"); - if((p = config_get(config, "", "cflags")) - != NULL) - fprintf(fp, "%s%s%s", "CFLAGS\t= ", p, - "\n"); - } - fprintf(fp, "%s", "AR\t= ar rc\n"); - fprintf(fp, "%s", "RANLIB\t= ranlib\n"); - fprintf(fp, "%s", "LD\t= ld -shared\n"); - break; - case TT_OBJECT: - /* FIXME */ - break; - case TT_UNKNOWN: - break; - } - done[tt] = 1; - return 0; -} - -static int _targets_all(Prefs * prefs, Config * config, FILE * fp); -static int _targets_subdirs(Prefs * prefs, Config * config, FILE * fp); -static int _targets_target(Prefs * prefs, Config * config, FILE * fp, - String * target); -static int _write_targets(Prefs * prefs, Config * config, FILE * fp) -{ - char * targets = config_get(config, "", "targets"); - char c; - int i; - int ret = 0; - - if(_targets_all(prefs, config, fp) != 0 - || _targets_subdirs(prefs, config, fp) != 0) - return 1; - if(targets == NULL) - return 0; - for(i = 0;; i++) - { - if(targets[i] != ',' && targets[i] != '\0') - continue; - c = targets[i]; - targets[i] = '\0'; - ret += _targets_target(prefs, config, fp, targets); - if(c == '\0') - break; - targets[i] = c; - targets+=i+1; - i = 0; - } - return ret; -} - -static int _targets_all(Prefs * prefs, Config * config, FILE * fp) -{ - if(*prefs & PREFS_n) - return 0; - fprintf(fp, "%s", "\nall:"); - if(config_get(config, "", "subdirs") != NULL) - fprintf(fp, "%s", " subdirs"); - if(config_get(config, "", "targets") != NULL) - fprintf(fp, "%s", " $(TARGETS)"); - fprintf(fp, "%s", "\n"); - return 0; -} - -static int _targets_subdirs(Prefs * prefs, Config * config, FILE * fp) -{ - String * subdirs; - - if(*prefs & PREFS_n) - return 0; - if((subdirs = config_get(config, "", "subdirs")) != NULL) - fprintf(fp, "%s", "\nsubdirs:\n\t@for i in $(SUBDIRS); do" - " (cd $$i && $(MAKE)) || exit; done\n"); - return 0; -} - -static int _target_objs(Prefs * prefs, Config * config, FILE * fp, - String * target); -static int _target_library(Prefs * prefs, Config * config, FILE * fp, - String * target); -static int _targets_target(Prefs * prefs, Config * config, FILE * fp, - String * target) -{ - String * type; - TargetType tt; - String * p; - - if((type = config_get(config, target, "type")) == NULL) - { - fprintf(stderr, "%s%s%s", "configure: ", target, - ": no type defined for target\n"); - return 1; - } - tt = _target_type(type); - switch(tt) - { - case TT_BINARY: - if(_target_objs(prefs, config, fp, target) != 0) - return 1; - if(*prefs & PREFS_n) - return 0; - fprintf(fp, "%s%s", target, "_CFLAGS = $(CFLAGSF)" - " $(CFLAGS)"); - if((p = config_get(config, target, "cflags")) != NULL) - fprintf(fp, "%s%s", " ", p); - fputc('\n', fp); - fprintf(fp, "%s%s%s%s", target, ": $(", target, - "_OBJS)\n"); - fprintf(fp, "%s%s%s%s%s", "\t$(CC) $(LDFLAGSF)" - " $(LDFLAGS) -o ", target, " $(", - target, "_OBJS)\n"); - break; - case TT_LIBRARY: - return _target_library(prefs, config, fp, target); - case TT_OBJECT: - if((p = config_get(config, target, "sources")) == NULL) - { - fprintf(stderr, "%s%s%s", "configure: ", target, - " no sources for target\n"); - return 1; - } - if(*prefs & PREFS_n) - return 0; - fprintf(fp, "%s%s%s%s", target, ": ", p, "\n"); - /* FIXME */ - break; - case TT_UNKNOWN: - fprintf(stderr, "%s%s%s", "configure: ", target, - ": unknown type for target\n"); - return 1; - } - return 0; -} - -static int _objs_source(Prefs * prefs, FILE * fp, String * source); -static int _target_objs(Prefs * prefs, Config * config, FILE * fp, - String * target) -{ - int ret = 0; - String * sources; - int i; - char c; - - if((sources = config_get(config, target, "sources")) == NULL) - { - fprintf(stderr, "%s%s%s", "configure: ", target, - ": no sources defined for target\n"); - return 1; - } - if(!(*prefs & PREFS_n)) - fprintf(fp, "%s%s%s", "\n", target, "_OBJS ="); - for(i = 0; ret == 0; i++) - { - if(sources[i] != ',' && sources[i] != '\0') - continue; - c = sources[i]; - sources[i] = '\0'; - ret = _objs_source(prefs, fp, sources); - if(c == '\0') - break; - sources[i] = c; - sources+=i+1; - i = 0; - } - if(!(*prefs & PREFS_n)) - fputc('\n', fp); - return ret; -} - -static int _objs_source(Prefs * prefs, FILE * fp, String * source) -{ - int ret = 0; - String * extension; - ObjectType ot; - int len; - - if((extension = _source_extension(source)) == NULL) - { - fprintf(stderr, "%s%s%s", "configure: ", source, - ": no extension for source\n"); - return 1; - } - len = string_length(source) - string_length(extension) - 1; - source[len] = '\0'; - ot = _object_type(extension); - switch(ot) - { - case OT_ASM_SOURCE: - case OT_C_SOURCE: - if(*prefs & PREFS_n) - break; - fprintf(fp, "%s%s%s", " ", source, ".o"); - break; - case OT_UNKNOWN: - ret = 1; - fprintf(stderr, "%s%s%s", "configure: ", source, - ": unknown extension for source\n"); - break; - } - source[len] = '.'; - return ret; -} - -static int _target_library(Prefs * prefs, Config * config, FILE * fp, - String * target) -{ - String * p; - - if(_target_objs(prefs, config, fp, target) != 0) - return 1; - if(*prefs & PREFS_n) - return 0; - fprintf(fp, "%s%s", target, "_CFLAGS = $(CFLAGSF) $(CFLAGS)"); - if((p = config_get(config, target, "cflags")) != NULL) - fprintf(fp, "%s%s", " ", p); - fputc('\n', fp); - fprintf(fp, "%s%s%s%s", target, ".a: $(", target, "_OBJS)\n"); - fprintf(fp, "%s%s%s%s%s", "\t$(AR) ", target, ".a $(", target, - "_OBJS)\n"); - fprintf(fp, "%s%s%s", "\t$(RANLIB) ", target, ".a\n"); - fprintf(fp, "%s%s%s%s", target, ".so: $(", target, "_OBJS)\n"); - fprintf(fp, "%s%s%s%s%s", "\t$(LD) -o ", target, ".so $(", target, - "_OBJS)\n"); - return 0; -} - -static int _objects_target(Prefs * prefs, Config * config, FILE * fp, - String * target); -static int _write_objects(Prefs * prefs, Config * config, FILE * fp) -{ - char * targets = config_get(config, "", "targets"); - char c; - int i; - int ret = 0; - - if(targets == NULL) - return 0; - for(i = 0;; i++) - { - if(targets[i] != ',' && targets[i] != '\0') - continue; - c = targets[i]; - targets[i] = '\0'; - ret += _objects_target(prefs, config, fp, targets); - if(c == '\0') - break; - targets[i] = c; - targets+=i+1; - i = 0; - } - return ret; -} - -static int _target_source(Prefs * prefs, FILE * fp, String * target, - String * source); -static int _objects_target(Prefs * prefs, Config * config, FILE * fp, - String * target) -{ - String * sources; - int i; - char c; - - if((sources = config_get(config, target, "sources")) == NULL) - return 0; - for(i = 0;; i++) - { - if(sources[i] != ',' && sources[i] != '\0') - continue; - c = sources[i]; - sources[i] = '\0'; - _target_source(prefs, fp, target, sources); - if(c == '\0') - break; - sources[i] = c; - sources+=i+1; - i = 0; - } - return 0; -} - -static int _target_source(Prefs * prefs, FILE * fp, String * target, - String * source) -{ - int ret = 0; - String * extension; - ObjectType ot; - int len; - - if((extension = _source_extension(source)) == NULL) - return 1; - len = string_length(source) - string_length(extension) - 1; - source[len] = '\0'; - ot = _object_type(extension); - switch(ot) - { - case OT_ASM_SOURCE: - case OT_C_SOURCE: - if(*prefs & PREFS_n) - break; - fprintf(fp, "%s%s%s%s%s%s%s", "\n", source, ".o: ", - source, ".", sObjectType[ot], "\n"); - fprintf(fp, "%s%s%s%s%s%s", "\t$(CC) $(", target, - "_CFLAGS) -c ", source, ".", - sObjectType[ot]); - if(string_find(source, "/")) - fprintf(fp, "%s%s%s", " -o ", source, ".o"); - fputc('\n', fp); - break; - case OT_UNKNOWN: - ret = 1; - break; - } - source[len] = '.'; - return ret; -} - -static int _clean_targets(Config * config, FILE * fp); -static int _write_clean(Prefs * prefs, Config * config, FILE * fp) -{ - if(*prefs & PREFS_n) - return 0; - fprintf(fp, "%s", "\nclean:\n"); - if(config_get(config, "", "subdirs") != NULL) - fprintf(fp, "%s", "\t@for i in $(SUBDIRS); do" - " (cd $$i && $(MAKE) clean) || exit; done\n"); - return _clean_targets(config, fp); -} - -static int _clean_targets(Config * config, FILE * fp) -{ - String * targets; - int i; - char c; - - if((targets = config_get(config, "", "targets")) == NULL) - return 0; - fprintf(fp, "%s", "\t$(RM)"); - for(i = 0;; i++) - { - if(targets[i] != ',' && targets[i] != '\0') - continue; - c = targets[i]; - targets[i] = '\0'; - fprintf(fp, "%s%s%s", " $(", targets, "_OBJS)"); - if(c == '\0') - break; - targets[i] = c; - targets+=i+1; - i = 0; - } - fputc('\n', fp); - return 0; -} - -static int _write_distclean(Prefs * prefs, Config * config, FILE * fp) -{ - String * subdirs; - - if(*prefs & PREFS_n) - return 0; - fprintf(fp, "%s", "\ndistclean:"); - if((subdirs = config_get(config, "", "subdirs")) == NULL) - fprintf(fp, "%s", " clean\n"); - else - { - fprintf(fp, "%s", "\n\t@for i in $(SUBDIRS); do (cd $$i" - " && $(MAKE) distclean) || exit; done\n"); - _clean_targets(config, fp); - } - if(config_get(config, "", "targets") != NULL) - fprintf(fp, "%s", "\t$(RM) $(TARGETS)\n"); - return 0; -} - -static int _dist_subdir(Config * config, FILE * fp, Config * subdir); -static int _write_dist(Prefs * prefs, Config * config, FILE * fp, - configArray * ca, int from, int to) -{ - String const * package; - String const * version; - Config * p; - int i; - - if(*prefs & PREFS_n) - return 0; - if((package = config_get(config, "", "package")) == NULL - || (version = config_get(config, "", "version")) - == NULL) - return 0; - fprintf(fp, "%s", "\ndist:\n" - "\t$(RM) $(PACKAGE)-$(VERSION)\n" - "\t$(LN) . $(PACKAGE)-$(VERSION)\n" - "\t@$(TAR) $(PACKAGE)-$(VERSION).tar.gz \\\n"); - for(i = to; i > from; i--) - { - array_get_copy(ca, i - 1, &p); - _dist_subdir(config, fp, p); - } - fprintf(fp, "%s", "\t$(RM) $(PACKAGE)-$(VERSION)\n"); - return 0; -} - -static int _dist_subdir_dist(FILE * fp, String * path, String * dist); -static int _dist_subdir(Config * config, FILE * fp, Config * subdir) -{ - String * path; - int len; - String * targets; - String * dist; - int i; - char c; - - path = config_get(config, "", "directory"); - len = string_length(path); - path = config_get(subdir, "", "directory"); - path = &path[len]; - if(path[0] == '/') - path++; - if((targets = config_get(subdir, "", "targets")) != NULL) - { - /* FIXME unique SOURCES */ - for(i = 0;; i++) - { - if(targets[i] != ',' && targets[i] != '\0') - continue; - c = targets[i]; - targets[i] = '\0'; - if((dist = config_get(subdir, targets, "sources")) - != NULL) - _dist_subdir_dist(fp, path, dist); - if(c == '\0') - break; - targets[i] = c; - targets+=i+1; - i = 0; - } - } - if((dist = config_get(subdir, "", "dist")) != NULL) - _dist_subdir_dist(fp, path, dist); - fprintf(fp, "%s%s%s%s", "\t\t$(PACKAGE)-$(VERSION)/", path, - path[0] == '\0' ? "" : "/", PROJECT_CONF " \\\n"); - fprintf(fp, "%s%s%s%s%s", "\t\t$(PACKAGE)-$(VERSION)/", path, - path[0] == '\0' ? "" : "/", MAKEFILE, - path[0] == '\0' ? "\n" : " \\\n"); - return 0; -} - -static int _dist_subdir_dist(FILE * fp, String * path, String * dist) -{ - int i; - char c; - - for(i = 0;; i++) - { - if(dist[i] != ',' && dist[i] != '\0') - continue; - c = dist[i]; - dist[i] = '\0'; - fprintf(fp, "%s%s%s%s%s", "\t\t$(PACKAGE)-$(VERSION)/", - path[0] == '\0' ? "" : path, - path[0] == '\0' ? "" : "/", dist, " \\\n"); - if(c == '\0') - break; - dist[i] = c; - dist+=i+1; - i = 0; - } - return 0; -} - -static int _install_target(Config * config, FILE * fp, String * target); -static int _write_install(Prefs * prefs, Config * config, FILE * fp) -{ - int ret = 0; - String * subdirs; - String * targets; - int i; - char c; - - if(*prefs & PREFS_n) - return 0; - fprintf(fp, "%s", "\ninstall: all\n"); - if((subdirs = config_get(config, "", "subdirs")) != NULL) - fprintf(fp, "%s", "\t@for i in $(SUBDIRS); do" - " (cd $$i && $(MAKE) install) || exit; done\n"); - if((targets = config_get(config, "", "targets")) != NULL) - for(i = 0; ret == 0; i++) - { - if(targets[i] != ',' && targets[i] != '\0') - continue; - c = targets[i]; - targets[i] = '\0'; - ret = _install_target(config, fp, targets); - if(c == '\0') - break; - targets[i] = c; - targets+=i+1; - i = 0; - } - return ret; -} - -static int _install_target(Config * config, FILE * fp, String * target) -{ - String * type; - static Config * flag = NULL; - static int done[TT_LAST]; - TargetType tt; - - if((type = config_get(config, target, "type")) == NULL) - return 1; - if(flag != config) - { - flag = config; - memset(done, 0, sizeof(done)); - } - switch((tt = _target_type(type))) - { - case TT_BINARY: - if(!done[tt]) - fprintf(fp, "%s", "\t$(MKDIR) $(DESTDIR)" - "$(BINDIR)\n"); - fprintf(fp, "%s%s%s%s%s", "\t$(INSTALL) -m 0755 ", - target, " $(DESTDIR)$(BINDIR)/", - target, "\n"); - break; - case TT_LIBRARY: - if(!done[tt]) - fprintf(fp, "%s", "\t$(MKDIR) $(DESTDIR)" - "$(LIBDIR)\n"); - fprintf(fp, "%s%s%s%s%s", "\t$(INSTALL) -m 0644 ", - target, ".a $(DESTDIR)$(LIBDIR)/", - target, ".a\n"); - fprintf(fp, "%s%s%s%s%s", "\t$(INSTALL) -m 0755 ", - target, ".so $(DESTDIR)$(LIBDIR)/", - target, ".so\n"); - break; - case TT_OBJECT: - case TT_UNKNOWN: - break; - } - done[tt] = 1; - return 0; -} - -static int _uninstall_target(Config * config, FILE * fp, String * target); -static int _write_uninstall(Prefs * prefs, Config * config, FILE * fp) -{ - int ret = 0; - String * subdirs; - String * targets; - int i; - char c; - - if(*prefs & PREFS_n) - return 0; - fprintf(fp, "%s", "\nuninstall:\n"); - if((subdirs = config_get(config, "", "subdirs")) != NULL) - fprintf(fp, "%s", "\t@for i in $(SUBDIRS); do (cd $$i &&" - " $(MAKE) uninstall) || exit; done\n"); - if((targets = config_get(config, "", "targets")) != NULL) - for(i = 0; ret == 0; i++) - { - if(targets[i] != ',' && targets[i] != '\0') - continue; - c = targets[i]; - targets[i] = '\0'; - ret = _uninstall_target(config, fp, targets); - if(c == '\0') - break; - targets[i] = c; - targets+=i+1; - i = 0; - } - return ret; -} - -static int _uninstall_target(Config * config, FILE * fp, String * target) -{ - String * type; - - if((type = config_get(config, target, "type")) == NULL) - return 1; - switch(_target_type(type)) - { - case TT_BINARY: - fprintf(fp, "%s%s%s", "\t$(RM) $(DESTDIR)$(BINDIR)/", target, "\n"); - break; - case TT_LIBRARY: - fprintf(fp, "%s%s%s", "\t$(RM) $(DESTDIR)$(LIBDIR)/", target, ".a\n"); - fprintf(fp, "%s%s%s", "\t$(RM) $(DESTDIR)$(LIBDIR)/", target, ".so\n"); - break; - case TT_OBJECT: - case TT_UNKNOWN: - break; - } - return 0; -} - /* usage */ static int _usage(void) diff --git a/src/configure.h b/src/configure.h new file mode 100644 index 0000000..6d2640e --- /dev/null +++ b/src/configure.h @@ -0,0 +1,80 @@ +/* configure.h */ + + + +#ifndef __CONFIGURE_H +# define __CONFIGURE_H + +# include + + +/* types */ +typedef enum _HostArch +{ + HA_I386, HA_I486, HA_I586, HA_I686, + HA_SPARC, + HA_UNKNOWN +} HostArch; +# define HA_LAST HA_UNKNOWN +extern const String * sHostArch[HA_LAST+1]; + +typedef enum _HostOS +{ + HO_GNU_LINUX, + HO_FREEBSD, HO_NETBSD, HO_OPENBSD, + HO_UNKNOWN +} HostOS; +# define HO_LAST HO_UNKNOWN +extern const String * sHostOS[HO_LAST+1]; + +typedef enum _HostKernel +{ + HK_LINUX20, HK_LINUX22, HK_LINUX24, HK_LINUX26, + HK_NETBSD, + HK_UNKNOWN +} HostKernel; +# define HK_LAST HK_UNKNOWN +extern const String * sHostKernel[HK_LAST+1]; + +typedef enum _TargetType +{ + TT_BINARY = 0, TT_LIBRARY, TT_OBJECT, TT_UNKNOWN +} TargetType; +# define TT_LAST TT_UNKNOWN +extern const String * sTargetType[TT_LAST]; + +typedef enum _ObjectType +{ + OT_C_SOURCE = 0, OT_ASM_SOURCE, OT_UNKNOWN +} ObjectType; +# define OT_LAST OT_UNKNOWN +extern const String * sObjectType[OT_LAST]; +String * _source_extension(String * source); + + +/* constants */ +# define PROJECT_CONF "project.conf" +# define MAKEFILE "Makefile" + + +/* configure */ +/* types */ +typedef int Prefs; +# define PREFS_n 0x1 +# define PREFS_v 0x2 +typedef struct _Configure +{ + Prefs prefs; + HostArch arch; + HostOS os; + HostKernel kernel; +} Configure; + + +/* functions */ +int configure_error(char const * message, int ret); + +int enum_string(int last, const String * strings[], String * str); +int enum_string_short(int last, const String * strings[], String * str); + +#endif /* !__CONFIGURE_H */ diff --git a/src/makefile.c b/src/makefile.c new file mode 100644 index 0000000..e7771c5 --- /dev/null +++ b/src/makefile.c @@ -0,0 +1,913 @@ +/* makefile.c */ + + + +#include +#include +#include +#include "configure.h" + +ARRAY(Config *, config); + + +/* functions */ +static int _makefile_write(Configure * configure, Config * config, FILE * fp, + configArray * ca, int from, int to); +int makefile(Configure * configure, Config * config, String * directory, + configArray * ca, int from, int to) +{ + String * makefile; + FILE * fp = NULL; + int ret = 0; + + makefile = string_new(directory); + string_append(&makefile, "/"); + string_append(&makefile, MAKEFILE); + if(!(configure->prefs & PREFS_n) && (fp = fopen(makefile, "w")) == NULL) + ret = configure_error(makefile, 1); + else + { + if(configure->prefs & PREFS_v) + printf("%s%s%s%s%s", "Creating ", MAKEFILE, " in ", + directory, "\n"); + ret += _makefile_write(configure, config, fp, ca, from, to); + if(fp != NULL) + fclose(fp); + } + string_delete(makefile); + return ret; +} + +static int _write_variables(Configure * configure, Config * config, FILE * fp); +static int _write_targets(Prefs * prefs, Config * config, FILE * fp); +static int _write_objects(Prefs * prefs, Config * config, FILE * fp); +static int _write_clean(Prefs * prefs, Config * config, FILE * fp); +static int _write_distclean(Prefs * prefs, Config * config, FILE * fp); +static int _write_dist(Prefs * prefs, Config * config, FILE * fp, + configArray * ca, int from, int to); +static int _write_install(Prefs * prefs, Config * config, FILE * fp); +static int _write_uninstall(Prefs * prefs, Config * config, FILE * fp); +static int _makefile_write(Configure * configure, Config * config, FILE * fp, + configArray * ca, int from, int to) +{ + if(_write_variables(configure, config, fp) != 0 + || _write_targets(&configure->prefs, config, fp) != 0 + || _write_objects(&configure->prefs, config, fp) != 0 + || _write_clean(&configure->prefs, config, fp) != 0 + || _write_distclean(&configure->prefs, config, fp) != 0 + || _write_dist(&configure->prefs, config, fp, ca, from, + to) != 0 + || _write_install(&configure->prefs, config, fp) != 0 + || _write_uninstall(&configure->prefs, config, fp) != 0) + return 1; + return 0; +} + +static int _variables_package(Prefs * prefs, Config * config, FILE * fp, + String const * directory); +static int _variables_print(Prefs * prefs, Config * config, FILE * fp, + char const * input, char const * output); +static int _variables_targets(Prefs * prefs, Config * config, FILE * fp); +static int _variables_executables(Configure * configure, Config * config, + FILE * fp); +static int _write_variables(Configure * configure, Config * config, FILE * fp) +{ + String const * directory = config_get(config, "", "directory"); + int ret = 0; + + ret += _variables_package(&configure->prefs, config, fp, directory); + ret += _variables_print(&configure->prefs, config, fp, "subdirs", + "SUBDIRS"); + ret += _variables_targets(&configure->prefs, config, fp); + ret += _variables_executables(configure, config, fp); + if(!(configure->prefs & PREFS_n)) + fputc('\n', fp); + return ret; +} + +static int _variables_package(Prefs * prefs, Config * config, FILE * fp, + String const * directory) +{ + String * package; + String * version; + + if((package = config_get(config, "", "package")) == NULL) + return 0; + if(*prefs & PREFS_v) + printf("%s%s", "Package: ", package); + if((version = config_get(config, "", "version")) == NULL) + { + if(*prefs & PREFS_v) + fputc('\n', stdout); + fprintf(stderr, "%s%s%s", "configure: ", directory, + ": \"package\" needs \"version\"\n"); + return 1; + } + if(*prefs & PREFS_v) + printf("%s%s%s", " ", version, "\n"); + if(fp != NULL) + fprintf(fp, "%s%s%s%s%s", "PACKAGE\t= ", package, + "\nVERSION\t= ", version, "\n"); + return 0; +} + +static int _variables_print(Prefs * prefs, Config * config, FILE * fp, + char const * input, char const * output) +{ + String * prints; + int i; + char c; + + if(*prefs & PREFS_n) + return 0; + if((prints = config_get(config, "", input)) == NULL) + return 0; + fprintf(fp, "%s%s", output, "\t="); + for(i = 0;; i++) + { + if(prints[i] != ',' && prints[i] != '\0') + continue; + c = prints[i]; + prints[i] = '\0'; + fprintf(fp, " %s", prints); + if(c == '\0') + break; + prints[i] = c; + prints+=i+1; + i = 0; + } + fputc('\n', fp); + return 0; +} + +static int _variables_targets(Prefs * prefs, Config * config, FILE * fp) +{ + String * prints; + int i; + char c; + String * type; + + if(*prefs & PREFS_n) + return 0; + if((prints = config_get(config, "", "targets")) == NULL) + return 0; + fprintf(fp, "%s%s", "TARGETS", "\t="); + for(i = 0;; i++) + { + if(prints[i] != ',' && prints[i] != '\0') + continue; + c = prints[i]; + prints[i] = '\0'; + if((type = config_get(config, prints, "type")) == NULL) + fprintf(fp, " %s", prints); + else + switch(enum_string(TT_LAST, sTargetType, type)) + { + case TT_BINARY: + case TT_OBJECT: + case TT_UNKNOWN: + fprintf(fp, " %s", prints); + break; + case TT_LIBRARY: + fprintf(fp, " %s%s%s%s", prints, ".a ", + prints, ".so"); + break; + } + if(c == '\0') + break; + prints[i] = c; + prints+=i+1; + i = 0; + } + fputc('\n', fp); + return 0; +} + +static int _executables_variables(Configure * configure, Config * config, + FILE * fp, String * target); +static int _variables_executables(Configure * configure, Config * config, + FILE * fp) +{ + String * targets; + int i; + char c; + + if(configure->prefs & PREFS_n) + return 0; + if((targets = config_get(config, "", "targets")) != NULL) + { + for(i = 0;; i++) + { + if(targets[i] != ',' && targets[i] != '\0') + continue; + c = targets[i]; + targets[i] = '\0'; + _executables_variables(configure, config, fp, targets); + if(c == '\0') + break; + targets[i] = c; + targets+=i+1; + i = 0; + } + fprintf(fp, "%s", "RM\t= rm -f\n"); + } + if(config_get(config, "", "package")) + fprintf(fp, "%s", "LN\t= ln -sf\nTAR\t= tar cfzv\n"); + if(targets != NULL) + { + fprintf(fp, "%s", "MKDIR\t= mkdir -p\n"); + fprintf(fp, "%s", "INSTALL\t= install\n"); + } + return 0; +} + +static void _variables_binary(Configure * configure, Config * config, FILE * fp, + char * done); +static void _variables_library(Configure * configure, Config * config, + FILE * fp, char * done); +static void _variables_object(void); +static int _executables_variables(Configure * configure, Config * config, + FILE * fp, String * target) +{ + static Config * flag = NULL; + String * type; + char done[TT_LAST]; /* FIXME even better if'd be variable by variable */ + TargetType tt; + + if(flag != config) + { + flag = config; + memset(done, 0, sizeof(done)); + } + if((type = config_get(config, target, "type")) == NULL) + return 0; + if(done[(tt = enum_string(TT_LAST, sTargetType, type))]) + return 0; + switch(tt) + { + case TT_BINARY: + _variables_binary(configure, config, fp, done); + break; + case TT_LIBRARY: + _variables_library(configure, config, fp, done); + break; + case TT_OBJECT: + _variables_object(); + break; + case TT_UNKNOWN: + break; + } + done[tt] = 1; + return 0; +} + +static void _variables_binary(Configure * configure, Config * config, FILE * fp, + char * done) +{ + String * p; + + /* FIXME path given from user or autodetected */ + if(!done[TT_LIBRARY]) + { + fprintf(fp, "%s", "PREFIX\t= /usr/local\n"); + fprintf(fp, "%s", "DESTDIR\t=\n"); + } + fprintf(fp, "%s", "BINDIR\t= $(PREFIX)/bin\n"); + if(!done[TT_LIBRARY]) + { + fprintf(fp, "%s", "CC\t= cc\n"); + if((p = config_get(config, "", "cflags_force")) + != NULL) + { + fprintf(fp, "%s%s", "CFLAGSF\t= ", p); + if(configure->os == HO_GNU_LINUX + && string_find(p, "-ansi")) + fprintf(fp, "%s", " -D_GNU_SOURCE"); + fputc('\n', fp); + } + if((p = config_get(config, "", "cflags")) + != NULL) + fprintf(fp, "%s%s%s", "CFLAGS\t= ", p, + "\n"); + } + if((p = config_get(config, "", "ldflags_force")) + != NULL) + fprintf(fp, "%s%s%s", "LDFLAGSF= ", p, "\n"); + if((p = config_get(config, "", "ldflags")) != NULL) + fprintf(fp, "%s%s%s", "LDFLAGS\t= ", p, "\n"); +} + +static void _variables_library(Configure * configure, Config * config, + FILE * fp, char * done) +{ + String * p; + + /* FIXME path given from user or autodetected */ + if(!done[TT_LIBRARY]) + { + fprintf(fp, "%s", "PREFIX\t= /usr/local\n"); + fprintf(fp, "%s", "DESTDIR\t=\n"); + } + fprintf(fp, "%s", "LIBDIR\t= $(PREFIX)/lib\n"); + if(!done[TT_BINARY]) + { + fprintf(fp, "%s", "CC\t= cc\n"); + if((p = config_get(config, "", "cflags_force")) + != NULL) + { + fprintf(fp, "%s%s", "CFLAGSF\t= ", p); + if(configure->os == HO_GNU_LINUX + && string_find(p, "-ansi")) + fprintf(fp, "%s", " -D_GNU_SOURCE"); + fputc('\n', fp); + } + if((p = config_get(config, "", "cflags")) + != NULL) + fprintf(fp, "%s%s%s", "CFLAGS\t= ", p, + "\n"); + } + fprintf(fp, "%s", "AR\t= ar rc\n"); + fprintf(fp, "%s", "RANLIB\t= ranlib\n"); + fprintf(fp, "%s", "LD\t= ld -shared\n"); +} + +static void _variables_object(void) +{ +} + +static int _targets_all(Prefs * prefs, Config * config, FILE * fp); +static int _targets_subdirs(Prefs * prefs, Config * config, FILE * fp); +static int _targets_target(Prefs * prefs, Config * config, FILE * fp, + String * target); +static int _write_targets(Prefs * prefs, Config * config, FILE * fp) +{ + char * targets = config_get(config, "", "targets"); + char c; + int i; + int ret = 0; + + if(_targets_all(prefs, config, fp) != 0 + || _targets_subdirs(prefs, config, fp) != 0) + return 1; + if(targets == NULL) + return 0; + for(i = 0;; i++) + { + if(targets[i] != ',' && targets[i] != '\0') + continue; + c = targets[i]; + targets[i] = '\0'; + ret += _targets_target(prefs, config, fp, targets); + if(c == '\0') + break; + targets[i] = c; + targets+=i+1; + i = 0; + } + return ret; +} + +static int _targets_all(Prefs * prefs, Config * config, FILE * fp) +{ + if(*prefs & PREFS_n) + return 0; + fprintf(fp, "%s", "\nall:"); + if(config_get(config, "", "subdirs") != NULL) + fprintf(fp, "%s", " subdirs"); + if(config_get(config, "", "targets") != NULL) + fprintf(fp, "%s", " $(TARGETS)"); + fprintf(fp, "%s", "\n"); + return 0; +} + +static int _targets_subdirs(Prefs * prefs, Config * config, FILE * fp) +{ + String * subdirs; + + if(*prefs & PREFS_n) + return 0; + if((subdirs = config_get(config, "", "subdirs")) != NULL) + fprintf(fp, "%s", "\nsubdirs:\n\t@for i in $(SUBDIRS); do" + " (cd $$i && $(MAKE)) || exit; done\n"); + return 0; +} + +static int _target_objs(Prefs * prefs, Config * config, FILE * fp, + String * target); +static int _target_library(Prefs * prefs, Config * config, FILE * fp, + String * target); +static int _targets_target(Prefs * prefs, Config * config, FILE * fp, + String * target) +{ + String * type; + TargetType tt; + String * p; + + if((type = config_get(config, target, "type")) == NULL) + { + fprintf(stderr, "%s%s%s", "configure: ", target, + ": no type defined for target\n"); + return 1; + } + tt = enum_string(TT_LAST, sTargetType, type); + switch(tt) + { + case TT_BINARY: + if(_target_objs(prefs, config, fp, target) != 0) + return 1; + if(*prefs & PREFS_n) + return 0; + fprintf(fp, "%s%s", target, "_CFLAGS = $(CFLAGSF)" + " $(CFLAGS)"); + if((p = config_get(config, target, "cflags")) != NULL) + fprintf(fp, "%s%s", " ", p); + fputc('\n', fp); + fprintf(fp, "%s%s%s%s", target, ": $(", target, + "_OBJS)\n"); + fprintf(fp, "%s%s%s%s%s", "\t$(CC) $(LDFLAGSF)" + " $(LDFLAGS) -o ", target, " $(", + target, "_OBJS)\n"); + break; + case TT_LIBRARY: + return _target_library(prefs, config, fp, target); + case TT_OBJECT: + if((p = config_get(config, target, "sources")) == NULL) + { + fprintf(stderr, "%s%s%s", "configure: ", target, + " no sources for target\n"); + return 1; + } + if(*prefs & PREFS_n) + return 0; + fprintf(fp, "%s%s%s%s", target, ": ", p, "\n"); + /* FIXME */ + break; + case TT_UNKNOWN: + fprintf(stderr, "%s%s%s", "configure: ", target, + ": unknown type for target\n"); + return 1; + } + return 0; +} + +static int _objs_source(Prefs * prefs, FILE * fp, String * source); +static int _target_objs(Prefs * prefs, Config * config, FILE * fp, + String * target) +{ + int ret = 0; + String * sources; + int i; + char c; + + if((sources = config_get(config, target, "sources")) == NULL) + { + fprintf(stderr, "%s%s%s", "configure: ", target, + ": no sources defined for target\n"); + return 1; + } + if(!(*prefs & PREFS_n)) + fprintf(fp, "%s%s%s", "\n", target, "_OBJS ="); + for(i = 0; ret == 0; i++) + { + if(sources[i] != ',' && sources[i] != '\0') + continue; + c = sources[i]; + sources[i] = '\0'; + ret = _objs_source(prefs, fp, sources); + if(c == '\0') + break; + sources[i] = c; + sources+=i+1; + i = 0; + } + if(!(*prefs & PREFS_n)) + fputc('\n', fp); + return ret; +} + +static int _objs_source(Prefs * prefs, FILE * fp, String * source) +{ + int ret = 0; + String * extension; + int len; + + if((extension = _source_extension(source)) == NULL) + { + fprintf(stderr, "%s%s%s", "configure: ", source, + ": no extension for source\n"); + return 1; + } + len = string_length(source) - string_length(extension) - 1; + source[len] = '\0'; + switch(enum_string(OT_LAST, sObjectType, extension)) + { + case OT_ASM_SOURCE: + case OT_C_SOURCE: + if(*prefs & PREFS_n) + break; + fprintf(fp, "%s%s%s", " ", source, ".o"); + break; + case OT_UNKNOWN: + ret = 1; + fprintf(stderr, "%s%s%s", "configure: ", source, + ": unknown extension for source\n"); + break; + } + source[len] = '.'; + return ret; +} + +static int _target_library(Prefs * prefs, Config * config, FILE * fp, + String * target) +{ + String * p; + + if(_target_objs(prefs, config, fp, target) != 0) + return 1; + if(*prefs & PREFS_n) + return 0; + fprintf(fp, "%s%s", target, "_CFLAGS = $(CFLAGSF) $(CFLAGS)"); + if((p = config_get(config, target, "cflags")) != NULL) + fprintf(fp, "%s%s", " ", p); + fputc('\n', fp); + fprintf(fp, "%s%s%s%s", target, ".a: $(", target, "_OBJS)\n"); + fprintf(fp, "%s%s%s%s%s", "\t$(AR) ", target, ".a $(", target, + "_OBJS)\n"); + fprintf(fp, "%s%s%s", "\t$(RANLIB) ", target, ".a\n"); + fprintf(fp, "%s%s%s%s", target, ".so: $(", target, "_OBJS)\n"); + fprintf(fp, "%s%s%s%s%s", "\t$(LD) -o ", target, ".so $(", target, + "_OBJS)\n"); + return 0; +} + +static int _objects_target(Prefs * prefs, Config * config, FILE * fp, + String * target); +static int _write_objects(Prefs * prefs, Config * config, FILE * fp) +{ + char * targets = config_get(config, "", "targets"); + char c; + int i; + int ret = 0; + + if(targets == NULL) + return 0; + for(i = 0;; i++) + { + if(targets[i] != ',' && targets[i] != '\0') + continue; + c = targets[i]; + targets[i] = '\0'; + ret += _objects_target(prefs, config, fp, targets); + if(c == '\0') + break; + targets[i] = c; + targets+=i+1; + i = 0; + } + return ret; +} + +static int _target_source(Prefs * prefs, FILE * fp, String * target, + String * source); +static int _objects_target(Prefs * prefs, Config * config, FILE * fp, + String * target) +{ + String * sources; + int i; + char c; + + if((sources = config_get(config, target, "sources")) == NULL) + return 0; + for(i = 0;; i++) + { + if(sources[i] != ',' && sources[i] != '\0') + continue; + c = sources[i]; + sources[i] = '\0'; + _target_source(prefs, fp, target, sources); + if(c == '\0') + break; + sources[i] = c; + sources+=i+1; + i = 0; + } + return 0; +} + +static int _target_source(Prefs * prefs, FILE * fp, String * target, + String * source) +{ + int ret = 0; + String * extension; + ObjectType ot; + int len; + + if((extension = _source_extension(source)) == NULL) + return 1; + len = string_length(source) - string_length(extension) - 1; + source[len] = '\0'; + switch((ot = enum_string(OT_LAST, sObjectType, extension))) + { + case OT_ASM_SOURCE: + case OT_C_SOURCE: + if(*prefs & PREFS_n) + break; + fprintf(fp, "%s%s%s%s%s%s%s", "\n", source, ".o: ", + source, ".", sObjectType[ot], "\n"); + fprintf(fp, "%s%s%s%s%s%s", "\t$(CC) $(", target, + "_CFLAGS) -c ", source, ".", + sObjectType[ot]); + if(string_find(source, "/")) + fprintf(fp, "%s%s%s", " -o ", source, ".o"); + fputc('\n', fp); + break; + case OT_UNKNOWN: + ret = 1; + break; + } + source[len] = '.'; + return ret; +} + +static int _clean_targets(Config * config, FILE * fp); +static int _write_clean(Prefs * prefs, Config * config, FILE * fp) +{ + if(*prefs & PREFS_n) + return 0; + fprintf(fp, "%s", "\nclean:\n"); + if(config_get(config, "", "subdirs") != NULL) + fprintf(fp, "%s", "\t@for i in $(SUBDIRS); do" + " (cd $$i && $(MAKE) clean) || exit; done\n"); + return _clean_targets(config, fp); +} + +static int _clean_targets(Config * config, FILE * fp) +{ + String * targets; + int i; + char c; + + if((targets = config_get(config, "", "targets")) == NULL) + return 0; + fprintf(fp, "%s", "\t$(RM)"); + for(i = 0;; i++) + { + if(targets[i] != ',' && targets[i] != '\0') + continue; + c = targets[i]; + targets[i] = '\0'; + fprintf(fp, "%s%s%s", " $(", targets, "_OBJS)"); + if(c == '\0') + break; + targets[i] = c; + targets+=i+1; + i = 0; + } + fputc('\n', fp); + return 0; +} + +static int _write_distclean(Prefs * prefs, Config * config, FILE * fp) +{ + String * subdirs; + + if(*prefs & PREFS_n) + return 0; + fprintf(fp, "%s", "\ndistclean:"); + if((subdirs = config_get(config, "", "subdirs")) == NULL) + fprintf(fp, "%s", " clean\n"); + else + { + fprintf(fp, "%s", "\n\t@for i in $(SUBDIRS); do (cd $$i" + " && $(MAKE) distclean) || exit; done\n"); + _clean_targets(config, fp); + } + if(config_get(config, "", "targets") != NULL) + fprintf(fp, "%s", "\t$(RM) $(TARGETS)\n"); + return 0; +} + +static int _dist_subdir(Config * config, FILE * fp, Config * subdir); +static int _write_dist(Prefs * prefs, Config * config, FILE * fp, + configArray * ca, int from, int to) +{ + String const * package; + String const * version; + Config * p; + int i; + + if(*prefs & PREFS_n) + return 0; + if((package = config_get(config, "", "package")) == NULL + || (version = config_get(config, "", "version")) + == NULL) + return 0; + fprintf(fp, "%s", "\ndist:\n" + "\t$(RM) $(PACKAGE)-$(VERSION)\n" + "\t$(LN) . $(PACKAGE)-$(VERSION)\n" + "\t@$(TAR) $(PACKAGE)-$(VERSION).tar.gz \\\n"); + for(i = to; i > from; i--) + { + array_get_copy(ca, i - 1, &p); + _dist_subdir(config, fp, p); + } + fprintf(fp, "%s", "\t$(RM) $(PACKAGE)-$(VERSION)\n"); + return 0; +} + +static int _dist_subdir_dist(FILE * fp, String * path, String * dist); +static int _dist_subdir(Config * config, FILE * fp, Config * subdir) +{ + String * path; + int len; + String * targets; + String * dist; + int i; + char c; + + path = config_get(config, "", "directory"); + len = string_length(path); + path = config_get(subdir, "", "directory"); + path = &path[len]; + if(path[0] == '/') + path++; + if((targets = config_get(subdir, "", "targets")) != NULL) + { + /* FIXME unique SOURCES */ + for(i = 0;; i++) + { + if(targets[i] != ',' && targets[i] != '\0') + continue; + c = targets[i]; + targets[i] = '\0'; + if((dist = config_get(subdir, targets, "sources")) + != NULL) + _dist_subdir_dist(fp, path, dist); + if(c == '\0') + break; + targets[i] = c; + targets+=i+1; + i = 0; + } + } + if((dist = config_get(subdir, "", "dist")) != NULL) + _dist_subdir_dist(fp, path, dist); + fprintf(fp, "%s%s%s%s", "\t\t$(PACKAGE)-$(VERSION)/", path, + path[0] == '\0' ? "" : "/", PROJECT_CONF " \\\n"); + fprintf(fp, "%s%s%s%s%s", "\t\t$(PACKAGE)-$(VERSION)/", path, + path[0] == '\0' ? "" : "/", MAKEFILE, + path[0] == '\0' ? "\n" : " \\\n"); + return 0; +} + +static int _dist_subdir_dist(FILE * fp, String * path, String * dist) +{ + int i; + char c; + + for(i = 0;; i++) + { + if(dist[i] != ',' && dist[i] != '\0') + continue; + c = dist[i]; + dist[i] = '\0'; + fprintf(fp, "%s%s%s%s%s", "\t\t$(PACKAGE)-$(VERSION)/", + path[0] == '\0' ? "" : path, + path[0] == '\0' ? "" : "/", dist, " \\\n"); + if(c == '\0') + break; + dist[i] = c; + dist+=i+1; + i = 0; + } + return 0; +} + +static int _install_target(Config * config, FILE * fp, String * target); +static int _write_install(Prefs * prefs, Config * config, FILE * fp) +{ + int ret = 0; + String * subdirs; + String * targets; + int i; + char c; + + if(*prefs & PREFS_n) + return 0; + fprintf(fp, "%s", "\ninstall: all\n"); + if((subdirs = config_get(config, "", "subdirs")) != NULL) + fprintf(fp, "%s", "\t@for i in $(SUBDIRS); do" + " (cd $$i && $(MAKE) install) || exit; done\n"); + if((targets = config_get(config, "", "targets")) != NULL) + for(i = 0; ret == 0; i++) + { + if(targets[i] != ',' && targets[i] != '\0') + continue; + c = targets[i]; + targets[i] = '\0'; + ret = _install_target(config, fp, targets); + if(c == '\0') + break; + targets[i] = c; + targets+=i+1; + i = 0; + } + return ret; +} + +static int _install_target(Config * config, FILE * fp, String * target) +{ + String * type; + static Config * flag = NULL; + static int done[TT_LAST]; + TargetType tt; + + if((type = config_get(config, target, "type")) == NULL) + return 1; + if(flag != config) + { + flag = config; + memset(done, 0, sizeof(done)); + } + switch((tt = enum_string(TT_LAST, sTargetType, type))) + { + case TT_BINARY: + if(!done[tt]) + fprintf(fp, "%s", "\t$(MKDIR) $(DESTDIR)" + "$(BINDIR)\n"); + fprintf(fp, "%s%s%s%s%s", "\t$(INSTALL) -m 0755 ", + target, " $(DESTDIR)$(BINDIR)/", + target, "\n"); + break; + case TT_LIBRARY: + if(!done[tt]) + fprintf(fp, "%s", "\t$(MKDIR) $(DESTDIR)" + "$(LIBDIR)\n"); + fprintf(fp, "%s%s%s%s%s", "\t$(INSTALL) -m 0644 ", + target, ".a $(DESTDIR)$(LIBDIR)/", + target, ".a\n"); + fprintf(fp, "%s%s%s%s%s", "\t$(INSTALL) -m 0755 ", + target, ".so $(DESTDIR)$(LIBDIR)/", + target, ".so\n"); + break; + case TT_OBJECT: + case TT_UNKNOWN: + break; + } + done[tt] = 1; + return 0; +} + +static int _uninstall_target(Config * config, FILE * fp, String * target); +static int _write_uninstall(Prefs * prefs, Config * config, FILE * fp) +{ + int ret = 0; + String * subdirs; + String * targets; + int i; + char c; + + if(*prefs & PREFS_n) + return 0; + fprintf(fp, "%s", "\nuninstall:\n"); + if((subdirs = config_get(config, "", "subdirs")) != NULL) + fprintf(fp, "%s", "\t@for i in $(SUBDIRS); do (cd $$i &&" + " $(MAKE) uninstall) || exit; done\n"); + if((targets = config_get(config, "", "targets")) != NULL) + for(i = 0; ret == 0; i++) + { + if(targets[i] != ',' && targets[i] != '\0') + continue; + c = targets[i]; + targets[i] = '\0'; + ret = _uninstall_target(config, fp, targets); + if(c == '\0') + break; + targets[i] = c; + targets+=i+1; + i = 0; + } + return ret; +} + +static int _uninstall_target(Config * config, FILE * fp, String * target) +{ + String * type; + + if((type = config_get(config, target, "type")) == NULL) + return 1; + switch(enum_string(TT_LAST, sTargetType, type)) + { + case TT_BINARY: + fprintf(fp, "%s%s%s", "\t$(RM) $(DESTDIR)$(BINDIR)/", target, "\n"); + break; + case TT_LIBRARY: + fprintf(fp, "%s%s%s", "\t$(RM) $(DESTDIR)$(LIBDIR)/", target, ".a\n"); + fprintf(fp, "%s%s%s", "\t$(RM) $(DESTDIR)$(LIBDIR)/", target, ".so\n"); + break; + case TT_OBJECT: + case TT_UNKNOWN: + break; + } + return 0; +} diff --git a/src/makefile.h b/src/makefile.h new file mode 100644 index 0000000..aadf71a --- /dev/null +++ b/src/makefile.h @@ -0,0 +1,21 @@ +/* makefile.h */ + + + +#ifndef __MAKEFILE_H +# define __MAKEFILE_H + +# include +# include "configure.h" + +/* FIXME should be: +ARRAY(Config *, config); +but it can't be included multiple times */ +typedef Array configArray; +extern configArray * configarray_new(void); + +/* functions */ +int makefile(Configure * configure, Config * config, String * directory, + configArray * ca, int from, int to); + +#endif diff --git a/src/project.conf b/src/project.conf index 10500fa..90f6f13 100644 --- a/src/project.conf +++ b/src/project.conf @@ -5,4 +5,4 @@ ldflags_force=-L /System/Libraries -l System -l dl [configure] type=binary -sources=configure.c +sources=configure.c,makefile.c