From: John Hodge Date: Fri, 11 Oct 2013 03:50:34 +0000 (+0800) Subject: UDI/Tools - Renamed udibuild's src dir to say udibuild X-Git-Tag: rel0.15~115 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=8fe56f1234442dfa971e069bb8c139918430d511;p=tpg%2Facess2.git UDI/Tools - Renamed udibuild's src dir to say udibuild --- diff --git a/UDI/Tools/src/Makefile b/UDI/Tools/src/Makefile deleted file mode 100644 index 970dc5c9..00000000 --- a/UDI/Tools/src/Makefile +++ /dev/null @@ -1,25 +0,0 @@ - -OBJS = main.o inifile.o build.o udiprops.o -BIN = ../udibuild -CFLAGS = -std=c99 -MMD -MP -g - -OBJS := $(OBJS:%=obj/%) - -.PHONY: all clean - -all: $(BIN) - -clean: - $(RM) $(BIN) $(OBJS) $(OBJS:%.o=%.d) - -$(BIN): $(OBJS) - @echo --- [CC] $@ - @$(CC) -o $(BIN) $(OBJS) $(LDFLAGS) - -obj/%.o: %.c Makefile - @mkdir -p $(dir $@) - @echo --- [CC] $@ - @$(CC) -o $@ -c $< $(CFLAGS) - --include $(OBJS:%.o=%.d) - diff --git a/UDI/Tools/src/build.c b/UDI/Tools/src/build.c deleted file mode 100644 index 4d0b2947..00000000 --- a/UDI/Tools/src/build.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * udibuild - UDI Compilation Utility - * - By John Hodge (thePowersGang) - * - * build.c - * - Compilation functions - */ -#include -#include -#include -#include // mkdir -#include // unlink -#include "include/build.h" -#include "include/common.h" - -// === PROTOTYPES === -char *get_objfile(tIniFile *opts, const char *abi, const char *srcfile); -char *get_udipropsfile(tIniFile *opts, const char *abi); - -// === CODE === -int Build_CompileFile(tIniFile *opts, const char *abi, tUdiprops *udiprops, tUdiprops_Srcfile *srcfile) -{ - // Select compiler from opts [abi] - const char *cc_prog = IniFile_Get(opts, abi, "CC", NULL); - if( !cc_prog ) { - fprintf(stderr, "No 'CC' defined for ABI %s\n", abi); - return -1; - } - - // Build up compiler's command line - // - Include CFLAGS from .ini file - // - defines from udiprops - // - Object file is srcfile with .o appended - // > Place in 'obj/' dir? - char *objfile = get_objfile(opts, abi, srcfile->Filename); - char *cmd = mkstr("%s -DUDI_ABI_is_%s %s %s -c %s -o %s", - cc_prog, - abi, - IniFile_Get(opts, abi, "CFLAGS", ""), - srcfile->CompileOpts ? srcfile->CompileOpts : "", - srcfile->Filename, objfile); - printf("--- Compiling: %s\n", srcfile->Filename); - int rv = system(cmd); - free(cmd); - free(objfile); - - return rv; -} - -int Build_CreateUdiprops(tIniFile *opts, const char *abi, tUdiprops *udiprops) -{ - const char *cc_prog = IniFile_Get(opts, abi, "CC", NULL); - - char *filename = get_udipropsfile(opts, abi); - FILE *fp = fopen(filename, "w"); - fprintf(fp, "char udiprops[] __attribute__((section(\".udiprops\"))) = \n"); - for( int i = 0; i < udiprops->nLines; i ++ ) { - // TODO: Escape " in string - fprintf(fp, " \"%s\"\n", udiprops->Lines[i]); - } - fprintf(fp, " ;\n"); - fclose(fp); - - char *cmd = mkstr("%s %s -c %s -o %s.o", - cc_prog, IniFile_Get(opts, abi, "CFLAGS", ""), - filename, filename); - - int rv = system(cmd); - free(cmd); - unlink(filename); - free(filename); - - return rv; -} - -int Build_LinkObjects(tIniFile *opts, const char *abi, tUdiprops *udiprops) -{ - const char *linker = IniFile_Get(opts, abi, "LD", NULL); - if( !linker ) { - fprintf(stderr, "No 'LD' defined for ABI %s\n", abi); - return -1; - } - - char *objfiles[udiprops->nSourceFiles]; - size_t objfiles_len = 0; - for( int i = 0; i < udiprops->nSourceFiles; i ++ ) { - objfiles[i] = get_objfile(opts, abi, udiprops->SourceFiles[i]->Filename); - objfiles_len += strlen(objfiles[i])+1; - } - - // Create command string - char *objfiles_str = malloc(objfiles_len); - objfiles_len = 0; - for( int i = 0; i < udiprops->nSourceFiles; i ++ ) { - strcpy(objfiles_str + objfiles_len, objfiles[i]); - objfiles_len += strlen(objfiles[i])+1; - objfiles_str[objfiles_len-1] = ' '; - free( objfiles[i] ); - } - objfiles_str[objfiles_len-1] = '\0'; - - mkdir("bin", 0755); - char *abidir = mkstr("bin/%s", abi); - mkdir(abidir, 0755); - free(abidir); - - char *udiprops_c = get_udipropsfile(opts, abi); - char *cmd = mkstr("%s -r %s -o bin/%s/%s -s %s",// %s.o", - linker, IniFile_Get(opts, abi, "LDFLAGS", ""), - abi, udiprops->ModuleName, objfiles_str, udiprops_c - ); - printf("--- Linking: bin/%s/%s\n", abi, udiprops->ModuleName); - printf("%s\n", cmd); - int rv = system(cmd); - free(cmd); - free(udiprops_c); - free(objfiles_str); - - return rv; -} - -char *get_objfile(tIniFile *opts, const char *abi, const char *srcfile) -{ - return mkstr("%s.o", srcfile); -} - -char *get_udipropsfile(tIniFile *opts, const char *abi) -{ - return mkstr(".udiprops.c"); -} - diff --git a/UDI/Tools/src/include/build.h b/UDI/Tools/src/include/build.h deleted file mode 100644 index fe377ddf..00000000 --- a/UDI/Tools/src/include/build.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * udibuild - UDI Compilation Utility - * - By John Hodge (thePowersGang) - * - * build.h - * - Actual build steps (exposed functions) - */ -#ifndef _BUILD_H_ -#define _BUILD_H_ - -#include "inifile.h" -#include "udiprops.h" - -extern int Build_CompileFile(tIniFile *opts, const char *abi, tUdiprops *udiprops, tUdiprops_Srcfile *srcfile); -extern int Build_CreateUdiprops(tIniFile *opts, const char *abi, tUdiprops *udiprops); -extern int Build_LinkObjects(tIniFile *opts, const char *abi, tUdiprops *udiprops); - -#endif - diff --git a/UDI/Tools/src/include/common.h b/UDI/Tools/src/include/common.h deleted file mode 100644 index 0cb419b6..00000000 --- a/UDI/Tools/src/include/common.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * udibuild - UDI Compilation Utility - * - By John Hodge (thePowersGang) - * - * common.h - * - Common helpers - */ -#ifndef _COMMON_H_ -#define _COMMON_H_ - -#include - -#ifndef __GNUC__ -# define __attribute__(...) -#endif - -extern char *mkstr(const char *fmt, ...) __attribute__((format(printf,1,2))); - -#endif - diff --git a/UDI/Tools/src/include/inifile.h b/UDI/Tools/src/include/inifile.h deleted file mode 100644 index dce416fc..00000000 --- a/UDI/Tools/src/include/inifile.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * udibuild - UDI Compilation Utility - * - By John Hodge (thePowersGang) - * - * inifile.h - * - .ini file parsing - */ -#ifndef _INIFILE_H_ -#define _INIFILE_H_ - -typedef struct sInifile tIniFile; - -extern tIniFile *IniFile_Load(const char *Path); -extern const char *IniFile_Get(tIniFile *File, const char *Sect, const char *Key, const char *Default); -extern void IniFile_Free(tIniFile *File); - -#endif - diff --git a/UDI/Tools/src/include/udiprops.h b/UDI/Tools/src/include/udiprops.h deleted file mode 100644 index 4bbc5d4e..00000000 --- a/UDI/Tools/src/include/udiprops.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * udibuild - UDI Compilation Utility - * - By John Hodge (thePowersGang) - * - * udiprops.h - * - udiprops.txt parsing for udibuild - */ -#ifndef _UDIPROPS_H_ -#define _UDIPROPS_H_ - -typedef struct sUdiprops tUdiprops; - -typedef struct sUdiprops_Srcfile tUdiprops_Srcfile; - -struct sUdiprops_Srcfile -{ - const char *Filename; - const char *CompileOpts; -}; - -struct sUdiprops -{ - const char *ModuleName; - int nSourceFiles; - tUdiprops_Srcfile **SourceFiles; - - int nLines; - char **Lines; -}; - -extern tUdiprops *Udiprops_LoadBuild(const char *Filename); - -#endif - diff --git a/UDI/Tools/src/inifile.c b/UDI/Tools/src/inifile.c deleted file mode 100644 index d52a845d..00000000 --- a/UDI/Tools/src/inifile.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * udibuild - UDI Compilation Utility - * - By John Hodge (thePowersGang) - * - * inifile.c - * - .ini file parsing - */ -#include -#include -#include -#include -#include -#include "include/inifile.h" - -typedef struct sInifile_Section tIniFile_Section; -typedef struct sInifile_Value tIniFile_Value; - -struct sInifile_Value -{ - tIniFile_Value *Next; - const char *Key; - const char *Value; -}; - -struct sInifile_Section -{ - tIniFile_Section *Next; - const char *Name; - tIniFile_Value *FirstValue; -}; - -struct sInifile -{ - tIniFile_Section RootSection; -}; - -// === CODE === -static void rtrim(char *str) -{ - char *pos = str; - while( *pos ) - pos ++; - while( pos != str && isspace(pos[-1]) ) - *--pos = '\0'; -} - -tIniFile *IniFile_Load(const char *Path) -{ - FILE *fp = fopen(Path, "r"); - if( !fp ) - return NULL; - - tIniFile *ret = malloc( sizeof(tIniFile) ); - assert(ret); - - ret->RootSection.Name = ""; - ret->RootSection.FirstValue = NULL; - - tIniFile_Section *curSect = &ret->RootSection; - char buf[512]; - while( fgets(buf, sizeof(buf)-1, fp) ) - { - if( strchr(buf, '#') ) - *strchr(buf, '#') = '\0'; - rtrim(buf); - char name[64]; - size_t ofs = 0; - if( sscanf(buf, "[%[^]]]", name) == 1 ) { - //printf("section %s\n", name); - // new section - tIniFile_Section *new_sect = malloc(sizeof(tIniFile_Section)+strlen(name)+1); - new_sect->Next = NULL; - new_sect->Name = (const char*)(new_sect+1); - new_sect->FirstValue = NULL; - strcpy( (char*)new_sect->Name, name ); - curSect->Next = new_sect; - curSect = new_sect; - } - else if( sscanf(buf, "%[^=]=%n", name, &ofs) >= 1 ) { - //printf("key %s equals %s\n", name, value); - const char *value = buf + ofs; - tIniFile_Value *val = malloc(sizeof(tIniFile_Value)+strlen(name)+1+strlen(value)+1); - val->Next = curSect->FirstValue; - curSect->FirstValue = val; - - val->Key = (char*)(val+1); - strcpy((char*)val->Key, name); - val->Value = val->Key + strlen(val->Key) + 1; - strcpy((char*)val->Value, value); - } - else { - //printf("ignore %s\n", buf); - // ignore - } - } - - fclose(fp); - - return ret; -} - -const char *IniFile_Get(tIniFile *File, const char *Sect, const char *Key, const char *Default) -{ - tIniFile_Section *sect; - for( sect = &File->RootSection; sect; sect = sect->Next ) - { - if( strcmp(sect->Name, Sect) == 0 ) - break; - } - if( !sect ) - return Default; - - tIniFile_Value *val; - for( val = sect->FirstValue; val; val = val->Next ) - { - if( strcmp(val->Key, Key) == 0 ) - break; - } - if( !val ) - return Default; - - return val->Value; -} - -void IniFile_Free(tIniFile *File) -{ - // TODO: -} diff --git a/UDI/Tools/src/main.c b/UDI/Tools/src/main.c deleted file mode 100644 index b5b0042e..00000000 --- a/UDI/Tools/src/main.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * udibuild - UDI Compilation Utility - * - By John Hodge (thePowersGang) - * - * main.c - * - Core - */ -#include -#include -#include // getopt -#include -#include // strrchr -#include -#include "include/common.h" -#include "include/build.h" -#include "include/inifile.h" -#include "include/udiprops.h" - -#define CONFIG_FILENAME "udibuild.ini" -#ifdef __ACESS__ -#define RUNTIME_DIR "/Acess/Conf/UDI" -#else -#define RUNTIME_DIR "/etc/udi" -#endif - -// === PROTOTYPES === - int main(int argc, char *argv[]); - int ParseArguments(int argc, char *argv[]); -void Usage(const char *progname); - -// === GLOBALS === -const char *gsRuntimeDir = RUNTIME_DIR; -const char *gsOpt_ConfigFile; -const char *gsOpt_WorkingDir; -const char *gsOpt_UdipropsFile; -const char *gsOpt_ABIName = "ia32"; -tIniFile *gpOptions; -tUdiprops *gpUdipropsBuild; - -// === CODE === -int main(int argc, char *argv[]) -{ - if( ParseArguments(argc, argv) ) { - return 1; - } - - // Locate udibuild.ini - // 1. Check CWD - if( !gsOpt_ConfigFile ) { - //if( file_exists("./udibuild.ini") ) - //{ - // gsOpt_ConfigFile = "udibuild.ini"; - //} - } - // 2. Check program dir (if not invoked from PATH) - if( !gsOpt_ConfigFile && (argv[0][0] == '.' || argv[0][0] == '/') ) { - char *last_slash = strrchr(argv[0], '/'); - if( last_slash ) { - gsOpt_ConfigFile = mkstr("%.*s/%s", - last_slash-argv[0], argv[0], CONFIG_FILENAME); - } - //if( !file_exists(gsOpt_ConfigFile) ) { - // free(gsOpt_ConfigFile); - // gsOpt_ConfigFile = NULL; - //} - } - // 3. Check ~/.config/udi/udibuild.ini - // 4. Check RUNTIME_DIR/udibuild.ini - - // #. Oh well - if( !gsOpt_ConfigFile ) { - fprintf(stderr, "Can't locate "CONFIG_FILENAME" file, please specify using '-c'\n"); - exit(2); - } - - // Load udibuild.ini - gpOptions = IniFile_Load(gsOpt_ConfigFile); - assert(gpOptions); - - // Change to working directory (-C ) - if( gsOpt_WorkingDir ) - { - chdir(gsOpt_WorkingDir); - } - - // Load udiprops - gpUdipropsBuild = Udiprops_LoadBuild( gsOpt_UdipropsFile ? gsOpt_UdipropsFile : "udiprops.txt" ); - assert(gpUdipropsBuild); - assert(gpUdipropsBuild->SourceFiles); - - // Do build - for( int i = 0; i < gpUdipropsBuild->nSourceFiles; i ++ ) - { - int rv = Build_CompileFile(gpOptions, gsOpt_ABIName, gpUdipropsBuild, - gpUdipropsBuild->SourceFiles[i]); - if( rv ) { - fprintf(stderr, "*** Exit status: %i\n", rv); - return rv; - } - } - // Create file with `.udiprops` section - // - udimkpkg's job - //Build_CreateUdiprops(gpOptions, gsOpt_ABIName, gpUdipropsBuild); - // Link - Build_LinkObjects(gpOptions, gsOpt_ABIName, gpUdipropsBuild); - - return 0; -} - -int ParseArguments(int argc, char *argv[]) -{ - int opt; - while( (opt = getopt(argc, argv, "hC:c:f:a:")) != -1 ) - { - switch(opt) - { - case 'h': - Usage(argv[0]); - exit(0); - case 'C': - gsOpt_WorkingDir = optarg; - break; - case 'c': - gsOpt_ConfigFile = optarg; - break; - case 'f': - gsOpt_UdipropsFile = optarg; - break; - case 'a': - gsOpt_ABIName = optarg; - break; - case '?': - Usage(argv[0]); - return 1; - default: - fprintf(stderr, "BUG: Unhandled optarg %i '%c'\n", opt, opt); - break; - } - } - return 0; -} - -void Usage(const char *progname) -{ - fprintf(stderr, "Usage: %s [-C workingdir] [-c udibuild.ini] [-f udiprops.txt] [-a abiname]\n", - progname); - fprintf(stderr, "\n" - "-C workingdir : Change to the specified directory before looking for udiprops.txt\n" - "-c udibuild.ini : Override the default udibuild config file\n" - "-f udiprops.txt : Override the default udiprops file\n" - "-a abiname : Select a different ABI\n" - "\n"); -} - -char *mkstr(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - size_t len = vsnprintf(NULL, 0, fmt, args); - va_end(args); - va_start(args, fmt); - char *ret = malloc(len+1); - vsnprintf(ret, len+1, fmt, args); - va_end(args); - return ret; -} - diff --git a/UDI/Tools/src/udiprops.c b/UDI/Tools/src/udiprops.c deleted file mode 100644 index f6a9bfca..00000000 --- a/UDI/Tools/src/udiprops.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * udibuild - UDI Compilation Utility - * - By John Hodge (thePowersGang) - * - * udiprops.c - * - udiprops.txt parsing (for udibuild only) - */ -#include -#include -#include -#include -#include -#include -#include "include/udiprops.h" - -// === CODE === -static int _get_token_sym(const char *str, const char **outstr, ...) -{ - va_list args; - va_start(args, outstr); - const char *sym; - for( int idx = 0; (sym = va_arg(args, const char *)); idx ++ ) - { - size_t len = strlen(sym); - if( memcmp(str, sym, len) != 0 ) - continue ; - if( str[len] && !isspace(str[len]) ) - continue ; - - // Found it! - *outstr = str + len; - while( isspace(**outstr) ) - (*outstr) ++; - return idx; - } - va_end(args); - - const char *end = str; - while( !isspace(*end) ) - end ++; -// fprintf(stderr, "udiprops: Unknown token '%.*s'\n", end-str, str); - - *outstr = NULL; - return -1; -} - -static void rtrim(char *str) -{ - char *pos = str; - while( *pos ) - pos ++; - while( pos != str && isspace(pos[-1]) ) - *--pos = '\0'; -} - -static char *my_strdup(const char *str) -{ - char *ret = malloc(strlen(str)+1); - return strcpy(ret, str); -} - -tUdiprops *Udiprops_LoadBuild(const char *Filename) -{ - FILE *fp = fopen(Filename, "r"); - if( !fp ) { - perror("Udiprops_LoadBuild"); - return NULL; - } - - char *current_compile_opts = NULL; - int n_srcfiles = 0; - tUdiprops *ret = calloc( 1, sizeof(tUdiprops) ); - - char buf[512]; - while( fgets(buf, sizeof(buf)-1, fp) ) - { - char *str = buf; - { - char *hash = strchr(str, '#'); - if( hash ) *hash = '\0'; - } - rtrim(str); - if( !str[0] ) continue ; - - ret->nLines ++; - ret->Lines = realloc(ret->Lines, ret->nLines*sizeof(void*)); - ret->Lines[ret->nLines-1] = my_strdup(str); - - int sym = _get_token_sym(str, (const char**)&str, - "source_files", "compile_options", "source_requires", - "module", - NULL); - switch(sym) - { - case 0: // source_files - for(char *file = strtok(str, " \t"); file; file = strtok(NULL, " \t") ) - { - tUdiprops_Srcfile *srcfile = malloc(sizeof(tUdiprops_Srcfile)+strlen(file)+1); - srcfile->CompileOpts = current_compile_opts; - srcfile->Filename = (void*)(srcfile+1); - strcpy((char*)srcfile->Filename, file); - - n_srcfiles ++; - ret->SourceFiles = realloc(ret->SourceFiles, n_srcfiles*sizeof(void*)); - ret->SourceFiles[n_srcfiles-1] = srcfile; - } - break; - case 1: // compile_options - current_compile_opts = my_strdup(str); - break; - case 2: // source_requires - // TODO: Use source_requires - break; - case 3: // module - ret->ModuleName = my_strdup(str); - break; - } - } - - ret->nSourceFiles = n_srcfiles; - - // "Intentional" memory leak - // - current_compile_opts not freed, and shared between srcfiles - // - If two compile_options statements appear in a row, one is definitely leaked - - fclose(fp); - return ret; -} - diff --git a/UDI/Tools/udibuild_src/Makefile b/UDI/Tools/udibuild_src/Makefile new file mode 100644 index 00000000..970dc5c9 --- /dev/null +++ b/UDI/Tools/udibuild_src/Makefile @@ -0,0 +1,25 @@ + +OBJS = main.o inifile.o build.o udiprops.o +BIN = ../udibuild +CFLAGS = -std=c99 -MMD -MP -g + +OBJS := $(OBJS:%=obj/%) + +.PHONY: all clean + +all: $(BIN) + +clean: + $(RM) $(BIN) $(OBJS) $(OBJS:%.o=%.d) + +$(BIN): $(OBJS) + @echo --- [CC] $@ + @$(CC) -o $(BIN) $(OBJS) $(LDFLAGS) + +obj/%.o: %.c Makefile + @mkdir -p $(dir $@) + @echo --- [CC] $@ + @$(CC) -o $@ -c $< $(CFLAGS) + +-include $(OBJS:%.o=%.d) + diff --git a/UDI/Tools/udibuild_src/build.c b/UDI/Tools/udibuild_src/build.c new file mode 100644 index 00000000..4d0b2947 --- /dev/null +++ b/UDI/Tools/udibuild_src/build.c @@ -0,0 +1,131 @@ +/* + * udibuild - UDI Compilation Utility + * - By John Hodge (thePowersGang) + * + * build.c + * - Compilation functions + */ +#include +#include +#include +#include // mkdir +#include // unlink +#include "include/build.h" +#include "include/common.h" + +// === PROTOTYPES === +char *get_objfile(tIniFile *opts, const char *abi, const char *srcfile); +char *get_udipropsfile(tIniFile *opts, const char *abi); + +// === CODE === +int Build_CompileFile(tIniFile *opts, const char *abi, tUdiprops *udiprops, tUdiprops_Srcfile *srcfile) +{ + // Select compiler from opts [abi] + const char *cc_prog = IniFile_Get(opts, abi, "CC", NULL); + if( !cc_prog ) { + fprintf(stderr, "No 'CC' defined for ABI %s\n", abi); + return -1; + } + + // Build up compiler's command line + // - Include CFLAGS from .ini file + // - defines from udiprops + // - Object file is srcfile with .o appended + // > Place in 'obj/' dir? + char *objfile = get_objfile(opts, abi, srcfile->Filename); + char *cmd = mkstr("%s -DUDI_ABI_is_%s %s %s -c %s -o %s", + cc_prog, + abi, + IniFile_Get(opts, abi, "CFLAGS", ""), + srcfile->CompileOpts ? srcfile->CompileOpts : "", + srcfile->Filename, objfile); + printf("--- Compiling: %s\n", srcfile->Filename); + int rv = system(cmd); + free(cmd); + free(objfile); + + return rv; +} + +int Build_CreateUdiprops(tIniFile *opts, const char *abi, tUdiprops *udiprops) +{ + const char *cc_prog = IniFile_Get(opts, abi, "CC", NULL); + + char *filename = get_udipropsfile(opts, abi); + FILE *fp = fopen(filename, "w"); + fprintf(fp, "char udiprops[] __attribute__((section(\".udiprops\"))) = \n"); + for( int i = 0; i < udiprops->nLines; i ++ ) { + // TODO: Escape " in string + fprintf(fp, " \"%s\"\n", udiprops->Lines[i]); + } + fprintf(fp, " ;\n"); + fclose(fp); + + char *cmd = mkstr("%s %s -c %s -o %s.o", + cc_prog, IniFile_Get(opts, abi, "CFLAGS", ""), + filename, filename); + + int rv = system(cmd); + free(cmd); + unlink(filename); + free(filename); + + return rv; +} + +int Build_LinkObjects(tIniFile *opts, const char *abi, tUdiprops *udiprops) +{ + const char *linker = IniFile_Get(opts, abi, "LD", NULL); + if( !linker ) { + fprintf(stderr, "No 'LD' defined for ABI %s\n", abi); + return -1; + } + + char *objfiles[udiprops->nSourceFiles]; + size_t objfiles_len = 0; + for( int i = 0; i < udiprops->nSourceFiles; i ++ ) { + objfiles[i] = get_objfile(opts, abi, udiprops->SourceFiles[i]->Filename); + objfiles_len += strlen(objfiles[i])+1; + } + + // Create command string + char *objfiles_str = malloc(objfiles_len); + objfiles_len = 0; + for( int i = 0; i < udiprops->nSourceFiles; i ++ ) { + strcpy(objfiles_str + objfiles_len, objfiles[i]); + objfiles_len += strlen(objfiles[i])+1; + objfiles_str[objfiles_len-1] = ' '; + free( objfiles[i] ); + } + objfiles_str[objfiles_len-1] = '\0'; + + mkdir("bin", 0755); + char *abidir = mkstr("bin/%s", abi); + mkdir(abidir, 0755); + free(abidir); + + char *udiprops_c = get_udipropsfile(opts, abi); + char *cmd = mkstr("%s -r %s -o bin/%s/%s -s %s",// %s.o", + linker, IniFile_Get(opts, abi, "LDFLAGS", ""), + abi, udiprops->ModuleName, objfiles_str, udiprops_c + ); + printf("--- Linking: bin/%s/%s\n", abi, udiprops->ModuleName); + printf("%s\n", cmd); + int rv = system(cmd); + free(cmd); + free(udiprops_c); + free(objfiles_str); + + return rv; +} + +char *get_objfile(tIniFile *opts, const char *abi, const char *srcfile) +{ + return mkstr("%s.o", srcfile); +} + +char *get_udipropsfile(tIniFile *opts, const char *abi) +{ + return mkstr(".udiprops.c"); +} + diff --git a/UDI/Tools/udibuild_src/include/build.h b/UDI/Tools/udibuild_src/include/build.h new file mode 100644 index 00000000..fe377ddf --- /dev/null +++ b/UDI/Tools/udibuild_src/include/build.h @@ -0,0 +1,19 @@ +/* + * udibuild - UDI Compilation Utility + * - By John Hodge (thePowersGang) + * + * build.h + * - Actual build steps (exposed functions) + */ +#ifndef _BUILD_H_ +#define _BUILD_H_ + +#include "inifile.h" +#include "udiprops.h" + +extern int Build_CompileFile(tIniFile *opts, const char *abi, tUdiprops *udiprops, tUdiprops_Srcfile *srcfile); +extern int Build_CreateUdiprops(tIniFile *opts, const char *abi, tUdiprops *udiprops); +extern int Build_LinkObjects(tIniFile *opts, const char *abi, tUdiprops *udiprops); + +#endif + diff --git a/UDI/Tools/udibuild_src/include/common.h b/UDI/Tools/udibuild_src/include/common.h new file mode 100644 index 00000000..0cb419b6 --- /dev/null +++ b/UDI/Tools/udibuild_src/include/common.h @@ -0,0 +1,20 @@ +/* + * udibuild - UDI Compilation Utility + * - By John Hodge (thePowersGang) + * + * common.h + * - Common helpers + */ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include + +#ifndef __GNUC__ +# define __attribute__(...) +#endif + +extern char *mkstr(const char *fmt, ...) __attribute__((format(printf,1,2))); + +#endif + diff --git a/UDI/Tools/udibuild_src/include/inifile.h b/UDI/Tools/udibuild_src/include/inifile.h new file mode 100644 index 00000000..dce416fc --- /dev/null +++ b/UDI/Tools/udibuild_src/include/inifile.h @@ -0,0 +1,18 @@ +/* + * udibuild - UDI Compilation Utility + * - By John Hodge (thePowersGang) + * + * inifile.h + * - .ini file parsing + */ +#ifndef _INIFILE_H_ +#define _INIFILE_H_ + +typedef struct sInifile tIniFile; + +extern tIniFile *IniFile_Load(const char *Path); +extern const char *IniFile_Get(tIniFile *File, const char *Sect, const char *Key, const char *Default); +extern void IniFile_Free(tIniFile *File); + +#endif + diff --git a/UDI/Tools/udibuild_src/include/udiprops.h b/UDI/Tools/udibuild_src/include/udiprops.h new file mode 100644 index 00000000..4bbc5d4e --- /dev/null +++ b/UDI/Tools/udibuild_src/include/udiprops.h @@ -0,0 +1,34 @@ +/* + * udibuild - UDI Compilation Utility + * - By John Hodge (thePowersGang) + * + * udiprops.h + * - udiprops.txt parsing for udibuild + */ +#ifndef _UDIPROPS_H_ +#define _UDIPROPS_H_ + +typedef struct sUdiprops tUdiprops; + +typedef struct sUdiprops_Srcfile tUdiprops_Srcfile; + +struct sUdiprops_Srcfile +{ + const char *Filename; + const char *CompileOpts; +}; + +struct sUdiprops +{ + const char *ModuleName; + int nSourceFiles; + tUdiprops_Srcfile **SourceFiles; + + int nLines; + char **Lines; +}; + +extern tUdiprops *Udiprops_LoadBuild(const char *Filename); + +#endif + diff --git a/UDI/Tools/udibuild_src/inifile.c b/UDI/Tools/udibuild_src/inifile.c new file mode 100644 index 00000000..d52a845d --- /dev/null +++ b/UDI/Tools/udibuild_src/inifile.c @@ -0,0 +1,128 @@ +/* + * udibuild - UDI Compilation Utility + * - By John Hodge (thePowersGang) + * + * inifile.c + * - .ini file parsing + */ +#include +#include +#include +#include +#include +#include "include/inifile.h" + +typedef struct sInifile_Section tIniFile_Section; +typedef struct sInifile_Value tIniFile_Value; + +struct sInifile_Value +{ + tIniFile_Value *Next; + const char *Key; + const char *Value; +}; + +struct sInifile_Section +{ + tIniFile_Section *Next; + const char *Name; + tIniFile_Value *FirstValue; +}; + +struct sInifile +{ + tIniFile_Section RootSection; +}; + +// === CODE === +static void rtrim(char *str) +{ + char *pos = str; + while( *pos ) + pos ++; + while( pos != str && isspace(pos[-1]) ) + *--pos = '\0'; +} + +tIniFile *IniFile_Load(const char *Path) +{ + FILE *fp = fopen(Path, "r"); + if( !fp ) + return NULL; + + tIniFile *ret = malloc( sizeof(tIniFile) ); + assert(ret); + + ret->RootSection.Name = ""; + ret->RootSection.FirstValue = NULL; + + tIniFile_Section *curSect = &ret->RootSection; + char buf[512]; + while( fgets(buf, sizeof(buf)-1, fp) ) + { + if( strchr(buf, '#') ) + *strchr(buf, '#') = '\0'; + rtrim(buf); + char name[64]; + size_t ofs = 0; + if( sscanf(buf, "[%[^]]]", name) == 1 ) { + //printf("section %s\n", name); + // new section + tIniFile_Section *new_sect = malloc(sizeof(tIniFile_Section)+strlen(name)+1); + new_sect->Next = NULL; + new_sect->Name = (const char*)(new_sect+1); + new_sect->FirstValue = NULL; + strcpy( (char*)new_sect->Name, name ); + curSect->Next = new_sect; + curSect = new_sect; + } + else if( sscanf(buf, "%[^=]=%n", name, &ofs) >= 1 ) { + //printf("key %s equals %s\n", name, value); + const char *value = buf + ofs; + tIniFile_Value *val = malloc(sizeof(tIniFile_Value)+strlen(name)+1+strlen(value)+1); + val->Next = curSect->FirstValue; + curSect->FirstValue = val; + + val->Key = (char*)(val+1); + strcpy((char*)val->Key, name); + val->Value = val->Key + strlen(val->Key) + 1; + strcpy((char*)val->Value, value); + } + else { + //printf("ignore %s\n", buf); + // ignore + } + } + + fclose(fp); + + return ret; +} + +const char *IniFile_Get(tIniFile *File, const char *Sect, const char *Key, const char *Default) +{ + tIniFile_Section *sect; + for( sect = &File->RootSection; sect; sect = sect->Next ) + { + if( strcmp(sect->Name, Sect) == 0 ) + break; + } + if( !sect ) + return Default; + + tIniFile_Value *val; + for( val = sect->FirstValue; val; val = val->Next ) + { + if( strcmp(val->Key, Key) == 0 ) + break; + } + if( !val ) + return Default; + + return val->Value; +} + +void IniFile_Free(tIniFile *File) +{ + // TODO: +} diff --git a/UDI/Tools/udibuild_src/main.c b/UDI/Tools/udibuild_src/main.c new file mode 100644 index 00000000..b5b0042e --- /dev/null +++ b/UDI/Tools/udibuild_src/main.c @@ -0,0 +1,167 @@ +/* + * udibuild - UDI Compilation Utility + * - By John Hodge (thePowersGang) + * + * main.c + * - Core + */ +#include +#include +#include // getopt +#include +#include // strrchr +#include +#include "include/common.h" +#include "include/build.h" +#include "include/inifile.h" +#include "include/udiprops.h" + +#define CONFIG_FILENAME "udibuild.ini" +#ifdef __ACESS__ +#define RUNTIME_DIR "/Acess/Conf/UDI" +#else +#define RUNTIME_DIR "/etc/udi" +#endif + +// === PROTOTYPES === + int main(int argc, char *argv[]); + int ParseArguments(int argc, char *argv[]); +void Usage(const char *progname); + +// === GLOBALS === +const char *gsRuntimeDir = RUNTIME_DIR; +const char *gsOpt_ConfigFile; +const char *gsOpt_WorkingDir; +const char *gsOpt_UdipropsFile; +const char *gsOpt_ABIName = "ia32"; +tIniFile *gpOptions; +tUdiprops *gpUdipropsBuild; + +// === CODE === +int main(int argc, char *argv[]) +{ + if( ParseArguments(argc, argv) ) { + return 1; + } + + // Locate udibuild.ini + // 1. Check CWD + if( !gsOpt_ConfigFile ) { + //if( file_exists("./udibuild.ini") ) + //{ + // gsOpt_ConfigFile = "udibuild.ini"; + //} + } + // 2. Check program dir (if not invoked from PATH) + if( !gsOpt_ConfigFile && (argv[0][0] == '.' || argv[0][0] == '/') ) { + char *last_slash = strrchr(argv[0], '/'); + if( last_slash ) { + gsOpt_ConfigFile = mkstr("%.*s/%s", + last_slash-argv[0], argv[0], CONFIG_FILENAME); + } + //if( !file_exists(gsOpt_ConfigFile) ) { + // free(gsOpt_ConfigFile); + // gsOpt_ConfigFile = NULL; + //} + } + // 3. Check ~/.config/udi/udibuild.ini + // 4. Check RUNTIME_DIR/udibuild.ini + + // #. Oh well + if( !gsOpt_ConfigFile ) { + fprintf(stderr, "Can't locate "CONFIG_FILENAME" file, please specify using '-c'\n"); + exit(2); + } + + // Load udibuild.ini + gpOptions = IniFile_Load(gsOpt_ConfigFile); + assert(gpOptions); + + // Change to working directory (-C ) + if( gsOpt_WorkingDir ) + { + chdir(gsOpt_WorkingDir); + } + + // Load udiprops + gpUdipropsBuild = Udiprops_LoadBuild( gsOpt_UdipropsFile ? gsOpt_UdipropsFile : "udiprops.txt" ); + assert(gpUdipropsBuild); + assert(gpUdipropsBuild->SourceFiles); + + // Do build + for( int i = 0; i < gpUdipropsBuild->nSourceFiles; i ++ ) + { + int rv = Build_CompileFile(gpOptions, gsOpt_ABIName, gpUdipropsBuild, + gpUdipropsBuild->SourceFiles[i]); + if( rv ) { + fprintf(stderr, "*** Exit status: %i\n", rv); + return rv; + } + } + // Create file with `.udiprops` section + // - udimkpkg's job + //Build_CreateUdiprops(gpOptions, gsOpt_ABIName, gpUdipropsBuild); + // Link + Build_LinkObjects(gpOptions, gsOpt_ABIName, gpUdipropsBuild); + + return 0; +} + +int ParseArguments(int argc, char *argv[]) +{ + int opt; + while( (opt = getopt(argc, argv, "hC:c:f:a:")) != -1 ) + { + switch(opt) + { + case 'h': + Usage(argv[0]); + exit(0); + case 'C': + gsOpt_WorkingDir = optarg; + break; + case 'c': + gsOpt_ConfigFile = optarg; + break; + case 'f': + gsOpt_UdipropsFile = optarg; + break; + case 'a': + gsOpt_ABIName = optarg; + break; + case '?': + Usage(argv[0]); + return 1; + default: + fprintf(stderr, "BUG: Unhandled optarg %i '%c'\n", opt, opt); + break; + } + } + return 0; +} + +void Usage(const char *progname) +{ + fprintf(stderr, "Usage: %s [-C workingdir] [-c udibuild.ini] [-f udiprops.txt] [-a abiname]\n", + progname); + fprintf(stderr, "\n" + "-C workingdir : Change to the specified directory before looking for udiprops.txt\n" + "-c udibuild.ini : Override the default udibuild config file\n" + "-f udiprops.txt : Override the default udiprops file\n" + "-a abiname : Select a different ABI\n" + "\n"); +} + +char *mkstr(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + size_t len = vsnprintf(NULL, 0, fmt, args); + va_end(args); + va_start(args, fmt); + char *ret = malloc(len+1); + vsnprintf(ret, len+1, fmt, args); + va_end(args); + return ret; +} + diff --git a/UDI/Tools/udibuild_src/udiprops.c b/UDI/Tools/udibuild_src/udiprops.c new file mode 100644 index 00000000..f6a9bfca --- /dev/null +++ b/UDI/Tools/udibuild_src/udiprops.c @@ -0,0 +1,129 @@ +/* + * udibuild - UDI Compilation Utility + * - By John Hodge (thePowersGang) + * + * udiprops.c + * - udiprops.txt parsing (for udibuild only) + */ +#include +#include +#include +#include +#include +#include +#include "include/udiprops.h" + +// === CODE === +static int _get_token_sym(const char *str, const char **outstr, ...) +{ + va_list args; + va_start(args, outstr); + const char *sym; + for( int idx = 0; (sym = va_arg(args, const char *)); idx ++ ) + { + size_t len = strlen(sym); + if( memcmp(str, sym, len) != 0 ) + continue ; + if( str[len] && !isspace(str[len]) ) + continue ; + + // Found it! + *outstr = str + len; + while( isspace(**outstr) ) + (*outstr) ++; + return idx; + } + va_end(args); + + const char *end = str; + while( !isspace(*end) ) + end ++; +// fprintf(stderr, "udiprops: Unknown token '%.*s'\n", end-str, str); + + *outstr = NULL; + return -1; +} + +static void rtrim(char *str) +{ + char *pos = str; + while( *pos ) + pos ++; + while( pos != str && isspace(pos[-1]) ) + *--pos = '\0'; +} + +static char *my_strdup(const char *str) +{ + char *ret = malloc(strlen(str)+1); + return strcpy(ret, str); +} + +tUdiprops *Udiprops_LoadBuild(const char *Filename) +{ + FILE *fp = fopen(Filename, "r"); + if( !fp ) { + perror("Udiprops_LoadBuild"); + return NULL; + } + + char *current_compile_opts = NULL; + int n_srcfiles = 0; + tUdiprops *ret = calloc( 1, sizeof(tUdiprops) ); + + char buf[512]; + while( fgets(buf, sizeof(buf)-1, fp) ) + { + char *str = buf; + { + char *hash = strchr(str, '#'); + if( hash ) *hash = '\0'; + } + rtrim(str); + if( !str[0] ) continue ; + + ret->nLines ++; + ret->Lines = realloc(ret->Lines, ret->nLines*sizeof(void*)); + ret->Lines[ret->nLines-1] = my_strdup(str); + + int sym = _get_token_sym(str, (const char**)&str, + "source_files", "compile_options", "source_requires", + "module", + NULL); + switch(sym) + { + case 0: // source_files + for(char *file = strtok(str, " \t"); file; file = strtok(NULL, " \t") ) + { + tUdiprops_Srcfile *srcfile = malloc(sizeof(tUdiprops_Srcfile)+strlen(file)+1); + srcfile->CompileOpts = current_compile_opts; + srcfile->Filename = (void*)(srcfile+1); + strcpy((char*)srcfile->Filename, file); + + n_srcfiles ++; + ret->SourceFiles = realloc(ret->SourceFiles, n_srcfiles*sizeof(void*)); + ret->SourceFiles[n_srcfiles-1] = srcfile; + } + break; + case 1: // compile_options + current_compile_opts = my_strdup(str); + break; + case 2: // source_requires + // TODO: Use source_requires + break; + case 3: // module + ret->ModuleName = my_strdup(str); + break; + } + } + + ret->nSourceFiles = n_srcfiles; + + // "Intentional" memory leak + // - current_compile_opts not freed, and shared between srcfiles + // - If two compile_options statements appear in a row, one is definitely leaked + + fclose(fp); + return ret; +} +