summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/compile/README.md212
-rw-r--r--doc/mrbgems/README.md45
-rw-r--r--src/class.c43
-rw-r--r--tasks/libmruby.rake2
-rw-r--r--tasks/mruby_gem_spec.rake10
-rw-r--r--tasks/rules.rake2
-rw-r--r--test/t/module.rb24
7 files changed, 310 insertions, 28 deletions
diff --git a/doc/compile/README.md b/doc/compile/README.md
new file mode 100644
index 000000000..e68c0d6f1
--- /dev/null
+++ b/doc/compile/README.md
@@ -0,0 +1,212 @@
+# Compile
+
+mruby is using Rake to compile and cross-compile all libraries and
+binaries.
+
+## Prerequisites
+
+To compile mruby out of the source code you need the following tools:
+* C Compiler (i.e. ```gcc```)
+* Linker (i.e. ```gcc```)
+* Archive utility (i.e. ```ar```)
+* Parser generator (i.e. ```bison```)
+* Ruby 1.8 or 1.9
+
+Optional:
+* GIT (to update mruby source and integrate mrbgems easier)
+* C++ compiler (to use GEMs which include *.cpp)
+* Assembler (to use GEMs which include *.asm)
+
+## Usage
+
+Inside of the root directory of the mruby source exist a file
+called *build_config.rb*. This file contains the build configuration
+of mruby and looks like this for example:
+
+```
+MRuby::Build.new do |conf|
+ conf.cc = ENV['CC'] || 'gcc'
+ conf.ld = ENV['LD'] || 'gcc'
+ conf.ar = ENV['AR'] || 'ar'
+
+ conf.cflags << (ENV['CFLAGS'] || %w(-g -O3 -Wall -Werror-implicit-function-declaration))
+ conf.ldflags << (ENV['LDFLAGS'] || %w(-lm))
+end
+```
+
+All tools necessary to compile mruby can be set or modified here.
+The following options can be configurated:
+
+* conf.cc (C compiler)
+* conf.ld (Linker)
+* conf.ar (Archive utility)
+* conf.cxx (C++ compiler)
+* conf.objcc (Object compiler)
+* conf.asm (Assembler)
+* conf.yacc (Parser Generator)
+* conf.gperf (Hash function Generator)
+* conf.cat (Concatenate utility)
+* conf.git (GIT content tracker)
+* conf.cflags (C compiler flags)
+* conf.ldflags (Linker flags)
+* conf.cxxflags (C++ compiler flags)
+* conf.objccflags (Object compiler flags)
+* conf.asmflags (Assembler flags)
+* conf.gem (A GEM which should be integrated - can be set several times)
+
+To compile just call ```./minirake``` inside of the mruby source root. To
+generate the test tool environment call ```./minirake test```. To clean
+all build files call ```./minirake clean```.
+
+### Cross-Compilation
+
+mruby can also be cross-compiled from one platform to another. To
+achive this the *build_config.rb* needs to contain an instance of
+```MRuby::CrossBuild```. This instance defines the compilation
+tools and flags for the target platform. An example could look
+like this for example:
+
+```
+MRuby::CrossBuild.new('i386') do |conf|
+ conf.cc = ENV['CC'] || 'gcc'
+ conf.ld = ENV['LD'] || 'gcc'
+ conf.ar = ENV['AR'] || 'ar'
+
+ if ENV['OS'] == 'Windows_NT' # MinGW
+ conf.cflags = %w(-g -O3 -Wall -Werror-implicit-function-declaration -Di386_MARK)
+ conf.ldflags = %w(-s -static)
+ else
+ conf.cflags << %w(-g -O3 -Wall -Werror-implicit-function-declaration -arch i386)
+ conf.ldflags << %w(-arch i386)
+ end
+end
+```
+
+You can configurate the same options as for a normal build.
+
+## Build process
+
+During the build process the directory *build* will be created. The
+directory structure will look like this:
+
+```
++- build
+ |
+ +- host
+ |
+ +- bin <- Binaries (mirb, mrbc and mruby)
+ |
+ +- lib <- Libraries (libmruby.a and libmruby_core.a)
+ |
+ +- mrblib
+ |
+ +- src
+ |
+ +- test <- mrbtest tool
+ |
+ +- tools
+ |
+ +- mirb
+ |
+ +- mrbc
+ |
+ +- mruby
+```
+
+The compilation workflow will look like this:
+* compile all files under *src* (object files will be stored
+in *build/host/src*
+* generate parser grammar out of *src/parse.y* (generated
+result will be stored in *build/host/src/y.tab.c*
+* compile *build/host/src/y.tab.c* to *build/host/src/y.tab.o*
+* create *build/host/lib/libmruby_core.a* out of all object files (C only)
+* create ```build/host/bin/mrbc``` by compile *tools/mrbc/mrbc.c* and
+link with *build/host/lib/libmruby_core.a*
+* create *build/host/mrblib/mrblib.c* by compiling all *.rb files
+under *mrblib* with ```build/host/bin/mrbc```
+* compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
+* create *build/host/lib/libmruby.a* out of all object files (C and Ruby)
+* create ```build/host/bin/mruby``` by compile *tools/mruby/mruby.c* and
+link with *build/host/lib/libmruby.a*
+* create ```build/host/bin/mirb``` by compile *tools/mirb/mirb.c* and
+link with *build/host/lib/libmruby.a*
+
+### Cross-Compilation
+
+In case of a cross-compilation to *i386* the *build* directory structure looks
+like this:
+
+```
++- build
+ |
+ +- host
+ | |
+ | +- bin <- Native Binaries
+ | |
+ | +- lib <- Native Libraries
+ | |
+ | +- mrblib
+ | |
+ | +- src
+ | |
+ | +- test <- Native mrbtest tool
+ | |
+ | +- tools
+ | |
+ | +- mirb
+ | |
+ | +- mrbc
+ | |
+ | +- mruby
+ +- i386
+ |
+ +- bin <- Cross-compiled Binaries
+ |
+ +- lib <- Cross-compiled Libraries
+ |
+ +- mrblib
+ |
+ +- src
+ |
+ +- test <- Cross-compiled mrbtest tool
+ |
+ +- tools
+ |
+ +- mirb
+ |
+ +- mrbc
+ |
+ +- mruby
+```
+
+An extra directory is created for the target platform. In case you
+compile for *i386* a directory called *i386* is created under the
+build direcotry.
+
+The cross compilation workflow starts in the same way as the normal
+compilation by compiling all *native* libraries and binaries.
+Aftwards the cross compilation process proceeds like this:
+* cross-compile all files under *src* (object files will be stored
+in *build/i386/src*
+* generate parser grammar out of *src/parse.y* (generated
+result will be stored in *build/i386/src/y.tab.c*
+* cross-compile *build/i386/src/y.tab.c* to *build/i386/src/y.tab.o*
+* create *build/i386/mrblib/mrblib.c* by compiling all *.rb files
+under *mrblib* with the native ```build/host/bin/mrbc```
+* cross-compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
+* create *build/i386/lib/libmruby.a* out of all object files (C and Ruby)
+* create ```build/i386/bin/mruby``` by cross-compile *tools/mruby/mruby.c* and
+link with *build/i386/lib/libmruby.a*
+* create ```build/i386/bin/mirb``` by cross-compile *tools/mirb/mirb.c* and
+link with *build/i386/lib/libmruby.a*
+* create *build/i386/lib/libmruby_core.a* out of all object files (C only)
+* create ```build/i386/bin/mrbc``` by cross-compile *tools/mrbc/mrbc.c* and
+link with *build/i386/lib/libmruby_core.a*
+
+## Test Environment
+
+mruby's build process includes a test environment. In case you start the testing
+of mruby, a native binary called ```mrbtest``` will be generated and executed.
+This binary contains all test cases which are defined under *test/t*. In case
+of a cross-compilation an additional cross-compiled *mrbtest* binary is
+generated. This binary you can copy and run on your target system.
diff --git a/doc/mrbgems/README.md b/doc/mrbgems/README.md
index 6d5a023bc..cc28f48f8 100644
--- a/doc/mrbgems/README.md
+++ b/doc/mrbgems/README.md
@@ -5,11 +5,11 @@ standardised way into mruby.
## Usage
-By default mrbgems is currently deactivated. As soon as you add a GEM to the
-build configuration (build_config.rb), mrbgems will be activated and the
-extension will be integrated.
+By default mrbgems is currently deactivated. As soon as you add a GEM to your
+build configuration (*build_config.rb*), mrbgems will be activated and the
+extension integrated.
-To add a GEM into the build_config.rb add the following line:
+To add a GEM into the build_config.rb add the following line for example:
```
conf.gem '/path/to/your/gem/dir'
@@ -49,14 +49,13 @@ The maximal GEM structure looks like this:
The folder *mrblib* contains pure Ruby files to extend mruby. The folder *src*
contains C files to extend mruby. The folder *test* contains C and pure Ruby files
for testing purposes which will be used by ```mrbtest```. *mrbgem.rake* contains
-rules to build a *libmrb-GEMNAME-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.
+the specification to compile C and Ruby files. *README.md* is a short description
+of your GEM.
## Build process
-mrbgems expects a file called *mrbgem.rake* inside of your GEM directory. A
-typical file could for example look like this:
+mrbgems expects a specifcation file called *mrbgem.rake* inside of your
+GEM direcotry. A typical GEM specification could look like this for example:
```
MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
@@ -65,35 +64,35 @@ MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
end
```
-The mrbgems build process will use this file to create a archive file
-*libmrb-GEMNAME-gem.a* during the build process. This file will be used
-by tools like *mruby* and *mirb* to integrate the GEM functionality.
+The mrbgems build process will use this specification to compile Object and Ruby
+files. The compilation results will be add to *lib/libmruby.a*. This file is used
+by tools like ```mruby``` and ```mirb``` to empower the GEM functionality.
-In case your GEM has more complex build requirements you can empower
+In case your GEM has more complex build requirements you can use
the following options additionally inside of your GEM specification:
-* spec.cflags (flags for the C compiler)
-* spec.mruby_cflags (flags for the C compiler)
-* spec.mruby_ldflags (flags for the linker)
-* spec.mruby_libs (Libraries to include)
-* spec.mruby_includes (Directories for include)
+* spec.cflags (C compiler flags for this GEM)
+* spec.mruby_cflags (global C compiler flags for everything)
+* spec.mruby_ldflags (global linker flags for everything)
+* spec.mruby_libs (global libraries for everything)
+* spec.mruby_includes (global includes for everything)
* spec.rbfiles (Ruby files to compile)
-* spec.objs
+* spec.objs (Object files to compile)
* spec.test_rbfiles (Ruby test files for integration into mrbtest)
-* spec.test_objs
+* spec.test_objs (Object test files for integration into mrbtest)
* spec.test_preload (Initialization files for mrbtest)
## C Extension
-mruby can be extended with C. It is possible by using the C API to
+mruby can be extended with C. This is possible by using the C API to
integrate C libraries into mruby.
### 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. If you call your GEM directory *c_extension_example*,
-your initialisation method could look like this:
+by the name of your GEM. If you call your GEM *c_extension_example*, your
+initialisation method could look like this:
```
void
diff --git a/src/class.c b/src/class.c
index ace34eb34..ea0db2bdc 100644
--- a/src/class.c
+++ b/src/class.c
@@ -1595,6 +1595,48 @@ mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod)
return mrb_nil_value();
}
+/* 15.2.2.4.34 */
+/*
+ * call-seq:
+ * mod.method_defined?(symbol) -> true or false
+ *
+ * Returns +true+ if the named method is defined by
+ * _mod_ (or its included modules and, if _mod_ is a class,
+ * its ancestors). Public and protected methods are matched.
+ *
+ * module A
+ * def method1() end
+ * end
+ * class B
+ * def method2() end
+ * end
+ * class C < B
+ * include A
+ * def method3() end
+ * end
+ *
+ * A.method_defined? :method1 #=> true
+ * C.method_defined? "method1" #=> true
+ * C.method_defined? "method2" #=> true
+ * C.method_defined? "method3" #=> true
+ * C.method_defined? "method4" #=> false
+ */
+
+static mrb_value
+mrb_mod_method_defined(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value sym;
+ mrb_sym id;
+
+ mrb_get_args(mrb, "o", &sym);
+ id = mrb_sym_value(mrb,sym);
+
+ if (mrb_obj_respond_to(mrb_class_ptr(mod), id)) {
+ return mrb_true_value();
+ }
+ return mrb_false_value();
+}
+
static void
remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid)
{
@@ -1750,6 +1792,7 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, mod, "included", mrb_bob_init, ARGS_REQ(1)); /* 15.2.2.4.29 */
mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, ARGS_NONE()); /* 15.2.2.4.30 */
mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, ARGS_ANY()); /* 15.2.2.4.33 */
+ mrb_define_method(mrb, mod, "method_defined?", mrb_mod_method_defined, ARGS_REQ(1)); /* 15.2.2.4.34 */
mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, ARGS_ANY()); /* 15.2.2.4.35 */
mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, ARGS_REQ(1)); /* 15.2.2.4.39 */
mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, ARGS_ANY()); /* 15.2.2.4.41 */
diff --git a/tasks/libmruby.rake b/tasks/libmruby.rake
index 5b785d208..1c68aa5e4 100644
--- a/tasks/libmruby.rake
+++ b/tasks/libmruby.rake
@@ -1,4 +1,4 @@
- MRuby.each_target do
+MRuby.each_target do
file "#{build_dir}/lib/libmruby.a" => libmruby.flatten do |t|
archive t.name, 'r', t.prerequisites
end
diff --git a/tasks/mruby_gem_spec.rake b/tasks/mruby_gem_spec.rake
index ae6d46b95..9f28b2b6a 100644
--- a/tasks/mruby_gem_spec.rake
+++ b/tasks/mruby_gem_spec.rake
@@ -33,7 +33,7 @@ module MRuby
@name = name
@build = MRuby.build
@dir = Gem.processing_path
- @cflags = []
+ @cflags, @cxxflags, @objcflags, @asmflags = [], [], [], []
@mruby_cflags, @mruby_ldflags, @mruby_libs = [], [], []
@mruby_includes = ["#{dir}/include"]
@rbfiles = Dir.glob("#{dir}/mrblib/*.rb")
@@ -113,9 +113,11 @@ __EOF__
obj_matcher = Regexp.new("^#{build_dir}/(.*)\\.o$")
{
'.c' => proc { |t| build.compile_c t.name, t.prerequisites.first, cflags },
- '.cpp' => proc { |t| build.compile_cxx t.name, t.prerequisites.first, cflags },
- '.m' => proc { |t| build.compile_objc t.name, t.prerequisites.first, cflags },
- '.S' => proc { |t| build.compile_asm t.name, t.prerequisites.first, cflags }
+ '.cpp' => proc { |t| build.compile_cxx t.name, t.prerequisites.first, cxxflags },
+ '.cxx' => proc { |t| build.compile_cxx t.name, t.prerequisites.first, cxxflags },
+ '.cc' => proc { |t| build.compile_cxx t.name, t.prerequisites.first, cxxflags },
+ '.m' => proc { |t| build.compile_objc t.name, t.prerequisites.first, objcflags },
+ '.S' => proc { |t| build.compile_asm t.name, t.prerequisites.first, asmflags }
}.each do |ext, compile|
rule obj_matcher => [
proc { |file|
diff --git a/tasks/rules.rake b/tasks/rules.rake
index f53f3bccd..7d988cde3 100644
--- a/tasks/rules.rake
+++ b/tasks/rules.rake
@@ -12,6 +12,8 @@ MRuby.each_target do |t|
{
'.c' => proc { |t| compile_c t.name, t.prerequisites.first },
'.cpp' => proc { |t| compile_cxx t.name, t.prerequisites.first },
+ '.cxx' => proc { |t| compile_cxx t.name, t.prerequisites.first },
+ '.cc' => proc { |t| compile_cxx t.name, t.prerequisites.first },
'.m' => proc { |t| compile_objc t.name, t.prerequisites.first },
'.S' => proc { |t| compile_asm t.name, t.prerequisites.first }
}.each do |ext, compile|
diff --git a/test/t/module.rb b/test/t/module.rb
index bf9626c2d..286c2c085 100644
--- a/test/t/module.rb
+++ b/test/t/module.rb
@@ -199,6 +199,30 @@ assert('Module#instance_methods', '15.2.2.4.33') do
r.class == Array and r.include?(:method3) and r.include?(:method2)
end
+assert('Module#method_defined?', '15.2.2.4.34') do
+ module Test4MethodDefined
+ module A
+ def method1() end
+ end
+
+ class B
+ def method2() end
+ end
+
+ class C < B
+ include A
+ def method3() end
+ end
+ end
+
+ Test4MethodDefined::A.method_defined? :method1 and
+ Test4MethodDefined::C.method_defined? :method1 and
+ Test4MethodDefined::C.method_defined? "method2" and
+ Test4MethodDefined::C.method_defined? "method3" and
+ not Test4MethodDefined::C.method_defined? "method4"
+end
+
+
assert('Module#module_eval', '15.2.2.4.35') do
module Test4ModuleEval
@a = 11