Merge pull request #479 from bovi/mrbgems

mrbgems
This commit is contained in:
Yukihiro "Matz" Matsumoto
2012-12-07 01:04:32 -08:00
28 changed files with 982 additions and 13 deletions
+6
View File
@@ -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
+23 -3
View File
@@ -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)
+179
View File
@@ -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
@@ -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
@@ -0,0 +1,4 @@
C and Ruby Extension Example
=========
This is an example gem which implements a C and Ruby extension.
@@ -0,0 +1,5 @@
class RubyExtension
def CRubyExtension.ruby_method
puts "A Ruby Extension"
end
end
@@ -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());
}
@@ -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
+10
View File
@@ -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
@@ -0,0 +1,4 @@
C Extension Example
=========
This is an example gem which implements a C extension.
@@ -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());
}
@@ -0,0 +1,3 @@
assert('C Extension Example') do
CExtension.respond_to? :c_method
end
@@ -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
@@ -0,0 +1,4 @@
Pure Ruby Extension Example
=========
This is an example gem which implements a pure Ruby extension.
@@ -0,0 +1,5 @@
class RubyExtension
def RubyExtension.ruby_method
puts "A Ruby Extension"
end
end
@@ -0,0 +1,3 @@
assert('Ruby Extension Example') do
RubyExtension.respond_to? :ruby_method
end
+1
View File
@@ -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 File
+76
View File
@@ -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
+91
View File
@@ -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"
+1
View File
@@ -0,0 +1 @@
!.gitignore
+420
View File
@@ -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;
}
+4 -1
View File
@@ -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
}
+29 -4
View File
@@ -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)
+4
View File
@@ -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);
+19 -1
View File
@@ -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)
+7
View File
@@ -225,3 +225,10 @@ void
mrb_init_mrblib(mrb_state *mrb)
{
}
#ifdef ENABLE_GEMS
void
mrb_init_mrbgems(mrb_state *mrb)
{
}
#endif
+22 -4
View File
@@ -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)