first commit
This commit is contained in:
+492
@@ -0,0 +1,492 @@
|
||||
# Compile
|
||||
|
||||
mruby uses 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 (e.g. `gcc` or `clang`)
|
||||
* Linker (e.g. `gcc` or `clang`)
|
||||
* Archive utility (e.g. `ar`)
|
||||
* Parser generator (e.g. `bison`)
|
||||
* Ruby 2.0 or later (e.g. `ruby` or `jruby`)
|
||||
|
||||
Note that `bison` bundled with MacOS is too old to compile `mruby`.
|
||||
Try `brew install bison` and follow the instuction shown to update
|
||||
the `$PATH` to compile `mruby`.
|
||||
|
||||
Optional:
|
||||
* GIT (to update mruby source and integrate mrbgems easier)
|
||||
* C++ compiler (to use GEMs which include \*.cpp, \*.cxx, \*.cc)
|
||||
* Assembler (to use GEMs which include \*.asm)
|
||||
|
||||
## Usage
|
||||
|
||||
Inside of the root directory of the mruby source a file exists
|
||||
called *build_config.rb*. This file contains the build configuration
|
||||
of mruby and looks like this for example:
|
||||
```ruby
|
||||
MRuby::Build.new do |conf|
|
||||
toolchain :gcc
|
||||
end
|
||||
```
|
||||
|
||||
All tools necessary to compile mruby can be set or modified here. In case
|
||||
you want to maintain an additional *build_config.rb* you can define a
|
||||
customized path using the *$MRUBY_CONFIG* environment variable.
|
||||
|
||||
To compile just call `rake` inside of the mruby source root. To
|
||||
generate and execute the test tools call `rake test`. To clean
|
||||
all build files call `rake clean`. To see full command line on
|
||||
build, call `rake -v`.
|
||||
|
||||
## Build Configuration
|
||||
|
||||
Inside of the *build_config.rb* the following options can be configured
|
||||
based on your environment.
|
||||
|
||||
### Toolchains
|
||||
|
||||
The mruby build system already contains a set of toolchain templates which
|
||||
configure the build environment for specific compiler infrastructures.
|
||||
|
||||
#### GCC
|
||||
|
||||
Toolchain configuration for the GNU C Compiler.
|
||||
```ruby
|
||||
toolchain :gcc
|
||||
```
|
||||
|
||||
#### clang
|
||||
|
||||
Toolchain configuration for the LLVM C Compiler clang. Mainly equal to the
|
||||
GCC toolchain.
|
||||
```ruby
|
||||
toolchain :clang
|
||||
```
|
||||
|
||||
#### Visual Studio 2010, 2012 and 2013
|
||||
|
||||
Toolchain configuration for Visual Studio on Windows. If you use the
|
||||
[Visual Studio Command Prompt](http://msdn.microsoft.com/en-us/library/ms229859\(v=vs.110\).aspx),
|
||||
you normally do not have to specify this manually, since it gets automatically detected by our build process.
|
||||
```ruby
|
||||
toolchain :visualcpp
|
||||
```
|
||||
|
||||
#### Android
|
||||
|
||||
Toolchain configuration for Android.
|
||||
```ruby
|
||||
toolchain :android
|
||||
```
|
||||
|
||||
Requires the custom standalone Android NDK and the toolchain path
|
||||
in `ANDROID_STANDALONE_TOOLCHAIN`.
|
||||
|
||||
### Binaries
|
||||
|
||||
It is possible to select which tools should be compiled during the compilation
|
||||
process. The following tools can be selected:
|
||||
* mruby (mruby interpreter)
|
||||
* mirb (mruby interactive shell)
|
||||
|
||||
To select them declare conf.gem as follows:
|
||||
```ruby
|
||||
conf.gem "#{root}/mrbgems/mruby-bin-mruby"
|
||||
conf.gem "#{root}/mrbgems/mruby-bin-mirb"
|
||||
```
|
||||
|
||||
### File Separator
|
||||
|
||||
Some environments require a different file separator character. It is possible to
|
||||
set the character via `conf.file_separator`.
|
||||
```ruby
|
||||
conf.file_separator = '/'
|
||||
```
|
||||
|
||||
### C Compiler
|
||||
|
||||
Configuration of the C compiler binary, flags and include paths.
|
||||
```ruby
|
||||
conf.cc do |cc|
|
||||
cc.command = ...
|
||||
cc.flags = ...
|
||||
cc.include_paths = ...
|
||||
cc.defines = ...
|
||||
cc.option_include_path = ...
|
||||
cc.option_define = ...
|
||||
cc.compile_options = ...
|
||||
end
|
||||
```
|
||||
|
||||
C Compiler has header searcher to detect installed library.
|
||||
|
||||
If you need a include path of header file use `search_header_path`:
|
||||
```ruby
|
||||
# Searches ```iconv.h```.
|
||||
# If found it will return include path of the header file.
|
||||
# Otherwise it will return nil .
|
||||
fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h'
|
||||
```
|
||||
|
||||
If you need a full file name of header file use `search_header`:
|
||||
```ruby
|
||||
# Searches ```iconv.h```.
|
||||
# If found it will return full path of the header file.
|
||||
# Otherwise it will return nil .
|
||||
iconv_h = conf.cc.search_header 'iconv.h'
|
||||
print "iconv.h found: #{iconv_h}\n"
|
||||
```
|
||||
|
||||
Header searcher uses compiler's `include_paths` by default.
|
||||
When you are using GCC toolchain (including clang toolchain since its base is gcc toolchain)
|
||||
it will use compiler specific include paths too. (For example `/usr/local/include`, `/usr/include`)
|
||||
|
||||
If you need a special header search paths define a singleton method `header_search_paths` to C compiler:
|
||||
```ruby
|
||||
def conf.cc.header_search_paths
|
||||
['/opt/local/include'] + include_paths
|
||||
end
|
||||
```
|
||||
|
||||
### Linker
|
||||
|
||||
Configuration of the Linker binary, flags and library paths.
|
||||
```ruby
|
||||
conf.linker do |linker|
|
||||
linker.command = ...
|
||||
linker.flags = ...
|
||||
linker.flags_before_libraries = ...
|
||||
linker.libraries = ...
|
||||
linker.flags_after_libraries = ...
|
||||
linker.library_paths = ....
|
||||
linker.option_library = ...
|
||||
linker.option_library_path = ...
|
||||
linker.link_options = ...
|
||||
end
|
||||
```
|
||||
|
||||
### Archiver
|
||||
|
||||
Configuration of the Archiver binary and flags.
|
||||
```ruby
|
||||
conf.archiver do |archiver|
|
||||
archiver.command = ...
|
||||
archiver.archive_options = ...
|
||||
end
|
||||
```
|
||||
|
||||
### Parser Generator
|
||||
|
||||
Configuration of the Parser Generator binary and flags.
|
||||
```ruby
|
||||
conf.yacc do |yacc|
|
||||
yacc.command = ...
|
||||
yacc.compile_options = ...
|
||||
end
|
||||
```
|
||||
|
||||
### GPerf
|
||||
|
||||
Configuration of the GPerf binary and flags.
|
||||
```ruby
|
||||
conf.gperf do |gperf|
|
||||
gperf.command = ...
|
||||
gperf.compile_options = ...
|
||||
end
|
||||
```
|
||||
|
||||
### File Extensions
|
||||
```ruby
|
||||
conf.exts do |exts|
|
||||
exts.object = ...
|
||||
exts.executable = ...
|
||||
exts.library = ...
|
||||
end
|
||||
```
|
||||
|
||||
### Mrbgems
|
||||
|
||||
Integrate GEMs in the build process.
|
||||
```ruby
|
||||
# Integrate GEM with additional configuration
|
||||
conf.gem 'path/to/gem' do |g|
|
||||
g.cc.flags << ...
|
||||
end
|
||||
|
||||
# Integrate GEM without additional configuration
|
||||
conf.gem 'path/to/another/gem'
|
||||
```
|
||||
|
||||
See doc/mrbgems/README.md for more option about mrbgems.
|
||||
|
||||
### Mrbtest
|
||||
|
||||
Configuration Mrbtest build process.
|
||||
|
||||
If you want mrbtest.a only, You should set `conf.build_mrbtest_lib_only`
|
||||
```ruby
|
||||
conf.build_mrbtest_lib_only
|
||||
```
|
||||
|
||||
### Bintest
|
||||
|
||||
Tests for mrbgem tools using CRuby.
|
||||
To have bintests place \*.rb scripts to `bintest/` directory of mrbgems.
|
||||
See `mruby-bin-*/bintest/*.rb` if you need examples.
|
||||
If you want a temporary files use `tempfile` module of CRuby instead of `/tmp/`.
|
||||
|
||||
You can enable it with following:
|
||||
```ruby
|
||||
conf.enable_bintest
|
||||
```
|
||||
|
||||
### C++ ABI
|
||||
|
||||
By default, mruby uses setjmp/longjmp to implement its
|
||||
exceptions. But it doesn't release C++ stack object
|
||||
correctly. To support mrbgems written in C++, mruby can be
|
||||
configured to use C++ exception.
|
||||
|
||||
There are two levels of C++ exception handling. The one is
|
||||
`enable_cxx_exception` that enables C++ exception, but
|
||||
uses C ABI. The other is `enable_cxx_abi` where all
|
||||
files are compiled by C++ compiler.
|
||||
|
||||
When you mix C++ code, C++ exception would be enabled automatically.
|
||||
If you need to enable C++ exception explicitly add the following:
|
||||
```ruby
|
||||
conf.enable_cxx_exception
|
||||
```
|
||||
|
||||
#### C++ exception disabling.
|
||||
|
||||
If your compiler does not support C++ and you want to ensure
|
||||
you don't use mrbgem written in C++, you can explicitly disable
|
||||
C++ exception, add following:
|
||||
```ruby
|
||||
conf.disable_cxx_exception
|
||||
```
|
||||
and you will get an error when you try to use C++ gem.
|
||||
Note that it must be called before `enable_cxx_exception` or `gem` method.
|
||||
|
||||
### Debugging mode
|
||||
|
||||
To enable debugging mode add the following:
|
||||
```ruby
|
||||
conf.enable_debug
|
||||
```
|
||||
|
||||
When debugging mode is enabled
|
||||
* Macro `MRB_DEBUG` would be defined.
|
||||
* Which means `mrb_assert()` macro is enabled.
|
||||
* Debug information of irep would be generated by `mrbc`.
|
||||
* Because `-g` flag would be added to `mrbc` runner.
|
||||
* You can have better backtrace of mruby scripts with this.
|
||||
|
||||
## Cross-Compilation
|
||||
|
||||
mruby can also be cross-compiled from one platform to another. To
|
||||
achieve 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:
|
||||
```ruby
|
||||
MRuby::CrossBuild.new('32bit') do |conf|
|
||||
toolchain :gcc
|
||||
|
||||
conf.cc.flags << "-m32"
|
||||
conf.linker.flags << "-m32"
|
||||
end
|
||||
```
|
||||
|
||||
All configuration options of `MRuby::Build` can also be used
|
||||
in `MRuby::CrossBuild`.
|
||||
|
||||
### Mrbtest in Cross-Compilation
|
||||
|
||||
In cross compilation, you can run `mrbtest` on emulator if
|
||||
you have it by changing configuration of test runner.
|
||||
```ruby
|
||||
conf.test_runner do |t|
|
||||
t.command = ... # set emulator. this value must be non nil or false
|
||||
t.flags = ... # set flags of emulator
|
||||
|
||||
def t.run(bin) # override `run` if you need to change the behavior of it
|
||||
... # `bin` is the full path of mrbtest
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Build process
|
||||
|
||||
During the build process the directory *build* will be created in the
|
||||
root directory. The structure of this directory 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 compiling *tools/mrbc/mrbc.c* and
|
||||
linking 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 compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
|
||||
linking with *build/host/lib/libmruby.a*
|
||||
* create `build/host/bin/mirb` by compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
|
||||
linking with *build/host/lib/libmruby.a*
|
||||
|
||||
```
|
||||
_____ _____ ______ ____ ____ _____ _____ ____
|
||||
| CC |->|GEN |->|AR |->|CC |->|CC |->|AR |->|CC |->|CC |
|
||||
| *.c | |y.tab| |core.a| |mrbc| |*.rb| |lib.a| |mruby| |mirb|
|
||||
----- ----- ------ ---- ---- ----- ----- ----
|
||||
```
|
||||
|
||||
### 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 directory.
|
||||
|
||||
The cross compilation workflow starts in the same way as the normal
|
||||
compilation by compiling all *native* libraries and binaries.
|
||||
Afterwards 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-compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
|
||||
linking with *build/i386/lib/libmruby.a*
|
||||
* create `build/i386/bin/mirb` by cross-compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
|
||||
linking 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-compiling *tools/mrbc/mrbc.c* and
|
||||
linking with *build/i386/lib/libmruby_core.a*
|
||||
|
||||
```
|
||||
_______________________________________________________________
|
||||
| Native Compilation for Host System |
|
||||
| _____ ______ _____ ____ ____ _____ |
|
||||
| | CC | -> |AR | -> |GEN | -> |CC | -> |CC | -> |AR | |
|
||||
| | *.c | |core.a| |y.tab| |mrbc| |*.rb| |lib.a| |
|
||||
| ----- ------ ----- ---- ---- ----- |
|
||||
---------------------------------------------------------------
|
||||
||
|
||||
\||/
|
||||
\/
|
||||
________________________________________________________________
|
||||
| Cross Compilation for Target System |
|
||||
| _____ _____ _____ ____ ______ _____ |
|
||||
| | CC | -> |AR | -> |CC | -> |CC | -> |AR | -> |CC | |
|
||||
| | *.c | |lib.a| |mruby| |mirb| |core.a| |mrbc | |
|
||||
| ----- ----- ----- ---- ------ ----- |
|
||||
----------------------------------------------------------------
|
||||
```
|
||||
|
||||
## Build Configuration Examples
|
||||
|
||||
### Minimal Library
|
||||
|
||||
To build a minimal mruby library you need to use the Cross Compiling
|
||||
feature due to the reason that there are functions (e.g. stdio) which
|
||||
can't be disabled for the main build.
|
||||
|
||||
```ruby
|
||||
MRuby::CrossBuild.new('Minimal') do |conf|
|
||||
toolchain :gcc
|
||||
|
||||
conf.cc.defines = %w(MRB_DISABLE_STDIO)
|
||||
conf.bins = []
|
||||
end
|
||||
```
|
||||
|
||||
This configuration defines a cross compile build called 'Minimal' which
|
||||
is using the GCC and compiles for the host machine. It also disables
|
||||
all usages of stdio and doesn't compile any binaries (e.g. mrbc).
|
||||
|
||||
## 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. You can copy this binary and run on your target system.
|
||||
+370
@@ -0,0 +1,370 @@
|
||||
# How to Use the mruby Debugger
|
||||
|
||||
copyright (c) 2014 Specified Non-Profit Corporation mruby Forum
|
||||
|
||||
## 1. Summary
|
||||
|
||||
This file documents the mruby debugger ('mrdb') methods.
|
||||
|
||||
## 2 Debugging with mrdb
|
||||
|
||||
## 2.1 Building mrdb
|
||||
|
||||
The trunk of the mruby source tree, with the most recent mrdb, can be checked out with the following command:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/mruby/mruby.git
|
||||
```
|
||||
|
||||
To run the `make` command:
|
||||
|
||||
```bash
|
||||
$ cd mruby
|
||||
$ make
|
||||
```
|
||||
|
||||
By default, the `make` command will install the debugger files into mruby/bin.
|
||||
|
||||
You can add the path for mrdb on your host environment with the following command:
|
||||
|
||||
```bash
|
||||
$ echo "export PATH=\$PATH:MRUBY_ROOT/bin" >> ~/.bashrc
|
||||
$ source ~/.bashrc
|
||||
```
|
||||
|
||||
`*MRUBY_ROOT` is the directory in which mruby source code will be installed.
|
||||
|
||||
To confirm mrdb was installed properly, run mrdb with the `--version` option:
|
||||
|
||||
```bash
|
||||
$ mrdb --version
|
||||
mruby 2.1.2 (2020-08-06)
|
||||
```
|
||||
|
||||
## 2.2 Basic Operation
|
||||
|
||||
### 2.2.1 Debugging mruby Script Files (rb file) with mrdb
|
||||
|
||||
To invoke the mruby debugger, just type `mrdb`.
|
||||
|
||||
To specify the script file:
|
||||
|
||||
```bash
|
||||
$ mrdb [option] file name
|
||||
```
|
||||
|
||||
For example: Debugging sample.rb
|
||||
|
||||
```bash
|
||||
$ mrdb sample.rb
|
||||
```
|
||||
|
||||
You can execute the shell commands listed below:
|
||||
|
||||
|command|description|
|
||||
|:-:|:--|
|
||||
|run|execute programs|
|
||||
|step|execute stepping|
|
||||
|continue|execute continuing program|
|
||||
|break|configure the breaking point|
|
||||
|delete|deleting the breaking points|
|
||||
|disable|disabling the breaking points|
|
||||
|enable|enabling the breaking points|
|
||||
|info breakpoints|showing list of the breaking points|
|
||||
|print|evaluating and printing the values of the mruby expressions in the script|
|
||||
|list|displaying the source cords|
|
||||
|help|showing help|
|
||||
|quit|terminating the mruby debugger|
|
||||
|
||||
### 2.2.2 Debugging mruby Binary Files (mrb file) with mrdb
|
||||
|
||||
You can debug the mruby binary files.
|
||||
|
||||
#### 2.2.2.1 Debugging the binary files
|
||||
|
||||
* notice
|
||||
To debug mruby binary files, you need to compile mruby files with option `-g`.
|
||||
|
||||
```bash
|
||||
$ mrbc -g sample.rb
|
||||
```
|
||||
|
||||
You can debug the mruby binary files with following command and the option `-b`.
|
||||
|
||||
```bash
|
||||
$ mrdb -b sample.mrb
|
||||
```
|
||||
|
||||
Then you can execute all debugger shell commands.
|
||||
|
||||
#### Break Command
|
||||
|
||||
You can use any breakpoint to stop the program by specifying the line number and method name.
|
||||
The breakpoint list will be displayed after you have set the breakpoint successfully.
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
break [file:]linenum
|
||||
b [file:]linenum
|
||||
break [class:]method
|
||||
b [class:]method
|
||||
```
|
||||
|
||||
The breakpoint will be ordered in serial from 1.
|
||||
The number, which was given to the deleted breakpoint, will never be given to another breakpoint again.
|
||||
|
||||
You can give multiple breakpoints to specified the line number and method.
|
||||
Be ware that breakpoint command will not check the validity of the class name and method name.
|
||||
|
||||
You can get the current breakpoint information by the following options.
|
||||
|
||||
breakpoint breakpoint number : file name. line number
|
||||
|
||||
breakpoint breakpoint number : [class name,] method name
|
||||
|
||||
#### Continue Command
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
continue [N]
|
||||
c [N]
|
||||
```
|
||||
|
||||
N: the next breakpoint number
|
||||
|
||||
When resuming the program, it will stop at breakpoint N (N-1 breakpoint will be ignored).
|
||||
|
||||
When you run the `continue` command without specifying N, the program will be stopped at the next breakpoint.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
(foo.rb:1) continue 3
|
||||
```
|
||||
|
||||
This will resume the program and stop it at the third breakpoint.
|
||||
|
||||
#### Delete Command
|
||||
|
||||
This will delete the specified breakpoint.
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
delete [breakpoint-no]
|
||||
d [breakpoint-no]
|
||||
```
|
||||
|
||||
breakpoint-no: breakpoint number
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
(foo.rb:1) delete
|
||||
```
|
||||
|
||||
This will delete all of the breakpoints.
|
||||
|
||||
```
|
||||
(foo.rb:1) delete 1 3
|
||||
```
|
||||
|
||||
This will delete the breakpoint at 1 and 3.
|
||||
|
||||
#### Disable Command
|
||||
|
||||
This will disable the specified breakpoint.
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
disable [breakpoint-no]
|
||||
dis [breakpoint-no]
|
||||
```
|
||||
|
||||
reappointing: breakpoint number
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
(foo.rb:1) disable
|
||||
```
|
||||
|
||||
Use `disable` if you would like to disable all of the breakpoints.
|
||||
|
||||
```
|
||||
(foo.rb:1) disable 1 3
|
||||
```
|
||||
|
||||
This will disable the breakpoints at 1 and 3.
|
||||
|
||||
#### Enable Command
|
||||
|
||||
This will enable the specified breakpoints.
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
enable [breakpoint-no]
|
||||
e [breakpoint-no]
|
||||
```
|
||||
|
||||
breakpoint-no: breakpoint number
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
(foo.rb:1) enable
|
||||
```
|
||||
|
||||
Enabling all breakpoints
|
||||
```
|
||||
(foo.rb:1) enable 1 3
|
||||
```
|
||||
|
||||
Enabling the breakpoint 1 and 3
|
||||
|
||||
#### eval command
|
||||
|
||||
Evaluating the string as source code and printing the value.
|
||||
|
||||
Same as print command, please see print command.
|
||||
|
||||
#### help command
|
||||
|
||||
Displaying the help message.
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
help [command]
|
||||
h [command]
|
||||
```
|
||||
|
||||
Typing `help` without any options will display the command list.
|
||||
|
||||
#### Info Breakpoints Command
|
||||
|
||||
Displaying the specified breakpoint information.
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
info breakpoints [breakpoint-no]
|
||||
i b [breakpoint-no]
|
||||
```
|
||||
|
||||
breakpoint-no: breakpoint number
|
||||
|
||||
Typing "info breakpoints" without ant option will display all breakpoint information.
|
||||
Example:
|
||||
|
||||
```
|
||||
(sample.rb:1) info breakpoints
|
||||
Num Type Enb What
|
||||
1 breakpoint y at sample.rb:3 -> file name,line number
|
||||
2 breakpoint n in Sample_class:sample_class_method -> [class:]method name
|
||||
3 breakpoint y in sample_global_method
|
||||
```
|
||||
|
||||
Displaying the specified breakpoint number:
|
||||
|
||||
```
|
||||
(foo.rb:1) info breakpoints 1 3
|
||||
Num Type Enb What
|
||||
1 breakpoint y at sample.rb:3
|
||||
3 breakpoint y in sample_global_method
|
||||
```
|
||||
|
||||
#### List Command
|
||||
|
||||
To display the code of the source file.
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
list [filename:]first[,last]
|
||||
l [filename]:first[,last]
|
||||
```
|
||||
|
||||
first: the opening row number
|
||||
last : the closing row number
|
||||
|
||||
When you specify the `first`, but not the `last` option, you will receive 10 rows.
|
||||
When you do not specify both the `first` and `last` options, you will receive the next 10 rows.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
Specifying file name and first row number
|
||||
sample.rb:1) list sample2.rb:5
|
||||
```
|
||||
|
||||
Specifying the file name and the first and last row number:
|
||||
|
||||
```
|
||||
(sample.rb:1) list sample2.rb:6,7
|
||||
```
|
||||
|
||||
#### Print Command
|
||||
|
||||
Evaluating the string as source code and printing the value.
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
print [expr]
|
||||
p [expr]
|
||||
```
|
||||
|
||||
expr: expression
|
||||
|
||||
The expression is mandatory.
|
||||
The displayed expressions will be serially ordered from 1.
|
||||
If an exception occurs, the exception information will be displayed and the debugging will be continued.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
(sample.rb:1) print 1+2
|
||||
$1 = 3
|
||||
(sample.rb:1) print self
|
||||
$2 = main
|
||||
```
|
||||
|
||||
Below is the case of the exception:
|
||||
|
||||
```
|
||||
(sample.rb:1) print (1+2
|
||||
$1 = SyntaxError: line 1: syntax error, unexpected $end, expecting ')'
|
||||
```
|
||||
|
||||
#### Quit Command
|
||||
|
||||
Quitting the debugger.
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
quit
|
||||
q
|
||||
```
|
||||
|
||||
#### Run Command
|
||||
|
||||
Running the program and stopping at the first breakpoint.
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
run
|
||||
r
|
||||
```
|
||||
|
||||
#### Step Command
|
||||
|
||||
This will run the program step by step.
|
||||
When the method and the block are invoked, the program will be stop at the first row.
|
||||
The program, which is developed in C, will be ignored.
|
||||
@@ -0,0 +1,177 @@
|
||||
# How to use `mrb_gc_arena_save()`/`mrb_gc_arena_restore()`/`mrb_gc_protect()`
|
||||
|
||||
_This is an English translation of [Matz's blog post][matz blog post]
|
||||
written in Japanese._
|
||||
_Some parts are updated to reflect recent changes._
|
||||
[matz blog post]: http://www.rubyist.net/~matz/20130731.html
|
||||
|
||||
When you are extending mruby using C language, you may encounter
|
||||
mysterious "arena overflow error" or memory leak or very slow
|
||||
execution speed. This is an error indicating overflow of "GC arena"
|
||||
implementing "conservative GC".
|
||||
|
||||
GC (garbage collector) must ensure that object is "alive", in other
|
||||
words, that it is referenced by somewhere from program. This can be
|
||||
determined by checking if the object can be directly or indirectly
|
||||
referenced by root. The local variables, global variables and
|
||||
constants etc are root.
|
||||
|
||||
If program execution is performed inside mruby VM, there is nothing to
|
||||
worry about because GC can access all roots owned by VM.
|
||||
|
||||
The problem arises when executing C functions. The object referenced
|
||||
by C variable is also "alive", but mruby GC cannot aware of this, so
|
||||
it might mistakenly recognize the objects referenced by only C
|
||||
variables as dead.
|
||||
|
||||
This can be a fatal bug if the GC tries to collect a live object.
|
||||
|
||||
In CRuby, we scan C stack area, and use C variable as root to check
|
||||
whether object is alive or not. Of course, because we are accessing C
|
||||
stack just as memory region, we never know it is an integer or a
|
||||
pointer. We workaround this by assuming that if it looks like a
|
||||
pointer, then assume it as a pointer. We call it "conservative".
|
||||
|
||||
By the way, CRuby's "conservative GC" has some problems.
|
||||
|
||||
The biggest problem is we have no way to access to the stack area in
|
||||
portable way. Therefore, we cannot use this method if we'd like to
|
||||
implement highly portable runtime, like mruby.
|
||||
|
||||
So we came up with an another plan to implement "conservative GC" in mruby.
|
||||
|
||||
Again, the problem is when an object which was created in C function, becomes
|
||||
no longer referenced in the Ruby world, and cannot be treated as garbage.
|
||||
|
||||
In mruby, we recognize all objects created in C function are alive.
|
||||
Then we have no problem such as confusing a live object as dead.
|
||||
|
||||
This means that because we cannot collect truly dead object, we may
|
||||
lose efficiency, but as a trade-off the GC itself is highly portable.
|
||||
We can say goodbye to the problem that GC deletes live objects due to
|
||||
optimization which sometimes occurs in CRuby.
|
||||
|
||||
According to this idea, we have a table, called "GC arena", which
|
||||
remembers objects created in C function.
|
||||
|
||||
The arena is stack structure, when C function execution is returned to mruby
|
||||
VM, all objects registered in the arena are popped.
|
||||
|
||||
This works very well, but can cause another problem: "arena overflow error" or
|
||||
memory leak.
|
||||
|
||||
As of this writing, mruby automatically extend arena to remember
|
||||
objects (See `MRB_GC_FIXED_ARENA` and `MRB_GC_ARENA_SIZE` in
|
||||
doc/guides/mrbconf.md).
|
||||
|
||||
If you create many objects in C functions, memory usage will increase, since
|
||||
GC never kick in. This memory usage may look like memory leak, but will also
|
||||
make execution slower as more memory will need to be allocated.
|
||||
|
||||
With the build time configuration, you can limit the maximum size of
|
||||
arena (e.g., 100). Then if you create many objects, arena overflows,
|
||||
thus you will get an "arena overflow error".
|
||||
|
||||
To workaround these problems, we have `mrb_gc_arena_save()` and
|
||||
`mrb_gc_arena_restore()` functions.
|
||||
|
||||
`int mrb_gc_arena_save(mrb)` returns the current position of the stack
|
||||
top of GC arena, and `void mrb_gc_arena_restore(mrb, idx)` sets the
|
||||
stack top position to back to given `idx`.
|
||||
|
||||
We can use them like this:
|
||||
|
||||
```c
|
||||
int arena_idx = mrb_gc_arena_save(mrb);
|
||||
|
||||
// ...create objects...
|
||||
mrb_gc_arena_restore(mrb, arena_idx);
|
||||
|
||||
```
|
||||
|
||||
In mruby, C function calls are surrounded by this save/restore, but we
|
||||
can further optimize memory usage by surrounding save/restore, and can
|
||||
avoid creating arena overflow bugs.
|
||||
|
||||
Let's take a real example. Here is the source code of `Array#inspect`:
|
||||
|
||||
```c
|
||||
static mrb_value
|
||||
inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
|
||||
{
|
||||
mrb_int i;
|
||||
mrb_value s, arystr;
|
||||
char head[] = { '[' };
|
||||
char sep[] = { ',', ' ' };
|
||||
char tail[] = { ']' };
|
||||
|
||||
/* check recursive */
|
||||
for(i=0; i<RARRAY_LEN(list); i++) {
|
||||
if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) {
|
||||
return mrb_str_new(mrb, "[...]", 5);
|
||||
}
|
||||
}
|
||||
|
||||
mrb_ary_push(mrb, list, ary);
|
||||
|
||||
arystr = mrb_str_new_capa(mrb, 64);
|
||||
mrb_str_cat(mrb, arystr, head, sizeof(head));
|
||||
|
||||
for(i=0; i<RARRAY_LEN(ary); i++) {
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
if (i > 0) {
|
||||
mrb_str_cat(mrb, arystr, sep, sizeof(sep));
|
||||
}
|
||||
if (mrb_array_p(RARRAY_PTR(ary)[i])) {
|
||||
s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list);
|
||||
}
|
||||
else {
|
||||
s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]);
|
||||
}
|
||||
mrb_str_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s));
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
}
|
||||
|
||||
mrb_str_cat(mrb, arystr, tail, sizeof(tail));
|
||||
mrb_ary_pop(mrb, list);
|
||||
|
||||
return arystr;
|
||||
}
|
||||
```
|
||||
|
||||
This is a real example, so a little bit complicated, but bear with me.
|
||||
The essence of `Array#inspect` is that after stringifying each element
|
||||
of array using `inspect` method, we join them together so that we can
|
||||
get `inspect` representation of the entire array.
|
||||
|
||||
After the `inspect` representation is created, we no longer require the
|
||||
individual string representation. This means that we don't have to register
|
||||
these temporal objects into GC arena.
|
||||
|
||||
Therefore, in order to keep the arena size small; the `ary_inspect()` function
|
||||
will do the following:
|
||||
|
||||
* save the position of the stack top using `mrb_gc_arena_save()`.
|
||||
* get `inspect` representation of each element.
|
||||
* append it to the constructing entire `inspect` representation of array.
|
||||
* restore stack top position using `mrb_gc_arena_restore()`.
|
||||
|
||||
Please note that the final `inspect` representation of entire array
|
||||
was created before the call of `mrb_gc_arena_restore()`. Otherwise,
|
||||
required temporal object may be deleted by GC.
|
||||
|
||||
We may have a usecase where after creating many temporal objects, we'd
|
||||
like to keep some of them. In this case, we cannot use the same idea
|
||||
in `ary_inspect()` like appending objects to existing one.
|
||||
Instead, after `mrb_gc_arena_restore()`, we must re-register the objects we
|
||||
want to keep in the arena using `mrb_gc_protect(mrb, obj)`.
|
||||
Use `mrb_gc_protect()` with caution because it could also lead to an "arena
|
||||
overflow error".
|
||||
|
||||
We must also mention that when `mrb_funcall` is called in top level, the return
|
||||
value is also registered to GC arena, so repeated use of `mrb_funcall` may
|
||||
eventually lead to an "arena overflow error".
|
||||
|
||||
Use `mrb_gc_arena_save()` and `mrb_gc_arena_restore()` or possible use of
|
||||
`mrb_gc_protect()` to workaround this.
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
# mruby configuration macros.
|
||||
|
||||
## How to use these macros.
|
||||
You can use mrbconfs with following ways:
|
||||
* Write them in `mrbconf.h`.
|
||||
* Using compiler flags is preferred when building a cross binaries or multiple mruby binaries
|
||||
since it's easier to use different mrbconf per each `MRuby::Build`.
|
||||
* Most flags can be enabled by just commenting in.
|
||||
* Pass them as compiler flags.
|
||||
* Make sure you pass the same flags to all compilers since some mrbconf(e.g., `MRB_GC_FIXED_ARENA`)
|
||||
changes `struct` layout and cause memory access error when C and other language(e.g., C++) is mixed.
|
||||
|
||||
## stdio setting.
|
||||
`MRB_DISABLE_STDIO`
|
||||
* When defined `<stdio.h>` functions won't be used.
|
||||
* Some features will be disabled when this is enabled:
|
||||
* `mrb_irep` load/dump from/to file.
|
||||
* Compiling mruby script from file.
|
||||
* Printing features in **src/print.c**.
|
||||
|
||||
## Debug macros.
|
||||
`MRB_ENABLE_DEBUG_HOOK`
|
||||
* When defined code fetch hook and debug OP hook will be enabled.
|
||||
* When using any of the hook set function pointer `code_fetch_hook` and/or `debug_op_hook` of `mrb_state`.
|
||||
* Fetch hook will be called before any OP.
|
||||
* Debug OP hook will be called when dispatching `OP_DEBUG`.
|
||||
|
||||
`MRB_DEBUG`
|
||||
* When defined `mrb_assert*` macro will be defined with macros from `<assert.h>`.
|
||||
* Could be enabled via `enable_debug` method of `MRuby::Build`.
|
||||
|
||||
## Stack configuration
|
||||
|
||||
`MRB_STACK_EXTEND_DOUBLING`
|
||||
* If defined doubles the stack size when extending it.
|
||||
* Else extends stack with `MRB_STACK_GROWTH`.
|
||||
|
||||
`MRB_STACK_GROWTH`
|
||||
* Default value is `128`.
|
||||
* Used in stack extending.
|
||||
* Ignored when `MRB_STACK_EXTEND_DOUBLING` is defined.
|
||||
|
||||
`MRB_STACK_MAX`
|
||||
* Default value is `0x40000 - MRB_STACK_GROWTH`.
|
||||
* Raises `RuntimeError` when stack size exceeds this value.
|
||||
|
||||
## Primitive type configuration.
|
||||
|
||||
`MRB_USE_FLOAT`
|
||||
* When defined single precision floating point type(C type `float`) is used as `mrb_float`.
|
||||
* Else double precision floating point type(C type `double`) is used as `mrb_float`.
|
||||
|
||||
`MRB_WITHOUT_FLOAT`
|
||||
* When defined removes floating point numbers from mruby.
|
||||
* It makes mruby easier to handle in "Microcontroller without FPU" and "Kernel Space".
|
||||
|
||||
`MRB_INT32`
|
||||
* When defined, or `MRB_INT64` are not defined on 32-bit CPU mode, `mrb_int` will be defined as `int32_t`.
|
||||
* Conflicts with `MRB_INT64`.
|
||||
|
||||
`MRB_INT64`
|
||||
* When defined, or `MRB_INT32` are not defined on 64-bit CPU mode, `mrb_int` will be defined as `int64_t`.
|
||||
* Conflicts with `MRB_INT32`.
|
||||
|
||||
## Garbage collector configuration.
|
||||
|
||||
`MRB_GC_STRESS`
|
||||
* When defined full GC is emitted per each `RBasic` allocation.
|
||||
* Mainly used in memory manager debugging.
|
||||
|
||||
`MRB_GC_TURN_OFF_GENERATIONAL`
|
||||
* When defined turns generational GC by default.
|
||||
|
||||
`MRB_GC_FIXED_ARENA`
|
||||
* When defined used fixed size GC arena.
|
||||
* Raises `RuntimeError` when this is defined and GC arena size exceeds `MRB_GC_ARENA_SIZE`.
|
||||
* Useful tracking unnecessary mruby object allocation.
|
||||
|
||||
`MRB_GC_ARENA_SIZE`
|
||||
* Default value is `100`.
|
||||
* Ignored when `MRB_GC_FIXED_ARENA` isn't defined.
|
||||
* Defines fixed GC arena size.
|
||||
|
||||
`MRB_HEAP_PAGE_SIZE`
|
||||
* Defines value is `1024`.
|
||||
* Specifies number of `RBasic` per each heap page.
|
||||
|
||||
## Memory pool configuration.
|
||||
|
||||
`POOL_ALIGNMENT`
|
||||
* Default value is `4`.
|
||||
* If you're allocating data types that requires alignment more than default value define the
|
||||
largest value of required alignment.
|
||||
|
||||
`POOL_PAGE_SIZE`
|
||||
* Default value is `16000`.
|
||||
* Specifies page size of pool page.
|
||||
* Smaller the value is increases memory overhead.
|
||||
|
||||
## State atexit configuration.
|
||||
|
||||
`MRB_FIXED_STATE_ATEXIT_STACK`
|
||||
* If defined enables fixed size `mrb_state` atexit stack.
|
||||
* Raises `RuntimeError` when `mrb_state_atexit` call count to same `mrb_state` exceeds
|
||||
`MRB_FIXED_STATE_ATEXIT_STACK_SIZE`'s value.
|
||||
|
||||
`MRB_FIXED_STATE_ATEXIT_STACK_SIZE`
|
||||
* Default value is `5`.
|
||||
* If `MRB_FIXED_STATE_ATEXIT_STACK` isn't defined this macro is ignored.
|
||||
|
||||
## `mrb_value` configuration.
|
||||
|
||||
`MRB_ENDIAN_BIG`
|
||||
* If defined compiles mruby for big endian machines.
|
||||
* Used in `MRB_NAN_BOXING`.
|
||||
* Some mrbgem use this mrbconf.
|
||||
|
||||
`MRB_NAN_BOXING`
|
||||
* If defined represent `mrb_value` in boxed `double`.
|
||||
* Conflicts with `MRB_USE_FLOAT` and `MRB_WITHOUT_FLOAT`.
|
||||
|
||||
`MRB_WORD_BOXING`
|
||||
* If defined represent `mrb_value` as a word.
|
||||
* If defined `Float` will be a mruby object with `RBasic`.
|
||||
|
||||
## Instance variable configuration.
|
||||
`MRB_IV_SEGMENT_SIZE`
|
||||
* Default value is `4`.
|
||||
* Specifies size of each segment in segment list.
|
||||
|
||||
## Reduce heap memory configuration.
|
||||
|
||||
`MRB_USE_LINK_TIME_RO_DATA_P`
|
||||
* Only available on ELF platforms.
|
||||
* If you specify the address of a read-only section when creating a symbol or string, that string will be used as it is.
|
||||
* Heap memory can be saved.
|
||||
* Uses `__ehdr_start` and `__init_array_start`.
|
||||
* It must be `__ehdr_start < data_addr < __init_array_start`.
|
||||
|
||||
`MRB_USE_CUSTOM_RO_DATA_P`
|
||||
* Takes precedence over `MRB_USE_LINK_TIME_RO_DATA_P`.
|
||||
* Please try if `MRB_USE_LINK_TIME_RO_DATA_P` is not available.
|
||||
* The `mrb_ro_data_p()` function is implemented by the user in an arbitrary file.
|
||||
* The prototype declaration is `mrb_bool mrb_ro_data_p(const char *ptr)`.
|
||||
* Return `TRUE` if `ptr` is in read-only section, otherwise return `FALSE`.
|
||||
|
||||
## Other configuration.
|
||||
`MRB_UTF8_STRING`
|
||||
* Adds UTF-8 encoding support to character-oriented String instance methods.
|
||||
* If it isn't defined, they only support the US-ASCII encoding.
|
||||
|
||||
`MRB_FUNCALL_ARGC_MAX`
|
||||
* Default value is `16`.
|
||||
* Specifies 4th argument(`argc`) max value of `mrb_funcall`.
|
||||
* Raises `ArgumentError` when the `argc` argument is bigger then this value `mrb_funcall`.
|
||||
|
||||
`KHASH_DEFAULT_SIZE`
|
||||
* Default value is `32`.
|
||||
* Specifies default size of khash table bucket.
|
||||
* Used in `kh_init_ ## name` function.
|
||||
|
||||
`MRB_STR_BUF_MIN_SIZE`
|
||||
* Default value is `128`.
|
||||
* Specifies initial capacity of `RString` created by `mrb_str_buf_new` function..
|
||||
|
||||
`MRB_METHOD_CACHE`
|
||||
* Improve performance for method dispatch.
|
||||
|
||||
`MRB_METHOD_CACHE_SIZE`
|
||||
* Default value is `128`.
|
||||
* Ignored if `MRB_METHOD_CACHE` is not defined.
|
||||
* Need to be the power of 2.
|
||||
|
||||
`MRB_METHOD_T_STRUCT`
|
||||
* Use C struct to represent `mrb_method_t`
|
||||
* No `MRB_METHOD_T_STRUCT` requires highest 2 bits of function pointers to be zero
|
||||
* Define this macro on machines that use higher bits of pointers
|
||||
|
||||
`MRB_ENABLE_ALL_SYMBOLS`
|
||||
* Make it available `Symbols.all_symbols` in `mrbgems/mruby-symbol-ext`
|
||||
* Increase heap memory usage.
|
||||
+350
@@ -0,0 +1,350 @@
|
||||
# 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 soon as you add a GEM to your
|
||||
build configuration (i.e. *build_config.rb*), mrbgems will be activated and the
|
||||
extension integrated.
|
||||
|
||||
To add a GEM into the *build_config.rb* add the following line for example:
|
||||
```ruby
|
||||
conf.gem '/path/to/your/gem/dir'
|
||||
```
|
||||
|
||||
You can also use a relative path which would be relative from the mruby root:
|
||||
```ruby
|
||||
conf.gem 'examples/mrbgems/ruby_extension_example'
|
||||
```
|
||||
|
||||
A remote GIT repository location for a GEM is also supported:
|
||||
```ruby
|
||||
conf.gem :git => 'https://github.com/masuidrive/mrbgems-example.git', :branch => 'master'
|
||||
conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master'
|
||||
conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master'
|
||||
```
|
||||
|
||||
You can specify the sub directory of the repository with `:path` option:
|
||||
```ruby
|
||||
conf.gem github: 'mruby/mruby', path: 'mrbgems/mruby-socket'
|
||||
```
|
||||
|
||||
To use mrbgem from [mgem-list](https://github.com/mruby/mgem-list) use `:mgem` option:
|
||||
```ruby
|
||||
conf.gem :mgem => 'mruby-yaml'
|
||||
conf.gem :mgem => 'yaml' # 'mruby-' prefix could be omitted
|
||||
```
|
||||
|
||||
For specifying commit hash to checkout use `:checksum_hash` option:
|
||||
```ruby
|
||||
conf.gem mgem: 'mruby-redis', checksum_hash: '3446d19fc4a3f9697b5ddbf2a904f301c42f2f4e'
|
||||
```
|
||||
|
||||
If there is missing dependencies, mrbgem dependencies solver will reference
|
||||
mrbgem from core or mgem-list.
|
||||
|
||||
To pull all gems from remote GIT repository on build, call ```rake -p```,
|
||||
or ```rake --pull-gems```.
|
||||
|
||||
NOTE: `:bitbucket` option supports only git. Hg is unsupported in this version.
|
||||
|
||||
## GemBox
|
||||
|
||||
There are instances when you wish to add a collection of mrbgems into mruby at
|
||||
once, or be able to substitute mrbgems based on configuration, without having to
|
||||
add each gem to the *build_config.rb* file. A packaged collection of mrbgems
|
||||
is called a GemBox. A GemBox is a file that contains a list of mrbgems to load
|
||||
into mruby, in the same format as if you were adding them to *build_config.rb*
|
||||
via `config.gem`, but wrapped in an `MRuby::GemBox` object. GemBoxes are
|
||||
loaded into mruby via `config.gembox 'boxname'`.
|
||||
|
||||
Below we have created a GemBox containing *mruby-time* and *mrbgems-example*:
|
||||
```ruby
|
||||
MRuby::GemBox.new do |conf|
|
||||
conf.gem "#{root}/mrbgems/mruby-time"
|
||||
conf.gem :github => 'masuidrive/mrbgems-example'
|
||||
end
|
||||
```
|
||||
|
||||
As mentioned, the GemBox uses the same conventions as `MRuby::Build`. The GemBox
|
||||
must be saved with a *.gembox* extension inside the *mrbgems* directory to to be
|
||||
picked up by mruby.
|
||||
|
||||
To use this example GemBox, we save it as `custom.gembox` inside the *mrbgems*
|
||||
directory in mruby, and add the following to our *build_config.rb* file inside
|
||||
the build block:
|
||||
```ruby
|
||||
conf.gembox 'custom'
|
||||
```
|
||||
This will cause the *custom* GemBox to be read in during the build process,
|
||||
adding *mruby-time* and *mrbgems-example* to the build.
|
||||
|
||||
If you want, you can put GemBox outside of mruby directory. In that case you must
|
||||
specify an absolute path like below.
|
||||
```ruby
|
||||
conf.gembox "#{ENV["HOME"]}/mygemboxes/custom"
|
||||
```
|
||||
|
||||
There are two GemBoxes that ship with mruby: [default](../../mrbgems/default.gembox)
|
||||
and [full-core](../../mrbgems/full-core.gembox). The [default](../../mrbgems/default.gembox) GemBox
|
||||
contains several core components of mruby, and [full-core](../../mrbgems/full-core.gembox)
|
||||
contains every gem found in the *mrbgems* directory.
|
||||
|
||||
## GEM Structure
|
||||
|
||||
The maximal GEM structure looks like this:
|
||||
|
||||
+- GEM_NAME <- Name of GEM
|
||||
|
|
||||
+- include/ <- Header for Ruby extension (will exported)
|
||||
|
|
||||
+- mrblib/ <- Source for Ruby extension
|
||||
|
|
||||
+- src/ <- Source for C extension
|
||||
|
|
||||
+- test/ <- Test code (Ruby)
|
||||
|
|
||||
+- mrbgem.rake <- GEM Specification
|
||||
|
|
||||
+- README.md <- Readme for GEM
|
||||
|
||||
The folder *mrblib* contains pure Ruby files to extend mruby. The folder *src*
|
||||
contains C/C++ files to extend mruby. The folder *include* contains C/C++ header
|
||||
files. The folder *test* contains C/C++ and pure Ruby files for testing purposes
|
||||
which will be used by `mrbtest`. *mrbgem.rake* contains the specification
|
||||
to compile C and Ruby files. *README.md* is a short description of your GEM.
|
||||
|
||||
## Build process
|
||||
|
||||
mrbgems expects a specification file called *mrbgem.rake* inside of your
|
||||
GEM directory. A typical GEM specification could look like this for example:
|
||||
```ruby
|
||||
MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = 'Example mrbgem using C and ruby'
|
||||
end
|
||||
```
|
||||
|
||||
The mrbgems build process will use this specification to compile Object and Ruby
|
||||
files. The compilation results will be added to *lib/libmruby.a*. This file exposes
|
||||
the GEM functionality to tools like `mruby` and `mirb`.
|
||||
|
||||
The following properties can be set inside of your `MRuby::Gem::Specification` for
|
||||
information purpose:
|
||||
|
||||
* `spec.license` or `spec.licenses` (A single license or a list of them under which this GEM is licensed)
|
||||
* `spec.author` or `spec.authors` (Developer name or a list of them)
|
||||
* `spec.version` (Current version)
|
||||
* `spec.description` (Detailed description)
|
||||
* `spec.summary`
|
||||
* One line short description of mrbgem.
|
||||
* Printed in build summary of rake when set.
|
||||
* `spec.homepage` (Homepage)
|
||||
* `spec.requirements` (External requirements as information for user)
|
||||
|
||||
The `license` and `author` properties are required in every GEM!
|
||||
|
||||
In case your GEM is depending on other GEMs please use
|
||||
`spec.add_dependency(gem, *requirements[, default_get_info])` like:
|
||||
```ruby
|
||||
MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.author = 'mruby developers'
|
||||
|
||||
# Add GEM dependency mruby-parser.
|
||||
# The version must be between 1.0.0 and 1.5.2 .
|
||||
spec.add_dependency('mruby-parser', '>= 1.0.0', '<= 1.5.2')
|
||||
|
||||
# Use any version of mruby-uv from github.
|
||||
spec.add_dependency('mruby-uv', '>= 0.0.0', :github => 'mattn/mruby-uv')
|
||||
|
||||
# Use latest mruby-onig-regexp from github. (version requirements can be omitted)
|
||||
spec.add_dependency('mruby-onig-regexp', :github => 'mattn/mruby-onig-regexp')
|
||||
|
||||
# You can add extra mgems active only on test
|
||||
spec.add_test_dependency('mruby-process', :github => 'iij/mruby-process')
|
||||
end
|
||||
```
|
||||
|
||||
The version requirements and default gem information are optional.
|
||||
|
||||
Version requirement supports following operators:
|
||||
* '=': is equal
|
||||
* '!=': is not equal
|
||||
* '>': is greater
|
||||
* '<': is lesser
|
||||
* '>=': is equal or greater
|
||||
* '<=': is equal or lesser
|
||||
* '~>': is equal or greater and is lesser than the next major version
|
||||
* example 1: '~> 2.2.2' means '>= 2.2.2' and '< 2.3.0'
|
||||
* example 2: '~> 2.2' means '>= 2.2.0' and '< 3.0.0'
|
||||
|
||||
When more than one version requirements is passed, the dependency must satisfy all of it.
|
||||
|
||||
You can have default gem to use as dependency when it's not defined in *build_config.rb*.
|
||||
When the last argument of `add_dependency` call is `Hash`, it will be treated as default gem information.
|
||||
Its format is same as argument of method `MRuby::Build#gem`, expect that it can't be treated as path gem location.
|
||||
|
||||
When a special version of dependency is required,
|
||||
use `MRuby::Build#gem` in *build_config.rb* to override default gem.
|
||||
|
||||
If you have conflicting GEMs use the following method:
|
||||
* `spec.add_conflict(gem, *requirements)`
|
||||
* The `requirements` argument is same as in `add_dependency` method.
|
||||
|
||||
like following code:
|
||||
```ruby
|
||||
MRuby::Gem::Specification.new 'some-regexp-binding' do |spec|
|
||||
spec.license = 'BSD'
|
||||
spec.author = 'John Doe'
|
||||
|
||||
spec.add_conflict 'mruby-onig-regexp', '> 0.0.0'
|
||||
spec.add_conflict 'mruby-hs-regexp'
|
||||
spec.add_conflict 'mruby-pcre-regexp'
|
||||
spec.add_conflict 'mruby-regexp-pcre'
|
||||
end
|
||||
```
|
||||
|
||||
In case your GEM has more complex build requirements you can use
|
||||
the following options additionally inside of your GEM specification:
|
||||
|
||||
* `spec.cc.flags` (C compiler flags)
|
||||
* `spec.cc.defines` (C compiler defines)
|
||||
* `spec.cc.include_paths` (C compiler include paths)
|
||||
* `spec.linker.flags` (Linker flags)
|
||||
* `spec.linker.libraries` (Linker libraries)
|
||||
* `spec.linker.library_paths` (Linker additional library path)
|
||||
* `spec.bins` (Generate binary file)
|
||||
* `spec.rbfiles` (Ruby files to compile)
|
||||
* `spec.objs` (Object files to compile)
|
||||
* `spec.test_rbfiles` (Ruby test files for integration into mrbtest)
|
||||
* `spec.test_objs` (Object test files for integration into mrbtest)
|
||||
* `spec.test_preload` (Initialization files for mrbtest)
|
||||
|
||||
You also can use `spec.mruby.cc` and `spec.mruby.linker` to add extra global parameters for compiler and linker.
|
||||
|
||||
### include_paths and dependency
|
||||
|
||||
Your GEM can export include paths to another GEMs that depends on your GEM.
|
||||
By default, `/...absolute path.../{GEM_NAME}/include` will be exported.
|
||||
So it is recommended not to put GEM's local header files on include/.
|
||||
|
||||
These exports are retroactive.
|
||||
For example: when B depends to C and A depends to B, A will get include paths exported by C.
|
||||
|
||||
Exported include_paths are automatically appended to GEM local include_paths by rake.
|
||||
You can use `spec.export_include_paths` accessor if you want more complex build.
|
||||
|
||||
|
||||
## C Extension
|
||||
|
||||
mruby can be extended with C. This is possible by using the C API to
|
||||
integrate C libraries into mruby.
|
||||
|
||||
### Preconditions
|
||||
|
||||
mrbgems expects that you have implemented a C method called
|
||||
`mrb_YOURGEMNAME_gem_init(mrb_state)`. `YOURGEMNAME` will be replaced
|
||||
by the name of your GEM. If you call your GEM *c_extension_example*, your
|
||||
initialisation method could look like this:
|
||||
```C
|
||||
void
|
||||
mrb_c_extension_example_gem_init(mrb_state* mrb) {
|
||||
struct RClass *class_cextension = mrb_define_module(mrb, "CExtension");
|
||||
mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE());
|
||||
}
|
||||
```
|
||||
|
||||
### Finalize
|
||||
|
||||
mrbgems expects that you have implemented a C method called
|
||||
`mrb_YOURGEMNAME_gem_final(mrb_state)`. `YOURGEMNAME` will be replaced
|
||||
by the name of your GEM. If you call your GEM *c_extension_example*, your
|
||||
finalizer method could look like this:
|
||||
|
||||
```C
|
||||
void
|
||||
mrb_c_extension_example_gem_final(mrb_state* mrb) {
|
||||
free(someone);
|
||||
}
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
+- c_extension_example/
|
||||
|
|
||||
+- src/
|
||||
| |
|
||||
| +- example.c <- C extension source
|
||||
|
|
||||
+- test/
|
||||
| |
|
||||
| +- example.rb <- Test code for C extension
|
||||
|
|
||||
+- mrbgem.rake <- GEM specification
|
||||
|
|
||||
+- 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.
|
||||
|
||||
|
||||
### Pre-Conditions
|
||||
|
||||
none
|
||||
|
||||
### Example
|
||||
|
||||
+- ruby_extension_example/
|
||||
|
|
||||
+- mrblib/
|
||||
| |
|
||||
| +- example.rb <- Ruby extension source
|
||||
|
|
||||
+- test/
|
||||
| |
|
||||
| +- example.rb <- Test code for Ruby extension
|
||||
|
|
||||
+- mrbgem.rake <- GEM specification
|
||||
|
|
||||
+- 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.
|
||||
|
||||
mruby codes under *mrblib* directory would be executed after gem init C
|
||||
function is called. Make sure *mruby script* depends on *C code* and
|
||||
*C code* doesn't depend on *mruby script*.
|
||||
|
||||
### 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
|
||||
|
|
||||
+- mrbgem.rake <- GEM specification
|
||||
|
|
||||
+- README.md
|
||||
Reference in New Issue
Block a user