Commit 4b50b1c2 authored by Daniel Bovensiepen's avatar Daniel Bovensiepen

Merge remote-tracking branch 'mruby/master'

parents d7668c5f fe954098
# 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.
...@@ -5,11 +5,11 @@ standardised way into mruby. ...@@ -5,11 +5,11 @@ standardised way into mruby.
## Usage ## Usage
By default mrbgems is currently deactivated. As soon as you add a GEM to the 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 build configuration (*build_config.rb*), mrbgems will be activated and the
extension will be integrated. 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' conf.gem '/path/to/your/gem/dir'
...@@ -49,14 +49,13 @@ The maximal GEM structure looks like this: ...@@ -49,14 +49,13 @@ The maximal GEM structure looks like this:
The folder *mrblib* contains pure Ruby files to extend mruby. The folder *src* 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 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 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 the specification to compile C and Ruby files. *README.md* is a short description
will be used for integration into the normal mruby build process. *README.md* of your GEM.
is a short description of your GEM.
## Build process ## Build process
mrbgems expects a file called *mrbgem.rake* inside of your GEM directory. A mrbgems expects a specifcation file called *mrbgem.rake* inside of your
typical file could for example look like this: GEM direcotry. A typical GEM specification could look like this for example:
``` ```
MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| 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| ...@@ -65,35 +64,35 @@ MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
end end
``` ```
The mrbgems build process will use this file to create a archive file The mrbgems build process will use this specification to compile Object and Ruby
*libmrb-GEMNAME-gem.a* during the build process. This file will be used files. The compilation results will be add to *lib/libmruby.a*. This file is used
by tools like *mruby* and *mirb* to integrate the GEM functionality. 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: the following options additionally inside of your GEM specification:
* spec.cflags (flags for the C compiler) * spec.cflags (C compiler flags for this GEM)
* spec.mruby_cflags (flags for the C compiler) * spec.mruby_cflags (global C compiler flags for everything)
* spec.mruby_ldflags (flags for the linker) * spec.mruby_ldflags (global linker flags for everything)
* spec.mruby_libs (Libraries to include) * spec.mruby_libs (global libraries for everything)
* spec.mruby_includes (Directories for include) * spec.mruby_includes (global includes for everything)
* spec.rbfiles (Ruby files to compile) * 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_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) * spec.test_preload (Initialization files for mrbtest)
## C Extension ## 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. integrate C libraries into mruby.
### Pre-Conditions ### Pre-Conditions
mrbgems expects that you have implemented a C method called mrbgems expects that you have implemented a C method called
```mrb_YOURGEMNAME_gem_init(mrb_state)```. ```YOURGEMNAME``` will be replaced ```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*, by the name of your GEM. If you call your GEM *c_extension_example*, your
your initialisation method could look like this: initialisation method could look like this:
``` ```
void void
......
...@@ -1595,6 +1595,48 @@ mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod) ...@@ -1595,6 +1595,48 @@ mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod)
return mrb_nil_value(); 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 static void
remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid) remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid)
{ {
...@@ -1750,6 +1792,7 @@ mrb_init_class(mrb_state *mrb) ...@@ -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", 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, "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, "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, "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_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 */ mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, ARGS_ANY()); /* 15.2.2.4.41 */
......
MRuby.each_target do MRuby.each_target do
file "#{build_dir}/lib/libmruby.a" => libmruby.flatten do |t| file "#{build_dir}/lib/libmruby.a" => libmruby.flatten do |t|
archive t.name, 'r', t.prerequisites archive t.name, 'r', t.prerequisites
end end
......
...@@ -33,7 +33,7 @@ module MRuby ...@@ -33,7 +33,7 @@ module MRuby
@name = name @name = name
@build = MRuby.build @build = MRuby.build
@dir = Gem.processing_path @dir = Gem.processing_path
@cflags = [] @cflags, @cxxflags, @objcflags, @asmflags = [], [], [], []
@mruby_cflags, @mruby_ldflags, @mruby_libs = [], [], [] @mruby_cflags, @mruby_ldflags, @mruby_libs = [], [], []
@mruby_includes = ["#{dir}/include"] @mruby_includes = ["#{dir}/include"]
@rbfiles = Dir.glob("#{dir}/mrblib/*.rb") @rbfiles = Dir.glob("#{dir}/mrblib/*.rb")
...@@ -113,9 +113,11 @@ __EOF__ ...@@ -113,9 +113,11 @@ __EOF__
obj_matcher = Regexp.new("^#{build_dir}/(.*)\\.o$") obj_matcher = Regexp.new("^#{build_dir}/(.*)\\.o$")
{ {
'.c' => proc { |t| build.compile_c t.name, t.prerequisites.first, cflags }, '.c' => proc { |t| build.compile_c t.name, t.prerequisites.first, cflags },
'.cpp' => proc { |t| build.compile_cxx t.name, t.prerequisites.first, cflags }, '.cpp' => proc { |t| build.compile_cxx t.name, t.prerequisites.first, cxxflags },
'.m' => proc { |t| build.compile_objc t.name, t.prerequisites.first, cflags }, '.cxx' => proc { |t| build.compile_cxx t.name, t.prerequisites.first, cxxflags },
'.S' => proc { |t| build.compile_asm t.name, t.prerequisites.first, cflags } '.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| }.each do |ext, compile|
rule obj_matcher => [ rule obj_matcher => [
proc { |file| proc { |file|
......
...@@ -12,6 +12,8 @@ MRuby.each_target do |t| ...@@ -12,6 +12,8 @@ MRuby.each_target do |t|
{ {
'.c' => proc { |t| compile_c t.name, t.prerequisites.first }, '.c' => proc { |t| compile_c t.name, t.prerequisites.first },
'.cpp' => proc { |t| compile_cxx 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 }, '.m' => proc { |t| compile_objc t.name, t.prerequisites.first },
'.S' => proc { |t| compile_asm t.name, t.prerequisites.first } '.S' => proc { |t| compile_asm t.name, t.prerequisites.first }
}.each do |ext, compile| }.each do |ext, compile|
......
...@@ -199,6 +199,30 @@ assert('Module#instance_methods', '15.2.2.4.33') do ...@@ -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) r.class == Array and r.include?(:method3) and r.include?(:method2)
end 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 assert('Module#module_eval', '15.2.2.4.35') do
module Test4ModuleEval module Test4ModuleEval
@a = 11 @a = 11
......
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