Commit d6f2f55b authored by Daniel Bovensiepen's avatar Daniel Bovensiepen

Add Support for Ruby Extensions, C Extensions and Test Integration

parent f93572c5
...@@ -17,29 +17,31 @@ export AR = ar ...@@ -17,29 +17,31 @@ export AR = ar
.PHONY : all .PHONY : all
all : $(INIT).o all_gems all : $(INIT).o all_gems
$(MMAKER_BIN) : $(MMAKER).o all_gems : g/Makefile
@echo "Build the generator which creates the driver and Gem Makefile" @echo "Build all gems"
$(LL) -o $@ $(CC_FLAGS) $< $(MAKE) -C g
$(MMAKER).o : $(MMAKER).c g/Makefile : $(MMAKER_BIN)
$(CC) $(CC_FLAGS) -MMD -c $< -o $@ @echo "Generate Gem Makefile"
$(MMAKER_BIN) makefile > $@
$(INIT).c : $(MMAKER_BIN) $(INIT).c : $(MMAKER_BIN)
@echo "Generate Gem driver" @echo "Generate Gem driver"
$(MMAKER_BIN) $(INIT) > $@ $(MMAKER_BIN) $(INIT) > $@
$(INIT).o : $(INIT).c $(INIT).o : $(INIT).c
@echo "Build the driver which initiailizes all gems" @echo "Build the driver which initializes all gems"
gcc $(CC_FLAGS) -c $< -o $@ $(CC) $(CC_FLAGS) -MMD -c $< -o $@
$(AR) rs $(LIBR) $@ $(AR) rs $(LIBR) $@
g/Makefile : # Generator
@echo "Generate Gem Makefile"
$(MMAKER_BIN) makefile > $@
all_gems : $(MMAKER_BIN) g/Makefile $(MMAKER_BIN) : $(MMAKER).o
@echo "Build all gems" @echo "Build the generator which creates the driver and Gem Makefile"
$(MAKE) -C g $(LL) -o $@ $(CC_FLAGS) $<
$(MMAKER).o : $(MMAKER).c
$(CC) $(CC_FLAGS) -MMD -c $< -o $@
test : test :
@$(MAKE) test -C g @$(MAKE) test -C g
......
include ../../Makefile4gem include ../../Makefile4gem
GEM := hello_world GEM := clib_example
GEM_C_FILES := $(wildcard $(SRC_DIR)/*.c) GEM_C_FILES := $(wildcard $(SRC_DIR)/*.c)
GEM_OBJECTS := $(patsubst %.c, %.o, $(GEM_C_FILES)) GEM_OBJECTS := $(patsubst %.c, %.o, $(GEM_C_FILES))
......
CLib Extension Example
=========
This is an example gem which implements a C extension.
#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());
}
assert('CLib Extension') do
CLib.respond_to? :clib_method
end
#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());
}
assert('Hello World') do
HW.respond_to? :say
end
include ../../Makefile4gem
GEM := mrblib_example
gem-all :
gem-clean :
class MRBLib
def MRBLib.mrblib_method
puts "A Ruby Extension"
end
end
assert('MRBLib extension') do
MRBLib.respond_to? :mrblib_method
end
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <dirent.h> #include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <mrbconf.h>
static int static int
one (const struct dirent *unused) one (const struct dirent *unused)
...@@ -9,14 +12,50 @@ one (const struct dirent *unused) ...@@ -9,14 +12,50 @@ one (const struct dirent *unused)
return 1; 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 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; struct dirent **eps;
int n; int n;
char gemname[1024] = ""; char gemname[1024] = "";
char gemname_path[4096] = ""; char gemname_path[4096] = "";
char complete_line[4096] = ""; char complete_line[4096] = "";
char src_path[4096] = "";
struct stat attribut; struct stat attribut;
strcat(complete_line, start); strcat(complete_line, start);
...@@ -28,6 +67,8 @@ dir_list (char before[1024], char after[1024], char start[1024], char end[1024]) ...@@ -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, eps[cnt]->d_name);
strcpy(gemname_path, "./g/"); strcpy(gemname_path, "./g/");
strcat(gemname_path, gemname); strcat(gemname_path, gemname);
strcpy(src_path, gemname_path);
strcat(src_path, "/src");
if (strcmp(gemname, ".") == 0) if (strcmp(gemname, ".") == 0)
continue; continue;
...@@ -35,13 +76,22 @@ dir_list (char before[1024], char after[1024], char start[1024], char end[1024]) ...@@ -35,13 +76,22 @@ dir_list (char before[1024], char after[1024], char start[1024], char end[1024])
continue; continue;
stat(gemname_path, &attribut); stat(gemname_path, &attribut);
if (S_ISDIR(attribut.st_mode) == 0) if (S_ISDIR(attribut.st_mode) == 0) {
continue; 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, before);
strcat(complete_line, gemname); strcat(complete_line, gemname);
strcat(complete_line, after); strcat(complete_line, after);
} }
} }
else { else {
...@@ -65,8 +115,28 @@ make_gem_makefile() ...@@ -65,8 +115,28 @@ make_gem_makefile()
puts(""); puts("");
puts(".PHONY : all"); puts(".PHONY : all");
puts("all :"); puts("all : all_gems mrblib_gem.o");
dir_list("\t@$(MAKE) -C ", " $(MAKE_FLAGS)\n", "", ""); 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(".PHONY : test");
puts("test : mrbtest"); puts("test : mrbtest");
...@@ -93,13 +163,13 @@ make_gem_makefile() ...@@ -93,13 +163,13 @@ make_gem_makefile()
puts(""); puts("");
puts("mrbtest.rbtmp :"); 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("");
puts(".PHONY : clean"); puts(".PHONY : clean");
puts("clean :"); puts("clean :");
puts("\t$(RM) *.c *.d *.rbtmp *.ctmp *.o mrbtest"); 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 void
...@@ -117,14 +187,28 @@ make_init_gems() ...@@ -117,14 +187,28 @@ make_init_gems()
puts(""); puts("");
puts("#include \"mruby.h\""); 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(""); 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("void");
puts("mrb_init_mrbgems(mrb_state *mrb)"); puts("mrb_init_mrbgems(mrb_state *mrb) {");
puts("{");
dir_list(" mrb_", "_gem_init(mrb);\n", "", ""); 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("}"); puts("}");
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment