summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDaniel Bovensiepen <[email protected]>2012-09-21 19:56:28 +0800
committerDaniel Bovensiepen <[email protected]>2012-09-21 19:56:28 +0800
commitd6f2f55b46ceddd986e7ba42fb8269aef0ca8e77 (patch)
tree9e3a405436789e9c782a6c4c00eafed4301df809
parentf93572c531c1e69dc0c5d2c2bfd03fc83044158c (diff)
downloadmruby-d6f2f55b46ceddd986e7ba42fb8269aef0ca8e77.tar.gz
mruby-d6f2f55b46ceddd986e7ba42fb8269aef0ca8e77.zip
Add Support for Ruby Extensions, C Extensions and Test Integration
-rw-r--r--mrbgems/Makefile28
-rw-r--r--mrbgems/g/clib_example/Makefile (renamed from mrbgems/g/hello_world/Makefile)2
-rw-r--r--mrbgems/g/clib_example/README.md4
-rw-r--r--mrbgems/g/clib_example/src/clib_example.c17
-rw-r--r--mrbgems/g/clib_example/test/clib_example.rb3
-rw-r--r--mrbgems/g/hello_world/src/hello_world.c17
-rw-r--r--mrbgems/g/hello_world/test/hello_world.rb3
-rw-r--r--mrbgems/g/mrblib_example/Makefile7
-rw-r--r--mrbgems/g/mrblib_example/README.md (renamed from mrbgems/g/hello_world/README.md)0
-rw-r--r--mrbgems/g/mrblib_example/mrblib/mrblib_example.rb5
-rw-r--r--mrbgems/g/mrblib_example/test/mrblib_example.rb3
-rw-r--r--mrbgems/gem_helper.c108
12 files changed, 151 insertions, 46 deletions
diff --git a/mrbgems/Makefile b/mrbgems/Makefile
index 0f2908ab9..1cb5b8a83 100644
--- a/mrbgems/Makefile
+++ b/mrbgems/Makefile
@@ -17,29 +17,31 @@ export AR = ar
.PHONY : all
all : $(INIT).o all_gems
-$(MMAKER_BIN) : $(MMAKER).o
- @echo "Build the generator which creates the driver and Gem Makefile"
- $(LL) -o $@ $(CC_FLAGS) $<
+all_gems : g/Makefile
+ @echo "Build all gems"
+ $(MAKE) -C g
-$(MMAKER).o : $(MMAKER).c
- $(CC) $(CC_FLAGS) -MMD -c $< -o $@
+g/Makefile : $(MMAKER_BIN)
+ @echo "Generate Gem Makefile"
+ $(MMAKER_BIN) makefile > $@
$(INIT).c : $(MMAKER_BIN)
@echo "Generate Gem driver"
$(MMAKER_BIN) $(INIT) > $@
$(INIT).o : $(INIT).c
- @echo "Build the driver which initiailizes all gems"
- gcc $(CC_FLAGS) -c $< -o $@
+ @echo "Build the driver which initializes all gems"
+ $(CC) $(CC_FLAGS) -MMD -c $< -o $@
$(AR) rs $(LIBR) $@
-g/Makefile :
- @echo "Generate Gem Makefile"
- $(MMAKER_BIN) makefile > $@
+# Generator
-all_gems : $(MMAKER_BIN) g/Makefile
- @echo "Build all gems"
- $(MAKE) -C g
+$(MMAKER_BIN) : $(MMAKER).o
+ @echo "Build the generator which creates the driver and Gem Makefile"
+ $(LL) -o $@ $(CC_FLAGS) $<
+
+$(MMAKER).o : $(MMAKER).c
+ $(CC) $(CC_FLAGS) -MMD -c $< -o $@
test :
@$(MAKE) test -C g
diff --git a/mrbgems/g/hello_world/Makefile b/mrbgems/g/clib_example/Makefile
index c03910bf6..2cd523905 100644
--- a/mrbgems/g/hello_world/Makefile
+++ b/mrbgems/g/clib_example/Makefile
@@ -1,6 +1,6 @@
include ../../Makefile4gem
-GEM := hello_world
+GEM := clib_example
GEM_C_FILES := $(wildcard $(SRC_DIR)/*.c)
GEM_OBJECTS := $(patsubst %.c, %.o, $(GEM_C_FILES))
diff --git a/mrbgems/g/clib_example/README.md b/mrbgems/g/clib_example/README.md
new file mode 100644
index 000000000..289f6635d
--- /dev/null
+++ b/mrbgems/g/clib_example/README.md
@@ -0,0 +1,4 @@
+CLib Extension Example
+=========
+
+This is an example gem which implements a C extension.
diff --git a/mrbgems/g/clib_example/src/clib_example.c b/mrbgems/g/clib_example/src/clib_example.c
new file mode 100644
index 000000000..2ab8682b2
--- /dev/null
+++ b/mrbgems/g/clib_example/src/clib_example.c
@@ -0,0 +1,17 @@
+#include <mruby.h>
+#include <stdio.h>
+
+static struct RClass *_class_clib;
+
+static mrb_value
+mrb_clib_example(mrb_state *mrb, mrb_value self)
+{
+ puts("A C Extension");
+ return self;
+}
+
+void
+mrb_clib_example_gem_init(mrb_state* mrb) {
+ _class_clib = mrb_define_module(mrb, "CLib");
+ mrb_define_class_method(mrb, _class_clib, "clib_method", mrb_clib_example, ARGS_NONE());
+}
diff --git a/mrbgems/g/clib_example/test/clib_example.rb b/mrbgems/g/clib_example/test/clib_example.rb
new file mode 100644
index 000000000..348b9271d
--- /dev/null
+++ b/mrbgems/g/clib_example/test/clib_example.rb
@@ -0,0 +1,3 @@
+assert('CLib Extension') do
+ CLib.respond_to? :clib_method
+end
diff --git a/mrbgems/g/hello_world/src/hello_world.c b/mrbgems/g/hello_world/src/hello_world.c
deleted file mode 100644
index 75d353542..000000000
--- a/mrbgems/g/hello_world/src/hello_world.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <mruby.h>
-#include <stdio.h>
-
-static struct RClass *_class_hw;
-
-static mrb_value
-mrb_hello_world(mrb_state *mrb, mrb_value self)
-{
- puts("Hello World");
- return self;
-}
-
-void
-mrb_hello_world_gem_init(mrb_state* mrb) {
- _class_hw = mrb_define_module(mrb, "HW");
- mrb_define_class_method(mrb, _class_hw, "say", mrb_hello_world, ARGS_NONE());
-}
diff --git a/mrbgems/g/hello_world/test/hello_world.rb b/mrbgems/g/hello_world/test/hello_world.rb
deleted file mode 100644
index 2d8c335db..000000000
--- a/mrbgems/g/hello_world/test/hello_world.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-assert('Hello World') do
- HW.respond_to? :say
-end
diff --git a/mrbgems/g/mrblib_example/Makefile b/mrbgems/g/mrblib_example/Makefile
new file mode 100644
index 000000000..a43677842
--- /dev/null
+++ b/mrbgems/g/mrblib_example/Makefile
@@ -0,0 +1,7 @@
+include ../../Makefile4gem
+
+GEM := mrblib_example
+
+gem-all :
+
+gem-clean :
diff --git a/mrbgems/g/hello_world/README.md b/mrbgems/g/mrblib_example/README.md
index 42792567f..42792567f 100644
--- a/mrbgems/g/hello_world/README.md
+++ b/mrbgems/g/mrblib_example/README.md
diff --git a/mrbgems/g/mrblib_example/mrblib/mrblib_example.rb b/mrbgems/g/mrblib_example/mrblib/mrblib_example.rb
new file mode 100644
index 000000000..444f32236
--- /dev/null
+++ b/mrbgems/g/mrblib_example/mrblib/mrblib_example.rb
@@ -0,0 +1,5 @@
+class MRBLib
+ def MRBLib.mrblib_method
+ puts "A Ruby Extension"
+ end
+end
diff --git a/mrbgems/g/mrblib_example/test/mrblib_example.rb b/mrbgems/g/mrblib_example/test/mrblib_example.rb
new file mode 100644
index 000000000..40189ffdd
--- /dev/null
+++ b/mrbgems/g/mrblib_example/test/mrblib_example.rb
@@ -0,0 +1,3 @@
+assert('MRBLib extension') do
+ MRBLib.respond_to? :mrblib_method
+end
diff --git a/mrbgems/gem_helper.c b/mrbgems/gem_helper.c
index dd19ea2d0..24b959df9 100644
--- a/mrbgems/gem_helper.c
+++ b/mrbgems/gem_helper.c
@@ -1,22 +1,61 @@
#include <string.h>
#include <stdio.h>
#include <dirent.h>
+#include <unistd.h>
+#include <sys/types.h>
#include <sys/stat.h>
-
+#include <mrbconf.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
+ * skip_if_src_not_exist:
+ * TRUE => skip template for GEMs with SRC directory
+ * FALSE => template for all GEMs
+ *
+ */
void
-dir_list (char before[1024], char after[1024], char start[1024], char end[1024])
+for_each_gem (char before[1024], char after[1024],
+ char start[1024], char end[1024],
+ char dir_to_skip[1024])
{
struct dirent **eps;
int n;
char gemname[1024] = "";
char gemname_path[4096] = "";
char complete_line[4096] = "";
+ char src_path[4096] = "";
struct stat attribut;
strcat(complete_line, start);
@@ -28,6 +67,8 @@ dir_list (char before[1024], char after[1024], char start[1024], char end[1024])
strcpy(gemname, eps[cnt]->d_name);
strcpy(gemname_path, "./g/");
strcat(gemname_path, gemname);
+ strcpy(src_path, gemname_path);
+ strcat(src_path, "/src");
if (strcmp(gemname, ".") == 0)
continue;
@@ -35,13 +76,22 @@ dir_list (char before[1024], char after[1024], char start[1024], char end[1024])
continue;
stat(gemname_path, &attribut);
- if (S_ISDIR(attribut.st_mode) == 0)
+ if (S_ISDIR(attribut.st_mode) == 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 {
@@ -65,8 +115,28 @@ make_gem_makefile()
puts("");
puts(".PHONY : all");
- puts("all :");
- dir_list("\t@$(MAKE) -C ", " $(MAKE_FLAGS)\n", "", "");
+ puts("all : all_gems mrblib_gem.o");
+ puts("\t$(AR) rs ../../lib/libmruby.a mrblib_gem.o");
+ puts("");
+
+ puts("all_gems :");
+ for_each_gem("\t@$(MAKE) -C ", " $(MAKE_FLAGS)\n", "", "", "");
+ puts("");
+
+ puts("mrblib_gem.o : mrblib_gem.c");
+ puts("");
+
+ puts("mrblib_gem.c : mrblib_gem.ctmp");
+ puts("\tcat $< > $@");
+ puts("");
+
+ puts("mrblib_gem.ctmp : mrblib_gem.rbtmp");
+ puts("\t../../bin/mrbc -Bmrblib_gem_irep -o$@ $<");
+ puts("");
+
+ puts("mrblib_gem.rbtmp :");
+ for_each_gem(" ", "/mrblib/*.rb", "\tcat", "> mrblib_gem.rbtmp", "mrblib");
+ puts("");
puts(".PHONY : test");
puts("test : mrbtest");
@@ -93,13 +163,13 @@ make_gem_makefile()
puts("");
puts("mrbtest.rbtmp :");
- dir_list("", "/test/*.rb ", "\tcat ../../test/assert.rb ", "> mrbtest.rbtmp");
+ for_each_gem("", "/test/*.rb ", "\tcat ../../test/assert.rb ", "> mrbtest.rbtmp", "");
puts("");
puts(".PHONY : clean");
puts("clean :");
puts("\t$(RM) *.c *.d *.rbtmp *.ctmp *.o mrbtest");
- dir_list("\t@$(MAKE) clean -C ", " $(MAKE_FLAGS)\n", "", "");
+ for_each_gem("\t@$(MAKE) clean -C ", " $(MAKE_FLAGS)\n", "", "", "");
}
void
@@ -117,14 +187,28 @@ make_init_gems()
puts("");
puts("#include \"mruby.h\"");
+ puts("#include \"mruby/irep.h\"");
+ puts("#include \"mruby/dump.h\"");
+ puts("#include \"mruby/string.h\"");
+ puts("#include \"mruby/proc.h\"");
puts("");
- dir_list("void mrb_", "_gem_init(mrb_state*);\n", "", "");
+ for_each_gem("void mrb_", "_gem_init(mrb_state*);\n", "", "", "src");
+
+ puts("extern const char mrblib_gem_irep[];");
+ puts("");
puts("void");
- puts("mrb_init_mrbgems(mrb_state *mrb)");
- puts("{");
- dir_list(" mrb_", "_gem_init(mrb);\n", "", "");
+ puts("mrb_init_mrbgems(mrb_state *mrb) {");
+
+ for_each_gem(" mrb_", "_gem_init(mrb);\n", "", "", "src");
+
+ puts(" int n = mrb_read_irep(mrb, mrblib_gem_irep);");
+ puts(" mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));");
+ puts(" if (mrb->exc) {");
+ puts(" mrb_p(mrb, mrb_obj_value(mrb->exc));");
+ puts(" exit(0);");
+ puts(" }");
puts("}");
}