diff options
27 files changed, 809 insertions, 9 deletions
diff --git a/.gitignore b/.gitignore index 8a76394ee..4bb5041e7 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,9 @@ cscope.out /test/mrubytest.* CMakeFiles CMakeCache.txt +/mrbgems/generator +/mrbgems/init_gems.c +/mrbgems/g/Makefile +/mrbgems/g/mrblib_gem.c +/mrbgems/g/mrblib_gem.ctmp +/mrbgems/g/mrblib_gem.rbtmp @@ -44,6 +44,7 @@ export CAT := cat all : @$(MAKE) -C src $(MAKE_FLAGS) @$(MAKE) -C mrblib $(MAKE_FLAGS) + @$(MAKE) -C mrbgems $(MAKE_FLAGS) @$(MAKE) -C tools/mruby $(MAKE_FLAGS) @$(MAKE) -C tools/mirb $(MAKE_FLAGS) @@ -56,6 +57,7 @@ test : all .PHONY : clean clean : @$(MAKE) clean -C src $(MAKE_FLAGS) + @$(MAKE) clean -C mrbgems $(MAKE_FLAGS) @$(MAKE) clean -C tools/mruby $(MAKE_FLAGS) @$(MAKE) clean -C tools/mirb $(MAKE_FLAGS) @$(MAKE) clean -C test $(MAKE_FLAGS) diff --git a/doc/mrbgems/README.md b/doc/mrbgems/README.md new file mode 100644 index 000000000..7eef38222 --- /dev/null +++ b/doc/mrbgems/README.md @@ -0,0 +1,123 @@ +# mrbgems + +mrbgems is a library manager to integrate C and Ruby extension in an easy and +standardised way into mruby. + +## GEM Structure + +The maximal Gem structure looks like this: + +``` ++- GEM_NAME <- Name of Gem + | + +- mrblib/ <- Source for Ruby extension + | + +- src/ <- Source for C extension + | + +- test/ <- Test code (Ruby) + | + +- Makefile <- Makefile for Gem + | + +- README.md <- Readme for Gem +``` + +The folder *mrblib* contains pure Ruby files to extend mruby. The folder *src* +contains C files to extend mruby. The folder *test* contains pure Ruby files +for testing purposes which will be used by mrbtest. The *Makefile* contains +rules to build all C files and integrates them into the normal mruby +build process. *README.md* is a short description of your Gem. + +All Gems have to be located under *$(MRUBY_ROOT)/mrbgems/g/*. + +## C Extension + +mruby can be extended with C. It is possible by using the C API to integrate C +libraries into mruby. You need to use the folder *src* for all C files. Pay +attention that your *Makefile* has to build the source and also add the object +files to libmruby.a + +### Pre-Conditions + +mrbgems will automatically call the *gem-all* make target of your Gem. Make +sure that you build all files in this target and that you add your object +files to libmruby.a + +mrbgems expects that you have implemented a C method called +*mrb_YOURGEMNAME_gem_init(mrb_state)*. YOURGEMNAME will be replaced +by the name of you Gem. The directory name of your Gem is considered also +as the name! If you call your Gem directory *c_extension_example*, your +initialisation method could look like this: + +``` +void +mrb_c_extension_example_gem_init(mrb_state* mrb) { + _class_cextension = mrb_define_module(mrb, "CExtension"); + mrb_define_class_method(mrb, _class_cextension, "c_method", mrb_c_method, ARGS_NONE()); +} +``` + +mrbgems will also use the *gem-clean* make target to clean up your Gem. Implement +this target with the necessary rules! + +### Example + +``` ++- c_extension_example/ + | + +- src/ + | | + | +- example.c <- C extension source + | + +- test/ + | | + | +- example.rb <- Test code for C extension + | + +- Makefile <- Build rules for C extension + | + +- README.md +``` + +## Ruby Extension + +mruby can be extended with pure Ruby. It is possible to override existing +classes or add new ones in this way. Put all Ruby files into the *mrblib* +folder. At the moment only one directory layer is supported. So don't +use a deeper structure for now! + +The *Makefile* is not used for building a Ruby extension. But you still +should maintain this file so that during the build process the progress +can be visualized. If you want to do additional things during the build +process of your Ruby extension you can use the *Makefile* too. + +### Example + +``` ++- ruby_extension_example/ + | + +- mrblib/ + | | + | +- example.rb <- Ruby extension source + | + +- test/ + | | + | +- example.rb <- Test code for Ruby extension + | + +- Makefile + | + +- README.md +``` + +## Current Limitations + +The following limitations are currently existing: + +* Gem _MUST NOT_ have a *src* folder in case it doesn't have a + C extension +* Gem _MUST NOT_ have a *mrblib* folder in case it doesn't have a + Ruby extension +* Only Ruby files in the root directory of *mrblib* will be integrated +* C files in the directory of *src* are overriding object files with + the same name. + +If you have ideas how to fix these issues without implementing to much +complexity into the code please provide your code or idea. diff --git a/doc/mrbgems/c_and_ruby_extension_example/Makefile b/doc/mrbgems/c_and_ruby_extension_example/Makefile new file mode 100644 index 000000000..1744d73c3 --- /dev/null +++ b/doc/mrbgems/c_and_ruby_extension_example/Makefile @@ -0,0 +1,12 @@ +include ../../Makefile4gem + +GEM := c_and_ruby_extension_example + +GEM_C_FILES := $(wildcard $(SRC_DIR)/*.c) +GEM_OBJECTS := $(patsubst %.c, %.o, $(GEM_C_FILES)) + +GEM_RB_FILES := $(wildcard $(MRB_DIR)/*.rb) + +gem-all : $(GEM_OBJECTS) gem-c-and-rb-files + +gem-clean : gem-clean-c-and-rb-files diff --git a/doc/mrbgems/c_and_ruby_extension_example/README.md b/doc/mrbgems/c_and_ruby_extension_example/README.md new file mode 100644 index 000000000..0b428b0b6 --- /dev/null +++ b/doc/mrbgems/c_and_ruby_extension_example/README.md @@ -0,0 +1,4 @@ +C and Ruby Extension Example +========= + +This is an example gem which implements a C and Ruby extension. diff --git a/doc/mrbgems/c_and_ruby_extension_example/mrblib/example.rb b/doc/mrbgems/c_and_ruby_extension_example/mrblib/example.rb new file mode 100644 index 000000000..0c2d3c7d1 --- /dev/null +++ b/doc/mrbgems/c_and_ruby_extension_example/mrblib/example.rb @@ -0,0 +1,5 @@ +class RubyExtension + def CRubyExtension.ruby_method + puts "A Ruby Extension" + end +end diff --git a/doc/mrbgems/c_and_ruby_extension_example/src/example.c b/doc/mrbgems/c_and_ruby_extension_example/src/example.c new file mode 100644 index 000000000..178514ffe --- /dev/null +++ b/doc/mrbgems/c_and_ruby_extension_example/src/example.c @@ -0,0 +1,17 @@ +#include <mruby.h> +#include <stdio.h> + +static struct RClass *_class_cextension; + +static mrb_value +mrb_c_method(mrb_state *mrb, mrb_value self) +{ + puts("A C Extension"); + return self; +} + +void +mrb_c_and_ruby_extension_example_gem_init(mrb_state* mrb) { + _class_cextension = mrb_define_module(mrb, "CRubyExtension"); + mrb_define_class_method(mrb, _class_cextension, "c_method", mrb_c_method, ARGS_NONE()); +} diff --git a/doc/mrbgems/c_and_ruby_extension_example/test/example.rb b/doc/mrbgems/c_and_ruby_extension_example/test/example.rb new file mode 100644 index 000000000..fffad710f --- /dev/null +++ b/doc/mrbgems/c_and_ruby_extension_example/test/example.rb @@ -0,0 +1,7 @@ +assert('C and Ruby Extension Example 1') do + CRubyExtension.respond_to? :c_method +end + +assert('C and Ruby Extension Example 2') do + CRubyExtension.respond_to? :ruby_method +end diff --git a/doc/mrbgems/c_extension_example/Makefile b/doc/mrbgems/c_extension_example/Makefile new file mode 100644 index 000000000..615557aca --- /dev/null +++ b/doc/mrbgems/c_extension_example/Makefile @@ -0,0 +1,10 @@ +include ../../Makefile4gem + +GEM := c_extension_example + +GEM_C_FILES := $(wildcard $(SRC_DIR)/*.c) +GEM_OBJECTS := $(patsubst %.c, %.o, $(GEM_C_FILES)) + +gem-all : $(GEM_OBJECTS) gem-c-files + +gem-clean : gem-clean-c-files diff --git a/doc/mrbgems/c_extension_example/README.md b/doc/mrbgems/c_extension_example/README.md new file mode 100644 index 000000000..3803c2065 --- /dev/null +++ b/doc/mrbgems/c_extension_example/README.md @@ -0,0 +1,4 @@ +C Extension Example +========= + +This is an example gem which implements a C extension. diff --git a/doc/mrbgems/c_extension_example/src/example.c b/doc/mrbgems/c_extension_example/src/example.c new file mode 100644 index 000000000..9f0b07839 --- /dev/null +++ b/doc/mrbgems/c_extension_example/src/example.c @@ -0,0 +1,17 @@ +#include <mruby.h> +#include <stdio.h> + +static struct RClass *_class_cextension; + +static mrb_value +mrb_c_method(mrb_state *mrb, mrb_value self) +{ + puts("A C Extension"); + return self; +} + +void +mrb_c_extension_example_gem_init(mrb_state* mrb) { + _class_cextension = mrb_define_module(mrb, "CExtension"); + mrb_define_class_method(mrb, _class_cextension, "c_method", mrb_c_method, ARGS_NONE()); +} diff --git a/doc/mrbgems/c_extension_example/test/example.rb b/doc/mrbgems/c_extension_example/test/example.rb new file mode 100644 index 000000000..367d18029 --- /dev/null +++ b/doc/mrbgems/c_extension_example/test/example.rb @@ -0,0 +1,3 @@ +assert('C Extension Example') do + CExtension.respond_to? :c_method +end diff --git a/doc/mrbgems/ruby_extension_example/Makefile b/doc/mrbgems/ruby_extension_example/Makefile new file mode 100644 index 000000000..33eee97e9 --- /dev/null +++ b/doc/mrbgems/ruby_extension_example/Makefile @@ -0,0 +1,9 @@ +include ../../Makefile4gem + +GEM := ruby_extension_example + +GEM_RB_FILES := $(wildcard $(MRB_DIR)/*.rb) + +gem-all : gem-rb-files + +gem-clean : gem-clean-rb-files diff --git a/doc/mrbgems/ruby_extension_example/README.md b/doc/mrbgems/ruby_extension_example/README.md new file mode 100644 index 000000000..906a0d8f2 --- /dev/null +++ b/doc/mrbgems/ruby_extension_example/README.md @@ -0,0 +1,4 @@ +Pure Ruby Extension Example +========= + +This is an example gem which implements a pure Ruby extension. diff --git a/doc/mrbgems/ruby_extension_example/mrblib/example.rb b/doc/mrbgems/ruby_extension_example/mrblib/example.rb new file mode 100644 index 000000000..b07a2b580 --- /dev/null +++ b/doc/mrbgems/ruby_extension_example/mrblib/example.rb @@ -0,0 +1,5 @@ +class RubyExtension + def RubyExtension.ruby_method + puts "A Ruby Extension" + end +end diff --git a/doc/mrbgems/ruby_extension_example/test/example.rb b/doc/mrbgems/ruby_extension_example/test/example.rb new file mode 100644 index 000000000..0c1b63469 --- /dev/null +++ b/doc/mrbgems/ruby_extension_example/test/example.rb @@ -0,0 +1,3 @@ +assert('Ruby Extension Example') do + RubyExtension.respond_to? :ruby_method +end diff --git a/mrbgems/GEMS.active b/mrbgems/GEMS.active new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/mrbgems/GEMS.active diff --git a/mrbgems/Makefile b/mrbgems/Makefile new file mode 100644 index 000000000..462540c09 --- /dev/null +++ b/mrbgems/Makefile @@ -0,0 +1,67 @@ +# makefile description. +# add gems to the ruby library + +LIBR := ../lib/libmruby.a +INIT := init_gems +RM_F := rm -f +CC_FLAGS := -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include + +export CC = gcc +export LL = gcc +export AR = ar + +GENERATOR := ./generator +ifeq ($(OS),Windows_NT) + GENERATOR_BIN := $(GENERATOR).exe +else + GENERATOR_BIN := $(GENERATOR) +endif +GEM_MAKEFILE := g/Makefile +GEM_MAKEFILE_LIST := g/MakefileGemList +GEMDLIB := g/mrbgemtest.ctmp + +############################## +# generic build targets, rules + +.PHONY : all +all : all_gems gem_init.a + +gem_init.a : $(INIT).o + $(AR) rs gem_init.a $(INIT).o + +all_gems : $(GENERATOR_BIN) + @echo "Generate Gem List Makefile" + $(GENERATOR_BIN) makefile_list > $(GEM_MAKEFILE_LIST) + @echo "Generate Gem Makefile" + $(GENERATOR_BIN) makefile > $(GEM_MAKEFILE) + @echo "Build all gems" + $(MAKE) -C g + +$(INIT).c : $(GENERATOR_BIN) + @echo "Generate Gem driver" + $(GENERATOR_BIN) $(INIT) > $@ + +$(INIT).o : $(INIT).c + @echo "Build the driver which initializes all gems" + $(CC) $(CC_FLAGS) -MMD -c $< -o $@ + +# Generator + +$(GENERATOR_BIN) : $(GENERATOR).o + @echo "Build the generator which creates the driver and Gem Makefile" + $(LL) -o $@ $(CC_FLAGS) $< + +$(GENERATOR).o : $(GENERATOR).c + $(CC) $(CC_FLAGS) -MMD -c $< -o $@ + +.PHONY : prepare-test +prepare-test : + @$(MAKE) prepare-test -C g + +# clean driver and all gems +.PHONY : clean +clean : $(GENERATOR_BIN) + @echo "Cleanup Gems" + $(GENERATOR_BIN) makefile > $(GEM_MAKEFILE) + $(MAKE) clean -C g + -$(RM_F) $(INIT).c *.o *.d $(GENERATOR_BIN) $(GEM_MAKEFILE) $(GEM_MAKEFILE_LIST) gem_init.a diff --git a/mrbgems/Makefile4gem b/mrbgems/Makefile4gem new file mode 100644 index 000000000..1b6376f9a --- /dev/null +++ b/mrbgems/Makefile4gem @@ -0,0 +1,82 @@ +# This is the default Makefile integrated +# by each Gem. It integrates important constants +# for usage inside of a Gem. + +# mruby src root +MRUBY_ROOT := ../../../ + +# Tools +CC := gcc +RM := rm -f +AR := ar + +SRC_DIR := src +MRB_DIR := mrblib + +INCLUDES := -I$(SRC_DIR) -I$(MRUBY_ROOT)include -I$(MRUBY_ROOT)src -I. +CFLAGS := $(INCLUDES) -O3 -g -Wall -Werror-implicit-function-declaration + +# LIBR can be manipulated with command line arguments +ifeq ($(strip $(LIBR)),) + # default mruby library + LIBR := $(MRUBY_ROOT)lib/libmruby.a +endif + +# Default rules which are calling the +# gem specific gem-all and gem-clean +# implementations of a gem + +.PHONY : all +all : gem-info gem-all + +gem-info: + @echo "Building Gem '$(GEM)'" + +# Building target for C and Ruby files +gem-c-and-rb-files : gem_mixlib.o + $(AR) rs gem.a $(GEM_OBJECTS) $^ + +gem_mixlib.c : gem_mrblib_header.ctmp gem_mrblib_irep.ctmp gem_mixlib_init.ctmp + cat $^ > $@ + +gem_mixlib_init.ctmp : + ../../generator gem_mixlib $(GEM) > $@ + +# Building target for C files +gem-c-files : gem_srclib.o + $(AR) rs gem.a $(GEM_OBJECTS) $< + +gem_srclib.c : + ../../generator gem_srclib $(GEM) > $@ + +# Building target for Ruby Files +gem-rb-files : gem_mrblib.o + $(AR) rs gem.a $< + +gem_mrblib.c : gem_mrblib_header.ctmp gem_mrblib_irep.ctmp gem_mrblib_init.ctmp + cat $^ > $@ + +gem_mrblib_header.ctmp : + ../../generator gem_mrblib > $@ + +gem_mrblib_init.ctmp : + ../../generator gem_mrblib $(GEM) > $@ + +gem_mrblib_irep.ctmp : gem_mrblib.rbtmp + ../../../bin/mrbc -Bgem_mrblib_irep_$(GEM) -o$@ $< + +gem_mrblib.rbtmp : + cat $(GEM_RB_FILES) > $@ + +gem-clean-c-and-rb-files : + -$(RM) gem.a gem_mixlib.o gem_mixlib.c gem_mrblib_header.ctmp gem_mrblib_irep.ctmp gem_mixlib_init.ctmp gem_mrblib.rbtmp + +gem-clean-c-files : + -$(RM) gem.a gem_srclib.c gem_srclib.o $(GEM_OBJECTS) + +gem-clean-rb-files : + -$(RM) gem.a gem_mrblib.o gem_mrblib.c gem_mrblib_header.ctmp gem_mrblib_init.ctmp gem_mrblib_irep.ctmp gem_mrblib.rbtmp + +.PHONY : clean +clean : gem-clean + @echo "Gem '$(GEM)' is clean" diff --git a/mrbgems/g/.gitignore b/mrbgems/g/.gitignore new file mode 100644 index 000000000..f935021a8 --- /dev/null +++ b/mrbgems/g/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/mrbgems/generator.c b/mrbgems/generator.c new file mode 100644 index 000000000..f5cd2b76a --- /dev/null +++ b/mrbgems/generator.c @@ -0,0 +1,377 @@ +#include <string.h> +#include <stdio.h> +#include <dirent.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <mrbconf.h> +#include <stdlib.h> + +static int +one (const struct dirent *unused) +{ + return 1; +} + +/* + * Does a directory exist? + * yes => TRUE + * no => FALSE + * fs error => FALSE + * + */ +static int +directory_exists(char path[4096]) { + DIR* dir = opendir(path); + if (dir) + return TRUE; + else + return FALSE; +} + +/* + * Template generator for each GEM + * + * Arguments: + * before: + * String before each GEM template + * after: + * String after each GEM template + * start: + * String at the start of the template + * end: + * String at the end of the template + * dir_to_skip: + * Name of a directory which will be skipped + * + */ +static char* +for_each_gem (char before[1024], char after[1024], + char start[1024], char end[1024], + char dir_to_skip[1024]) +{ + FILE *fp; + char *active_gems = NULL; + char ch; + char gem_name[1024] = { 0 }; + int char_index; + char gem_list[1024][1024] = { { 0 }, { 0 } }; + int gem_index; + int i; + int b; + int cnt; + + struct dirent **eps; + int n; + char gemname[1024] = { 0 }; + char gemname_path[4096] = { 0 }; + char src_path[4096] = { 0 }; + struct stat attribut; + + fp = fopen("GEMS.active", "r+"); + if (fp != NULL) { + char_index = 0; + gem_index = 0; + while((ch = fgetc(fp)) != EOF) { + if (ch == '\n') { + gem_name[char_index++] = '\0'; + strcpy(gem_list[gem_index++], gem_name); + + gem_name[0] = '\0'; + char_index = 0; + } + else { + gem_name[char_index++] = ch; + } + } + + fclose(fp); + } + else { /* Error: Active GEM list couldn't be loaded */ } + + /* return value */ + char* complete_line = malloc(4096 + sizeof(char)); + strcpy(complete_line, ""); + strcat(complete_line, start); + + n = scandir("./g", &eps, one, alphasort); + if (n >= 0) { + for (cnt = 0; cnt < n; ++cnt) { + strcpy(gemname, eps[cnt]->d_name); + strcpy(gemname_path, "./g/"); + strcat(gemname_path, gemname); + + if (strcmp(gemname, ".") == 0) + continue; + if (strcmp(gemname, "..") == 0) + continue; + if (strcmp(gemname, ".gitignore") == 0) + continue; + + stat(gemname_path, &attribut); + if (S_ISDIR(attribut.st_mode) == 0) { + continue; + } + + b = 0; + for(i = 0; i <= gem_index; i++) { + if (strcmp(gem_list[i], gemname) != 0) + b = 0; + else { + /* Current GEM is active */ + b = 1; + break; + } + } + + /* In case the current GEM isn't active we skip it */ + if (b == 0) + continue; + + if (strcmp(dir_to_skip, "") != 0) { + strcpy(src_path, gemname_path); + strcat(src_path, "/"); + strcat(src_path, dir_to_skip); + + if (directory_exists(src_path) != TRUE) + continue; + } + + strcat(complete_line, before); + strcat(complete_line, gemname); + strcat(complete_line, after); + } + } + else { + perror("Error while scanning the directory."); + } + + strcat(complete_line, end); + return complete_line; +} + +/* + * Gem Makefile Generator + * + */ +void +make_gem_makefile() +{ + char *gem_check = { 0 }; + int gem_empty; + + printf("CFLAGS := -I. -I../../include -I../../src\n\n" + "ifeq ($(OS),Windows_NT)\n" + "MAKE_FLAGS = --no-print-directory CC=$(CC) LL=$(LL) ALL_CFLAGS='$(ALL_CFLAGS)'\n" + "else\n" + "MAKE_FLAGS = --no-print-directory CC='$(CC)' LL='$(LL)' ALL_CFLAGS='$(ALL_CFLAGS)'\n" + "endif\n\n"); + + /* is there any GEM available? */ + gem_check = for_each_gem("", "", "", "", ""); + if (strcmp(gem_check, "") == 0) + gem_empty = TRUE; + else + gem_empty = FALSE; + + printf(".PHONY : all\n"); + if (gem_empty) + printf("all :\n\n"); + else { + printf("all : all_gems\n"); + + printf("\n"); + + /* Rule to make every GEM */ + printf("all_gems :\n%s\n", + for_each_gem("\t@$(MAKE) -C ", " $(MAKE_FLAGS)\n", "", "", "") + ); + } + + printf("\n.PHONY : prepare-test\n" + "prepare-test :\n" + ); + if (!gem_empty) + printf("%s", + for_each_gem(" ", "/test/*.rb ", "\tcat", " > mrbgemtest.rbtmp", "test") + ); + else + printf("\t../generator rbtmp > mrbgemtest.rbtmp"); + printf("\n\t../../bin/mrbc -Bmrbgemtest_irep -omrbgemtest.ctmp mrbgemtest.rbtmp\n\n"); + + printf(".PHONY : clean\n" + "clean :\n" + "\t$(RM) *.c *.d *.rbtmp *.ctmp *.o mrbtest\n"); + if (!gem_empty) + printf("%s", + for_each_gem("\t@$(MAKE) clean -C ", " $(MAKE_FLAGS)\n", "", "", "") + ); +} + +/* + * Gem Makefile List Generator + * + */ +void +make_gem_makefile_list() +{ + printf("%s", + for_each_gem(" ", "", "GEM_LIST := ", "\n", "") + ); + + printf("GEM_ARCHIVE_FILES := $(addprefix $(MRUBY_ROOT)/mrbgems/g/, $(GEM_LIST))\n" + "GEM_ARCHIVE_FILES := $(addsuffix /gem.a, $(GEM_ARCHIVE_FILES))\n" + "GEM_ARCHIVE_FILES += $(MRUBY_ROOT)/mrbgems/gem_init.a\n\n"); +} + +/* + * init_gems.c Generator + * + */ +void +make_init_gems() +{ + printf("/*\n" + " * This file contains a list of all\n" + " * initializing methods which are\n" + " * necessary to bootstrap all gems.\n" + " *\n" + " * IMPORTANT:\n" + " * This file was generated!\n" + " * All manual changes will get lost.\n" + " */\n\n" + "#include \"mruby.h\"\n"); + + /* Protoype definition of all initialization methods */ + printf("\n%s", + for_each_gem("void GENERATED_TMP_mrb_", "_gem_init(mrb_state*);\n", "", "", "") + ); + + /* mrb_init_mrbgems(mrb) method for initialization of all GEMs */ + printf("\nvoid\n" + "mrb_init_mrbgems(mrb_state *mrb) {\n"); + printf( "%s", + for_each_gem(" GENERATED_TMP_mrb_", "_gem_init(mrb);\n", "", "", "") + ); + printf("}"); +} + +void +make_rbtmp() +{ + printf("\n"); +} + +void +make_gem_mrblib_header() +{ + printf("/*\n" + " * This file is loading the irep\n" + " * Ruby GEM code.\n" + " *\n" + " * IMPORTANT:\n" + " * This file was generated!\n" + " * All manual changes will get lost.\n" + " */\n\n" + "#include \"mruby.h\"\n" + "#include \"mruby/irep.h\"\n" + "#include \"mruby/dump.h\"\n" + "#include \"mruby/string.h\"\n" + "#include \"mruby/proc.h\"\n\n"); +} + +void +make_gem_mrblib(char argv[1024]) +{ + printf("\n" + "void\n" + "GENERATED_TMP_mrb_%s_gem_init(mrb_state *mrb) {\n" + " int n = mrb_read_irep(mrb, gem_mrblib_irep_%s);\n" + " mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));\n" + " if (mrb->exc) {\n" + " mrb_p(mrb, mrb_obj_value(mrb->exc));\n" + " exit(0);\n" + " }\n" + "}", argv, argv); +} + +void +make_gem_srclib(char argv[1024]) +{ + printf("/*\n" + " * This file is loading the irep\n" + " * Ruby GEM code.\n" + " *\n" + " * IMPORTANT:\n" + " * This file was generated!\n" + " * All manual changes will get lost.\n" + " */\n\n" + "#include \"mruby.h\"\n"); + + printf("\n" + "void mrb_%s_gem_init(mrb_state*);\n", argv); + + printf("\n" + "void\n" + "GENERATED_TMP_mrb_%s_gem_init(mrb_state *mrb) {\n" + " mrb_%s_gem_init(mrb);\n" + "}", argv, argv); +} + +void +make_gem_mixlib(char argv[1024]) +{ + printf("\n" + "void mrb_%s_gem_init(mrb_state*);\n", argv); + + printf("\n" + "void\n" + "GENERATED_TMP_mrb_%s_gem_init(mrb_state *mrb) {\n" + " mrb_%s_gem_init(mrb);\n" + " int n = mrb_read_irep(mrb, gem_mrblib_irep_%s);\n" + " mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));\n" + " if (mrb->exc) {\n" + " mrb_p(mrb, mrb_obj_value(mrb->exc));\n" + " exit(0);\n" + " }\n" + "}", argv, argv, argv); +} + +int +main (int argc, char *argv[]) +{ + if (argc == 2) { + if (strcmp(argv[1], "makefile") == 0) + make_gem_makefile(); + else if (strcmp(argv[1], "makefile_list") == 0) + make_gem_makefile_list(); + else if (strcmp(argv[1], "init_gems") == 0) + make_init_gems(); + else if (strcmp(argv[1], "rbtmp") == 0) + make_rbtmp(); + else if (strcmp(argv[1], "gem_mrblib") == 0) + make_gem_mrblib_header(); + else { + printf("Wrong argument! Options: 'makefile', 'init_gems', 'rbtmp', 'gem_mrblib', gem_srclib\n"); + return 1; + } + } + else if (argc == 3) { + if (strcmp(argv[1], "gem_mrblib") == 0) + make_gem_mrblib(argv[2]); + else if (strcmp(argv[1], "gem_srclib") == 0) + make_gem_srclib(argv[2]); + else if (strcmp(argv[1], "gem_mixlib") == 0) + make_gem_mixlib(argv[2]); + else { + printf("Wrong argument! Options: 'makefile', 'init_gems', 'rbtmp', 'gem_mrblib', gem_srclib\n"); + return 1; + } + } + else { + printf("Argument missing! Options: 'makefile', 'init_gems', 'rbtmp', 'gem_mrblib, gem_srclib'\n"); + return 1; + } + + return 0; +} diff --git a/src/init.c b/src/init.c index 52fd9e118..1a7e72686 100644 --- a/src/init.c +++ b/src/init.c @@ -27,6 +27,7 @@ void mrb_init_print(mrb_state*); void mrb_init_time(mrb_state*); void mrb_init_math(mrb_state*); void mrb_init_mrblib(mrb_state*); +void mrb_init_mrbgems(mrb_state*); void @@ -66,6 +67,7 @@ mrb_init_core(mrb_state *mrb) #endif mrb_init_mrblib(mrb); + mrb_init_mrbgems(mrb); mrb_gc_arena_restore(mrb, 0); } diff --git a/test/Makefile b/test/Makefile index 3df07b280..1cadd90a2 100644 --- a/test/Makefile +++ b/test/Makefile @@ -3,13 +3,24 @@ # project-specific macros # extension of the executable-file is modifiable(.exe .out ...) +MRUBY_ROOT := .. BASEDIR = . TARGET := mrbtest LIBR := ../lib/libmruby.a + +MAKEFILE_GEM_LIST := $(MRUBY_ROOT)/mrbgems/g/MakefileGemList +ifeq ($(wildcard $(MAKEFILE_GEM_LIST)),) + GEM_ARCHIVE_FILES = +else + include $(MAKEFILE_GEM_LIST) +endif + MLIB := $(TARGET).o CLIB := $(TARGET).c INIT := init_$(TARGET).c DLIB := $(TARGET).ctmp +GEMDIR := ../mrbgems +GEMDLIB := $(GEMDIR)/g/mrbgemtest.ctmp RLIB := $(TARGET).rbtmp DEPLIB := $(TARGET).d driver.d ASSLIB := $(BASEDIR)/assert.rb @@ -58,7 +69,6 @@ MRUBY= ../bin/mruby EXE := $(TARGET) endif - ############################## # generic build targets, rules @@ -76,7 +86,7 @@ all : $(EXE) $(MRUBY) $(TESTRB) $(TESTMRB) # executable constructed using linker from object files $(EXE) : $(OBJS) $(LIBR) - $(LL) -o $@ $(CFLAGS) $(OBJS) $(LIBR) $(LIBS) + $(LL) -o $@ $(CFLAGS) $(OBJS) $(LIBR) $(GEM_ARCHIVE_FILES) $(LIBS) -include $(OBJS:.o=.d) @@ -85,8 +95,12 @@ $(OBJS) : %.o : %.c $(CC) $(ALL_CFLAGS) -MMD $(INCLUDES) -c $< -o $@ # Compile C source from merged mruby source -$(CLIB) : $(RLIB) $(MRBC) $(INIT) - $(MRBC) -Bmrbtest_irep -o$(DLIB) $(RLIB); $(CAT) $(INIT) $(DLIB) > $@ +$(CLIB) : $(DLIB) $(INIT) + @$(MAKE) prepare-test -C $(GEMDIR) + $(CAT) $(INIT) $(DLIB) $(GEMDLIB) > $@ + +$(DLIB) : $(RLIB) $(MRBC) + $(MRBC) -Bmrbtest_irep -o$@ $(RLIB) # merge mruby sources $(RLIB) : $(ASSLIB) $(MRBS) diff --git a/test/init_mrbtest.c b/test/init_mrbtest.c index b9f09dd2f..2bc2f2e4b 100644 --- a/test/init_mrbtest.c +++ b/test/init_mrbtest.c @@ -5,13 +5,16 @@ #include "mruby/proc.h" extern const char mrbtest_irep[]; +extern const char mrbgemtest_irep[]; void mrb_init_mrbtest(mrb_state *mrb) { int n = mrb_read_irep(mrb, mrbtest_irep); + int m = mrb_read_irep(mrb, mrbgemtest_irep); mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb)); + mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[m]), mrb_top_self(mrb)); if (mrb->exc) { mrb_p(mrb, mrb_obj_value(mrb->exc)); exit(0); diff --git a/tools/mirb/Makefile b/tools/mirb/Makefile index 8dbbc52b3..2729c4829 100644 --- a/tools/mirb/Makefile +++ b/tools/mirb/Makefile @@ -3,9 +3,18 @@ # project-specific macros # extension of the executable-file is modifiable(.exe .out ...) +MRUBY_ROOT := ../.. BASEDIR = ../../src TARGET := ../../bin/mirb LIBR := ../../lib/libmruby.a + +MAKEFILE_GEM_LIST := $(MRUBY_ROOT)/mrbgems/g/MakefileGemList +ifeq ($(wildcard $(MAKEFILE_GEM_LIST)),) + GEM_ARCHIVE_FILES = +else + include $(MAKEFILE_GEM_LIST) +endif + ifeq ($(OS),Windows_NT) EXE := $(TARGET).exe else @@ -49,7 +58,7 @@ all : $(LIBR) $(EXE) # executable constructed using linker from object files $(EXE) : $(LIBR) $(OBJS) $(EXTS) - $(LL) -o $@ $(CFLAGS) $(OBJS) $(LIBR) $(EXTS) $(LIBS) + $(LL) -o $@ $(CFLAGS) $(OBJS) $(LIBR) $(GEM_ARCHIVE_FILES) $(EXTS) $(LIBS) -include $(OBJS:.o=.d) diff --git a/tools/mrbc/mrbc.c b/tools/mrbc/mrbc.c index 2ecb00623..6d9c85fa9 100644 --- a/tools/mrbc/mrbc.c +++ b/tools/mrbc/mrbc.c @@ -225,3 +225,8 @@ void mrb_init_mrblib(mrb_state *mrb) { } + +void +mrb_init_mrbgems(mrb_state *mrb) +{ +} diff --git a/tools/mruby/Makefile b/tools/mruby/Makefile index e94c1b2b4..53383a70b 100644 --- a/tools/mruby/Makefile +++ b/tools/mruby/Makefile @@ -3,9 +3,18 @@ # project-specific macros # extension of the executable-file is modifiable(.exe .out ...) -BASEDIR = ../../src -TARGET := ../../bin/mruby -LIBR := ../../lib/libmruby.a +MRUBY_ROOT := ../.. +BASEDIR = $(MRUBY_ROOT)/src +TARGET := $(MRUBY_ROOT)/bin/mruby +LIBR := $(MRUBY_ROOT)/lib/libmruby.a + +MAKEFILE_GEM_LIST := $(MRUBY_ROOT)/mrbgems/g/MakefileGemList +ifeq ($(wildcard $(MAKEFILE_GEM_LIST)),) + GEM_ARCHIVE_FILES = +else + include $(MAKEFILE_GEM_LIST) +endif + ifeq ($(OS),Windows_NT) EXE := $(TARGET).exe else @@ -54,7 +63,7 @@ all : $(LIBR) $(EXE) # executable constructed using linker from object files $(EXE) : $(LIBR) $(OBJS) $(EXTS) - $(LL) -o $@ $(CFLAGS) $(OBJS) $(LIBR) $(EXTS) $(LIBS) + $(LL) -o $@ $(CFLAGS) $(OBJS) $(LIBR) $(GEM_ARCHIVE_FILES) $(EXTS) $(LIBS) -include $(OBJS:.o=.d) |
