Browse files

Merge pull request #479 from bovi/mrbgems

mrbgems
  • Loading branch information...
2 parents bd3b95c + bef73cc commit f521738953b9297a4d26e68ec42b7e9a22e5b442 @matz matz committed Dec 7, 2012
View
6 .gitignore
@@ -25,3 +25,9 @@ cscope.out
/test/mrubytest.*
CMakeFiles
CMakeCache.txt
+/mrbgems/generator
+/mrbgems/gem_init.c
+/mrbgems/g/Makefile
+/mrbgems/g/MakefileGemList
+/mrbgems/g/mrbgemtest.ctmp
+/mrbgems/g/mrbgemtest.rbtmp
View
26 Makefile
@@ -7,6 +7,18 @@ export LL = gcc
export AR = ar
export YACC = bison
+MRUBY_ROOT := $(realpath .)
+
+ifeq ($(strip $(ENABLE_GEMS)),)
+ # by default GEMs are deactivated
+ ENABLE_GEMS = false
+endif
+
+ifeq ($(strip $(ACTIVE_GEMS)),)
+ # the default file which contains the active GEMs
+ ACTIVE_GEMS = GEMS.active
+endif
+
ifeq ($(strip $(COMPILE_MODE)),)
# default compile option
COMPILE_MODE = debug
@@ -22,9 +34,9 @@ endif
ALL_CFLAGS = -Wall -Werror-implicit-function-declaration $(CFLAGS)
ifeq ($(OS),Windows_NT)
- MAKE_FLAGS = --no-print-directory CC=$(CC) LL=$(LL) ALL_CFLAGS='$(ALL_CFLAGS)'
+ MAKE_FLAGS = --no-print-directory CC=$(CC) LL=$(LL) ALL_CFLAGS='$(ALL_CFLAGS)' ENABLE_GEMS='$(ENABLE_GEMS)' ACTIVE_GEMS='$(ACTIVE_GEMS)' MRUBY_ROOT='$(MRUBY_ROOT)'
else
- MAKE_FLAGS = --no-print-directory CC='$(CC)' LL='$(LL)' ALL_CFLAGS='$(ALL_CFLAGS)'
+ MAKE_FLAGS = --no-print-directory CC='$(CC)' LL='$(LL)' ALL_CFLAGS='$(ALL_CFLAGS)' ENABLE_GEMS='$(ENABLE_GEMS)' ACTIVE_GEMS='$(ACTIVE_GEMS)' MRUBY_ROOT='$(MRUBY_ROOT)'
endif
##############################
@@ -44,7 +56,11 @@ export CAT := cat
all :
@$(MAKE) -C src $(MAKE_FLAGS)
@$(MAKE) -C mrblib $(MAKE_FLAGS)
- @$(MAKE) -C tools/mruby $(MAKE_FLAGS)
+ifeq ($(ENABLE_GEMS),true)
+ @echo "-- MAKE mrbgems --"
+ @$(MAKE) -C mrbgems $(MAKE_FLAGS)
+endif
+ $(MAKE) -C tools/mruby $(MAKE_FLAGS)
@$(MAKE) -C tools/mirb $(MAKE_FLAGS)
# mruby test
@@ -56,6 +72,10 @@ test : all
.PHONY : clean
clean :
@$(MAKE) clean -C src $(MAKE_FLAGS)
+ifeq ($(ENABLE_GEMS),true)
+ @echo "-- CLEAN mrbgems --"
+ @$(MAKE) clean -C mrbgems $(MAKE_FLAGS)
+endif
@$(MAKE) clean -C tools/mruby $(MAKE_FLAGS)
@$(MAKE) clean -C tools/mirb $(MAKE_FLAGS)
@$(MAKE) clean -C test $(MAKE_FLAGS)
View
179 doc/mrbgems/README.md
@@ -0,0 +1,179 @@
+# mrbgems
+
+mrbgems is a library manager to integrate C and Ruby extension in an easy and
+standardised way into mruby.
+
+## Usage
+
+By default mrbgems is currently deactivated. As long as mrbgems is deactivated
+there is no overhead inside of the mruby interpreter.
+
+To activate you have to make the following changes:
+* set *ENABLE_GEMS* to *true* in *$(MRUBY_ROOT)/Makefile*
+* define *ENABLE_GEMS* in *$(MRUBY_ROOT)/include/mrbconf.h*
+* activate GEMs in *$(MRUBY_ROOT)/mrbgems/GEMS.active*
+
+Every activated GEM has to be listed with his absolute path in *GEMS.active*. It
+is possible to point to an alternative activate file:
+* set *ACTIVE_GEMS* to your customized GEM list in *$(MRUBY_ROOT)/Makefile*
+
+## 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 a *gem.a* file inside of the GEM directory. Which will be used
+for integration into the normal mruby build process. *README.md* is a short
+description of your GEM.
+
+## Build process
+
+mrbgems will call *make* to build and *make clean* to clean your GEM. You
+have to build a *mrb-GEMNAME-gem.a* file during this build process. How you
+are going to do this is up to you.
+
+To make your build process more easier and more standardized we suggest
+to include *mrbgems/Makefile4gem* which defines some helper rules. In
+case you include this Makefile you have to define specific pre-defined
+rules like *gem-all* for the build process and *gem-clean* for the clean
+process. There are additional helper rules for specific GEM examples
+below.
+
+## C Extension
+
+mruby can be extended with C. It is possible by using the C API to
+integrate C libraries into mruby.
+
+The *Makefile* is used for building a C extension. You should
+define *GEM* (GEM name), *GEM_C_FILES* (all C files) and
+*GEM_OBJECTS* (all Object files). Pay also attention that your
+*Makefile* has to build the object files. You can use
+*gem-c-files* to build a *mrb-GEMNAME-gem.a* out of your
+Object code and use *gem-clean-c-files* to clean the object files.
+
+### Pre-Conditions
+
+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.
+
+The *Makefile* is used for building a Ruby extension. You should define
+*GEM* (GEM name) and *GEM_RB_FILES* (all Ruby files). You can use
+*gem-rb-files* to build a *mrb-GEMNAME-gem.a* out of your Ruby code and use
+*gem-clean-rb-files* to clean the generated C files.
+
+### Pre-Conditions
+
+mrbgems will automatically call the *gem-all* make target of your GEM.
+
+mrbgems will also use the *gem-clean* make target to clean up your GEM. Implement
+this target with the necessary rules!
+
+### Example
+
+```
++- ruby_extension_example/
+ |
+ +- mrblib/
+ | |
+ | +- example.rb <- Ruby extension source
+ |
+ +- test/
+ | |
+ | +- example.rb <- Test code for Ruby extension
+ |
+ +- Makefile
+ |
+ +- README.md
+```
+
+## C and Ruby Extension
+
+mruby can be extended with C and Ruby at the same time. It is possible to
+override existing classes or add new ones in this way. Put all Ruby files
+into the *mrblib* folder and all C files into the *src* folder.
+
+The *Makefile* is used for building a C and Ruby extension. You should
+define *GEM* (GEM name), *GEM_C_FILES* (all C files), *GEM_OBJECTS*
+(all Object files) and *GEM_RB_FILES* (all Ruby files). You can use
+*gem-c-and-rb-files* to build a *mrb-GEMNAME-gem.a* out of your Object
+and Ruby code. Use *gem-clean-c-and-rb-files* to clean the generated
+C files.
+
+### Pre-Conditions
+
+See C and Ruby example.
+
+### Example
+
+```
++- c_and_ruby_extension_example/
+ |
+ +- mrblib/
+ | |
+ | +- example.rb <- Ruby extension source
+ |
+ +- src/
+ | |
+ | +- example.c <- C extension source
+ |
+ +- test/
+ | |
+ | +- example.rb <- Test code for C and Ruby extension
+ |
+ +- Makefile
+ |
+ +- README.md
View
12 doc/mrbgems/c_and_ruby_extension_example/Makefile
@@ -0,0 +1,12 @@
+GEM := c_and_ruby_extension_example
+
+include $(MAKEFILE_4_GEM)
+
+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
View
4 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.
View
5 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
View
17 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());
+}
View
7 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
View
10 doc/mrbgems/c_extension_example/Makefile
@@ -0,0 +1,10 @@
+GEM := c_extension_example
+
+include $(MAKEFILE_4_GEM)
+
+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
View
4 doc/mrbgems/c_extension_example/README.md
@@ -0,0 +1,4 @@
+C Extension Example
+=========
+
+This is an example gem which implements a C extension.
View
17 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());
+}
View
3 doc/mrbgems/c_extension_example/test/example.rb
@@ -0,0 +1,3 @@
+assert('C Extension Example') do
+ CExtension.respond_to? :c_method
+end
View
9 doc/mrbgems/ruby_extension_example/Makefile
@@ -0,0 +1,9 @@
+GEM := ruby_extension_example
+
+include $(MAKEFILE_4_GEM)
+
+GEM_RB_FILES := $(wildcard $(MRB_DIR)/*.rb)
+
+gem-all : gem-rb-files
+
+gem-clean : gem-clean-rb-files
View
4 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.
View
5 doc/mrbgems/ruby_extension_example/mrblib/example.rb
@@ -0,0 +1,5 @@
+class RubyExtension
+ def RubyExtension.ruby_method
+ puts "A Ruby Extension"
+ end
+end
View
3 doc/mrbgems/ruby_extension_example/test/example.rb
@@ -0,0 +1,3 @@
+assert('Ruby Extension Example') do
+ RubyExtension.respond_to? :ruby_method
+end
View
1 include/mrbconf.h
@@ -50,6 +50,7 @@
//#define DISABLE_TIME /* Time class */
//#define DISABLE_STRUCT /* Struct class */
//#define DISABLE_STDIO /* use of stdio */
+#define DISABLE_GEMS /* Package Manager mrbgems */
#undef HAVE_UNISTD_H /* WINDOWS */
#define HAVE_UNISTD_H /* LINUX */
View
0 mrbgems/GEMS.active
No changes.
View
76 mrbgems/Makefile
@@ -0,0 +1,76 @@
+# makefile description.
+# add gems to the ruby library
+
+ifeq ($(strip $(MRUBY_ROOT)),)
+ MRUBY_ROOT := $(realpath ..)
+endif
+
+LIBR := ../lib/libmruby.a
+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 := $(MRUBY_ROOT)/mrbgems/generator
+ifeq ($(OS),Windows_NT)
+ GENERATOR_BIN := $(GENERATOR).exe
+else
+ GENERATOR_BIN := $(GENERATOR)
+endif
+GEM_INIT := gem_init
+GEM_MAKEFILE := g/Makefile
+GEM_MAKEFILE_LIST := g/MakefileGemList
+GEMDLIB := g/mrbgemtest.ctmp
+
+ifeq ($(strip $(ACTIVE_GEMS)),)
+ # the default file which contains the active GEMs
+ ACTIVE_GEMS = GEMS.active
+endif
+
+##############################
+# generic build targets, rules
+
+.PHONY : all
+all : all_gems $(GEM_INIT).a
+
+$(GEM_INIT).a : $(GEM_INIT).o
+ $(AR) rs gem_init.a $(GEM_INIT).o
+
+all_gems : $(GENERATOR_BIN)
+ @echo "Generate Gem List Makefile"
+ $(GENERATOR_BIN) makefile_list "$(ACTIVE_GEMS)" > $(GEM_MAKEFILE_LIST)
+ @echo "Generate Gem Makefile"
+ $(GENERATOR_BIN) makefile "$(ACTIVE_GEMS)" > $(GEM_MAKEFILE)
+ @echo "Build all gems"
+ $(MAKE) -C g MRUBY_ROOT='$(MRUBY_ROOT)' ACTIVE_GEMS="$(ACTIVE_GEMS)"
+
+$(GEM_INIT).c : $(GENERATOR_BIN)
+ @echo "Generate Gem driver"
+ $(GENERATOR_BIN) $(GEM_INIT) "$(ACTIVE_GEMS)" > $@
+
+$(GEM_INIT).o : $(GEM_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 ACTIVE_GEMS="$(ACTIVE_GEMS)" MRUBY_ROOT='$(MRUBY_ROOT)'
+
+# clean driver and all gems
+.PHONY : clean
+clean : $(GENERATOR_BIN)
+ @echo "Cleanup Gems"
+ $(GENERATOR_BIN) makefile "$(ACTIVE_GEMS)" > $(GEM_MAKEFILE)
+ $(MAKE) clean -C g ACTIVE_GEMS="$(ACTIVE_GEMS)" MRUBY_ROOT='$(MRUBY_ROOT)'
+ -$(RM_F) $(GEM_INIT).c *.o *.d $(GENERATOR_BIN) $(GEM_MAKEFILE) $(GEM_MAKEFILE_LIST) gem_init.a
View
91 mrbgems/Makefile4gem
@@ -0,0 +1,91 @@
+# This is the default Makefile integrated
+# by each Gem. It integrates important constants
+# for usage inside of a Gem.
+
+ifeq ($(strip $(MRUBY_ROOT)),)
+ # mruby src root
+ MRUBY_ROOT := $(realpath ../../..)
+endif
+
+# 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
+
+GEM_PACKAGE := mrb-$(GEM)-gem.a
+
+ifeq ($(strip $(ACTIVE_GEMS)),)
+ # the default file which contains the active GEMs
+ ACTIVE_GEMS = GEMS.active
+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_PACKAGE) $(GEM_OBJECTS) $^
+
+gem_mixlib.c : gem_mrblib_header.ctmp gem_mrblib_irep.ctmp gem_mixlib_init.ctmp
+ cat $^ > $@
+
+gem_mixlib_init.ctmp :
+ $(MRUBY_ROOT)/mrbgems/generator gem_mixlib $(GEM) "$(ACTIVE_GEMS)" > $@
+
+# Building target for C files
+gem-c-files : gem_srclib.o
+ $(AR) rs $(GEM_PACKAGE) $(GEM_OBJECTS) $<
+
+gem_srclib.c :
+ $(MRUBY_ROOT)/mrbgems/generator gem_srclib $(GEM) "$(ACTIVE_GEMS)" > $@
+
+# Building target for Ruby Files
+gem-rb-files : gem_mrblib.o
+ $(AR) rs $(GEM_PACKAGE) $<
+
+gem_mrblib.c : gem_mrblib_header.ctmp gem_mrblib_irep.ctmp gem_mrblib_init.ctmp
+ cat $^ > $@
+
+gem_mrblib_header.ctmp :
+ $(MRUBY_ROOT)/mrbgems/generator gem_mrblib "$(ACTIVE_GEMS)" > $@
+
+gem_mrblib_init.ctmp :
+ $(MRUBY_ROOT)/mrbgems/generator gem_mrblib $(GEM) "$(ACTIVE_GEMS)" > $@
+
+gem_mrblib_irep.ctmp : gem_mrblib.rbtmp
+ $(MRUBY_ROOT)/bin/mrbc -Bgem_mrblib_irep_$(GEM) -o$@ $<
+
+gem_mrblib.rbtmp :
+ cat $(GEM_RB_FILES) > $@
+
+gem-clean-c-and-rb-files :
+ -$(RM) $(GEM_PACKAGE) 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_PACKAGE) gem_srclib.c gem_srclib.o $(GEM_OBJECTS)
+
+gem-clean-rb-files :
+ -$(RM) $(GEM_PACKAGE) 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"
View
1 mrbgems/g/.gitignore
@@ -0,0 +1 @@
+!.gitignore
View
420 mrbgems/generator.c
@@ -0,0 +1,420 @@
+/*
+** generator.c - Generator for mrbgems
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <mrbconf.h>
+
+/*
+ * Get the file name part of *path*
+ *
+ * Arguments:
+ * path:
+ * String which represents the path
+ *
+ */
+static char
+*get_file_name(char *path)
+{
+ char *base = strrchr(path, '/');
+ return base ? base+1 : path;
+}
+
+/*
+ * Search in *s* for *old* and replace with *new*.
+ *
+ * Arguments:
+ * s:
+ * String in which the the replacement will be done
+ * old:
+ * String which will be replaced
+ * new:
+ * String which will be the replacement
+ *
+ */
+static char
+*replace(const char *s, const char *old, const char *new)
+{
+ char *ret;
+ int i, count = 0;
+ size_t newlen = strlen(new);
+ size_t oldlen = strlen(old);
+
+ for (i = 0; s[i] != '\0'; i++) {
+ if (strstr(&s[i], old) == &s[i]) {
+ count++;
+ i += oldlen - 1;
+ }
+ }
+
+ ret = malloc(i + count * (newlen - oldlen));
+ if (ret == NULL)
+ exit(EXIT_FAILURE);
+
+ i = 0;
+ while (*s) {
+ if (strstr(s, old) == s) {
+ strcpy(&ret[i], new);
+ i += newlen;
+ s += oldlen;
+ }
+ else
+ ret[i++] = *s++;
+ }
+ ret[i] = '\0';
+
+ return ret;
+}
+
+/*
+ * Template generator for each active 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
+ * full_path
+ * Should the full path of the GEM be used?
+ *
+ */
+static char*
+for_each_gem (char before[1024], char after[1024],
+ char start[1024], char end[1024],
+ int full_path, char active_gems[1024])
+{
+ /* active GEM check */
+ FILE *active_gem_file;
+ char gem_char;
+ char gem_name[1024] = { 0 };
+ int char_index;
+ char gem_list[1024][1024] = { { 0 }, { 0 } };
+ int gem_index;
+ int i;
+
+ /* return value */
+ char* complete_line = malloc(4096 + sizeof(char));
+ strcpy(complete_line, "");
+ strcat(complete_line, start);
+
+ /* Read out the active GEMs */
+ active_gem_file = fopen(active_gems, "r+");
+ if (active_gem_file != NULL) {
+ char_index = 0;
+ gem_index = 0;
+ while((gem_char = fgetc(active_gem_file)) != EOF) {
+ if (gem_char == '\n') {
+ /* Every line contains one active GEM */
+ gem_name[char_index++] = '\0';
+ strcpy(gem_list[gem_index++], gem_name);
+
+ gem_name[0] = '\0';
+ char_index = 0;
+ }
+ else
+ gem_name[char_index++] = gem_char;
+ }
+
+ fclose(active_gem_file);
+ }
+ else { /* Error: Active GEM list couldn't be loaded */ }
+
+ for(i = 0; i < gem_index; i++) {
+ strcat(complete_line, before);
+ if (full_path == TRUE)
+ strcat(complete_line, gem_list[i]);
+ else
+ strcat(complete_line, get_file_name(gem_list[i]));
+ strcat(complete_line, replace(after, "#GEMNAME#", get_file_name(gem_list[i])));
+ }
+
+ strcat(complete_line, end);
+ return complete_line;
+}
+
+/*
+ * Gem Makefile Generator
+ *
+ * Global Makefile which starts the build process
+ * for every active GEM.
+ *
+ */
+static void
+make_gem_makefile(char active_gems[1024])
+{
+ char *gem_check = { 0 };
+ int gem_empty;
+
+ printf("ifeq ($(strip $(MRUBY_ROOT)),)\n"
+ " MRUBY_ROOT := $(realpath ../../..)\n"
+ "endif\n\n"
+ "MAKEFILE_4_GEM := $(MRUBY_ROOT)/mrbgems/Makefile4gem\n\n"
+ "CFLAGS := -I. -I$(MRUBY_ROOT)/include -I$(MRUBY_ROOT)/src\n\n"
+ "ifeq ($(OS),Windows_NT)\n"
+ " MAKE_FLAGS = --no-print-directory CC=$(CC) LL=$(LL) ALL_CFLAGS='$(ALL_CFLAGS)' MRUBY_ROOT='$(MRUBY_ROOT)' MAKEFILE_4_GEM='$(MAKEFILE_4_GEM)'\n"
+ "else\n"
+ " MAKE_FLAGS = --no-print-directory CC='$(CC)' LL='$(LL)' ALL_CFLAGS='$(ALL_CFLAGS)' MRUBY_ROOT='$(MRUBY_ROOT)' MAKEFILE_4_GEM='$(MAKEFILE_4_GEM)'\n"
+ "endif\n\n");
+
+ /* is there any GEM available? */
+ gem_check = for_each_gem("", "", "", "", TRUE, active_gems);
+ if (strcmp(gem_check, "") == 0)
+ gem_empty = TRUE;
+ else
+ gem_empty = FALSE;
+
+ /* Makefile Rules to build every single GEM */
+
+ printf(".PHONY : all\n");
+ if (gem_empty)
+ printf("all :\n\n");
+ else {
+ printf("all : all_gems\n\n");
+
+ /* Call make for every GEM */
+ printf("all_gems :\n%s\n",
+ for_each_gem("\t@$(MAKE) -C ", " $(MAKE_FLAGS)\n", "", "", TRUE, active_gems)
+ );
+ printf("\n");
+ }
+
+ /* Makefile Rules to Test GEMs */
+
+ printf(".PHONY : prepare-test\n"
+ "prepare-test :\n"
+ );
+ if (!gem_empty)
+ printf("%s",
+ for_each_gem(" ", "/test/*.rb ", "\tcat", " > mrbgemtest.rbtmp", TRUE, active_gems)
+ );
+ else
+ printf("\t$(MRUBY_ROOT)/mrbgems/generator rbtmp \"%s\"> mrbgemtest.rbtmp", active_gems);
+
+ printf("\n\t$(MRUBY_ROOT)/bin/mrbc -Bmrbgemtest_irep -omrbgemtest.ctmp mrbgemtest.rbtmp\n\n");
+
+ /* Makefile Rules to Clean GEMs */
+
+ 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", "", "", TRUE, active_gems)
+ );
+}
+
+/*
+ * Gem Makefile List Generator
+ *
+ * Creates a Makefile which will be included by other Makefiles
+ * which need to know which GEMs are active.
+ *
+ */
+static void
+make_gem_makefile_list(char active_gems[1024])
+{
+ printf("%s",
+ for_each_gem(" ", "/mrb-#GEMNAME#-gem.a", "GEM_LIST := ", "\n", TRUE, active_gems)
+ );
+
+ printf("GEM_ARCHIVE_FILES := $(MRUBY_ROOT)/mrbgems/gem_init.a\n"
+ "GEM_ARCHIVE_FILES += $(GEM_LIST)\n\n");
+}
+
+/*
+ * gem_init.c Generator
+ *
+ */
+static void
+make_gem_init(char active_gems[1024])
+{
+ 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", "", "", FALSE, active_gems)
+ );
+ printf("\n");
+
+ /* mrb_init_mrbgems(mrb) method for initialization of all GEMs */
+ printf("void\n"
+ "mrb_init_mrbgems(mrb_state *mrb) {\n");
+ printf( "%s",
+ for_each_gem(" GENERATED_TMP_mrb_", "_gem_init(mrb);\n", "", "", FALSE, active_gems)
+ );
+ printf("}");
+}
+
+/*
+ * Empty Generator
+ *
+ * Generates a clean file with one new line.
+ *
+ */
+static void
+make_rbtmp(char active_gems[1024])
+{
+ printf("\n");
+}
+
+/*
+ * Header Generator
+ *
+ * Head of the C Code for loading the GEMs into the interpreter.
+ *
+ */
+static void
+make_gem_mrblib_header(char active_gems[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"
+ "#include \"mruby/irep.h\"\n"
+ "#include \"mruby/dump.h\"\n"
+ "#include \"mruby/string.h\"\n"
+ "#include \"mruby/proc.h\"\n\n");
+}
+
+/*
+ * mrblib Generator
+ *
+ * Generates the C Code for loading
+ * the pure Ruby GEMs into the interpreter.
+ *
+ */
+static void
+make_gem_mrblib(char argv[1024], char active_gems[1024])
+{
+ printf("\n"
+ "void\n"
+ "GENERATED_TMP_mrb_%s_gem_init(mrb_state *mrb) {\n"
+ " mrb_load_irep(mrb, gem_mrblib_irep_%s);\n"
+ " if (mrb->exc) {\n"
+ " mrb_p(mrb, mrb_obj_value(mrb->exc));\n"
+ " exit(0);\n"
+ " }\n"
+ "}", argv, argv);
+}
+
+/*
+ * srclib Generator
+ *
+ * Generates the C Code for loading
+ * the pure C GEMs into the interpreter.
+ *
+ */
+static void
+make_gem_srclib(char argv[1024], char active_gems[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);
+}
+
+/*
+ * mixlib Generator
+ *
+ * Generates the C Code for loading
+ * the mixed Ruby and C GEMs
+ * into the interpreter.
+ *
+ */
+static void
+make_gem_mixlib(char argv[1024], char active_gems[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"
+ " mrb_load_irep(mrb, gem_mrblib_irep_%s);\n"
+ " if (mrb->exc) {\n"
+ " mrb_p(mrb, mrb_obj_value(mrb->exc));\n"
+ " exit(0);\n"
+ " }\n"
+ "}", argv, argv, argv);
+}
+
+/*
+ * Start the generator and decide what to generate.
+ *
+ */
+int
+main (int argc, char *argv[])
+{
+ const char * argument_info = "Wrong argument! Options: 'makefile', 'gem_init', 'rbtmp', 'gem_mrblib', gem_srclib\n";
+ if (argc == 3) {
+ if (strcmp(argv[1], "makefile") == 0)
+ make_gem_makefile(argv[2]);
+ else if (strcmp(argv[1], "makefile_list") == 0)
+ make_gem_makefile_list(argv[2]);
+ else if (strcmp(argv[1], "gem_init") == 0)
+ make_gem_init(argv[2]);
+ else if (strcmp(argv[1], "rbtmp") == 0)
+ make_rbtmp(argv[2]);
+ else if (strcmp(argv[1], "gem_mrblib") == 0)
+ make_gem_mrblib_header(argv[2]);
+ else {
+ printf("%s", argument_info);
+ return 1;
+ }
+ }
+ else if (argc == 4) {
+ if (strcmp(argv[1], "gem_mrblib") == 0)
+ make_gem_mrblib(argv[2], argv[3]);
+ else if (strcmp(argv[1], "gem_srclib") == 0)
+ make_gem_srclib(argv[2], argv[3]);
+ else if (strcmp(argv[1], "gem_mixlib") == 0)
+ make_gem_mixlib(argv[2], argv[3]);
+ else {
+ printf("%s", argument_info);
+ return 1;
+ }
+ }
+ else {
+ printf("%s", argument_info);
+ return 1;
+ }
+
+ return 0;
+}
View
5 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*);
#define DONE mrb_gc_arena_restore(mrb, 0);
void
@@ -64,6 +65,8 @@ mrb_init_core(mrb_state *mrb)
#ifdef ENABLE_MATH
mrb_init_math(mrb); DONE;
#endif
-
mrb_init_mrblib(mrb); DONE;
+#ifdef ENABLE_GEMS
+ mrb_init_mrbgems(mrb); DONE;
+#endif
}
View
33 test/Makefile
@@ -3,9 +3,29 @@
# project-specific macros
# extension of the executable-file is modifiable(.exe .out ...)
+MRUBY_ROOT := ..
BASEDIR = .
TARGET := mrbtest
LIBR := ../lib/libmruby.a
+
+ifeq ($(strip $(ENABLE_GEMS)),)
+ # by default GEMs are deactivated
+ ENABLE_GEMS = false
+endif
+
+ifeq ($(ENABLE_GEMS),false)
+ GEM_ARCHIVE_FILES =
+else
+ GEMDIR := ../mrbgems
+ GEMDLIB := $(GEMDIR)/g/mrbgemtest.ctmp
+ MAKEFILE_GEM_LIST := $(MRUBY_ROOT)/mrbgems/g/MakefileGemList
+ ifeq ($(wildcard $(MAKEFILE_GEM_LIST)),)
+ GEM_ARCHIVE_FILES =
+ else
+ include $(MAKEFILE_GEM_LIST)
+ endif
+endif
+
MLIB := $(TARGET).o
CLIB := $(TARGET).c
INIT := init_$(TARGET).c
@@ -58,7 +78,6 @@ MRUBY= ../bin/mruby
EXE := $(TARGET)
endif
-
##############################
# generic build targets, rules
@@ -76,7 +95,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 +104,14 @@ $(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)
+ifeq ($(ENABLE_GEMS),true)
+ @$(MAKE) prepare-test -C $(GEMDIR)
+endif
+ $(CAT) $(INIT) $(DLIB) $(GEMDLIB) > $@
+
+$(DLIB) : $(RLIB) $(MRBC)
+ $(MRBC) -Bmrbtest_irep -o$@ $(RLIB)
# merge mruby sources
$(RLIB) : $(ASSLIB) $(MRBS)
View
4 test/init_mrbtest.c
@@ -5,11 +5,15 @@
#include "mruby/proc.h"
extern const char mrbtest_irep[];
+extern const char mrbgemtest_irep[];
void
mrb_init_mrbtest(mrb_state *mrb)
{
mrb_load_irep(mrb, mrbtest_irep);
+#ifdef ENABLE_GEMS
+ mrb_load_irep(mrb, mrbgemtest_irep);
+#endif
if (mrb->exc) {
mrb_p(mrb, mrb_obj_value(mrb->exc));
exit(0);
View
20 tools/mirb/Makefile
@@ -3,9 +3,27 @@
# project-specific macros
# extension of the executable-file is modifiable(.exe .out ...)
+MRUBY_ROOT := ../..
BASEDIR = ../../src
TARGET := ../../bin/mirb
LIBR := ../../lib/libmruby.a
+
+ifeq ($(strip $(ENABLE_GEMS)),)
+ # by default GEMs are deactivated
+ ENABLE_GEMS = false
+endif
+
+ifeq ($(ENABLE_GEMS),false)
+ GEM_ARCHIVE_FILES =
+else
+ MAKEFILE_GEM_LIST := $(MRUBY_ROOT)/mrbgems/g/MakefileGemList
+ ifeq ($(wildcard $(MAKEFILE_GEM_LIST)),)
+ GEM_ARCHIVE_FILES =
+ else
+ include $(MAKEFILE_GEM_LIST)
+ endif
+endif
+
ifeq ($(OS),Windows_NT)
EXE := $(TARGET).exe
else
@@ -49,7 +67,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)
View
7 tools/mrbc/mrbc.c
@@ -225,3 +225,10 @@ void
mrb_init_mrblib(mrb_state *mrb)
{
}
+
+#ifdef ENABLE_GEMS
+void
+mrb_init_mrbgems(mrb_state *mrb)
+{
+}
+#endif
View
26 tools/mruby/Makefile
@@ -3,9 +3,27 @@
# 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
+
+ifeq ($(strip $(ENABLE_GEMS)),)
+ # by default GEMs are deactivated
+ ENABLE_GEMS = false
+endif
+
+ifeq ($(ENABLE_GEMS),false)
+ GEM_ARCHIVE_FILES =
+else
+ MAKEFILE_GEM_LIST := $(MRUBY_ROOT)/mrbgems/g/MakefileGemList
+ ifeq ($(wildcard $(MAKEFILE_GEM_LIST)),)
+ GEM_ARCHIVE_FILES =
+ else
+ include $(MAKEFILE_GEM_LIST)
+ endif
+endif
+
ifeq ($(OS),Windows_NT)
EXE := $(TARGET).exe
else
@@ -54,7 +72,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)

0 comments on commit f521738

Please sign in to comment.